Warning: That file was not part of the compilation database. It may have many parsing errors.

1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the plugins of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qcorewlanengine.h"
41#include "../qnetworksession_impl.h"
42
43#include <QtNetwork/private/qnetworkconfiguration_p.h>
44
45#include <QtCore/qthread.h>
46#include <QtCore/qmutex.h>
47#include <QtCore/qcoreapplication.h>
48#include <QtCore/qstringlist.h>
49
50#include <QtCore/qdebug.h>
51
52#include <QDir>
53#ifndef QT_NO_BEARERMANAGEMENT
54
55extern "C" { // Otherwise it won't find CWKeychain* symbols at link time
56#import <CoreWLAN/CoreWLAN.h>
57}
58
59#include "private/qcore_mac_p.h"
60
61#include <net/if.h>
62#include <ifaddrs.h>
63
64@interface QT_MANGLE_NAMESPACE(QNSListener) : NSObject <CWEventDelegate>
65
66@property (assign) QCoreWlanEngine* engine;
67
68@end
69
70@implementation QT_MANGLE_NAMESPACE(QNSListener) {
71 NSNotificationCenter *notificationCenter;
72 CWWiFiClient *client;
73 QCoreWlanEngine *engine;
74 NSLock *locker;
75}
76
77- (instancetype)init
78{
79 if ((self = [super init])) {
80 [locker lock];
81 QMacAutoReleasePool pool;
82 notificationCenter = [NSNotificationCenter defaultCenter];
83 client = [CWWiFiClient sharedWiFiClient];
84 client.delegate = self;
85 [client startMonitoringEventWithType:CWEventTypePowerDidChange error:nil];
86 [locker unlock];
87 }
88 return self;
89}
90
91static QT_MANGLE_NAMESPACE(QNSListener) *listener = 0;
92
93-(void)dealloc
94{
95 client.delegate = nil;
96 listener = nil;
97 [super dealloc];
98}
99
100-(void)setEngine:(QCoreWlanEngine *)coreEngine
101{
102 [locker lock];
103 if(!engine)
104 engine = coreEngine;
105 [locker unlock];
106}
107
108-(QCoreWlanEngine *)engine
109{
110 return engine;
111}
112
113-(void)remove
114{
115 [locker lock];
116 [client stopMonitoringAllEventsAndReturnError:nil];
117 [locker unlock];
118}
119
120- (void)powerStateDidChangeForWiFiInterfaceWithName:(NSString *)interfaceName
121{
122 Q_UNUSED(interfaceName);
123 engine->requestUpdate();
124}
125@end
126
127
128QT_BEGIN_NAMESPACE
129
130void networkChangeCallback(SCDynamicStoreRef/* store*/, CFArrayRef changedKeys, void *info)
131{
132 for ( long i = 0; i < CFArrayGetCount(changedKeys); i++) {
133
134 QString changed = QString::fromCFString((CFStringRef)CFArrayGetValueAtIndex(changedKeys, i));
135 if( changed.contains("/Network/Global/IPv4")) {
136 QCoreWlanEngine* wlanEngine = static_cast<QCoreWlanEngine*>(info);
137 wlanEngine->requestUpdate();
138 }
139 }
140 return;
141}
142
143
144QScanThread::QScanThread(QObject *parent)
145 :QThread(parent)
146{
147}
148
149QScanThread::~QScanThread()
150{
151}
152
153void QScanThread::quit()
154{
155 wait();
156}
157
158void QScanThread::run()
159{
160 QMacAutoReleasePool pool;
161 QStringList found;
162 mutex.lock();
163 CWInterface *currentInterface = [[CWWiFiClient sharedWiFiClient]
164 interfaceWithName:interfaceName.toNSString()];
165 mutex.unlock();
166 const bool currentInterfaceServiceActive = currentInterface.serviceActive;
167
168 if (currentInterface.powerOn) {
169 NSError *err = nil;
170
171 NSSet* apSet = [currentInterface scanForNetworksWithName:nil error:&err];
172
173 if (!err) {
174 for (CWNetwork *apNetwork in apSet) {
175 const QString networkSsid = QString::fromNSString([apNetwork ssid]);
176 const QString id = QString::number(qHash(QLatin1String("corewlan:") + networkSsid));
177 found.append(id);
178
179 QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined;
180 bool known = isKnownSsid(networkSsid);
181 if (currentInterfaceServiceActive) {
182 if (networkSsid == QString::fromNSString([currentInterface ssid])) {
183 state = QNetworkConfiguration::Active;
184 }
185 }
186 if (state == QNetworkConfiguration::Undefined) {
187 if(known) {
188 state = QNetworkConfiguration::Discovered;
189 } else {
190 state = QNetworkConfiguration::Undefined;
191 }
192 }
193 QNetworkConfiguration::Purpose purpose = QNetworkConfiguration::UnknownPurpose;
194 if ([apNetwork supportsSecurity:kCWSecurityNone]) {
195 purpose = QNetworkConfiguration::PublicPurpose;
196 } else {
197 purpose = QNetworkConfiguration::PrivatePurpose;
198 }
199
200 found.append(foundNetwork(id, networkSsid, state, interfaceName, purpose));
201
202 }
203 }
204 }
205 // add known configurations that are not around.
206 for (auto i = userProfiles.cbegin(), end = userProfiles.cend(); i != end; ++i) {
207
208 QString networkName = i.key();
209 const QString id = QString::number(qHash(QLatin1String("corewlan:") + networkName));
210
211 if(!found.contains(id)) {
212 QString networkSsid = getSsidFromNetworkName(networkName);
213 const QString ssidId = QString::number(qHash(QLatin1String("corewlan:") + networkSsid));
214 QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined;
215 QString interfaceName;
216 if (!i.value().isEmpty())
217 interfaceName = i.value().last();
218
219 if (currentInterfaceServiceActive) {
220 if (networkSsid == QString::fromNSString([currentInterface ssid])) {
221 state = QNetworkConfiguration::Active;
222 }
223 }
224 if(state == QNetworkConfiguration::Undefined) {
225 if( userProfiles.contains(networkName)
226 && found.contains(ssidId)) {
227 state = QNetworkConfiguration::Discovered;
228 }
229 }
230
231 if(state == QNetworkConfiguration::Undefined) {
232 state = QNetworkConfiguration::Defined;
233 }
234
235 found.append(foundNetwork(id, networkName, state, interfaceName, QNetworkConfiguration::UnknownPurpose));
236 }
237 }
238 emit networksChanged();
239}
240
241QStringList QScanThread::foundNetwork(const QString &id, const QString &name, const QNetworkConfiguration::StateFlags state, const QString &interfaceName, const QNetworkConfiguration::Purpose purpose)
242{
243 QStringList found;
244 QMutexLocker locker(&mutex);
245 QNetworkConfigurationPrivate *ptr = new QNetworkConfigurationPrivate;
246
247 ptr->name = name;
248 ptr->isValid = true;
249 ptr->id = id;
250 ptr->state = state;
251 ptr->type = QNetworkConfiguration::InternetAccessPoint;
252 ptr->bearerType = QNetworkConfiguration::BearerWLAN;
253 ptr->purpose = purpose;
254
255 fetchedConfigurations.append( ptr);
256 configurationInterface.insert(ptr->id, interfaceName);
257
258 locker.unlock();
259 locker.relock();
260 found.append(id);
261 return found;
262}
263
264QList<QNetworkConfigurationPrivate *> QScanThread::getConfigurations()
265{
266 QMutexLocker locker(&mutex);
267 return qExchange(fetchedConfigurations, {});
268}
269
270void QScanThread::getUserConfigurations()
271{
272 QMutexLocker locker(&mutex);
273
274 QMacAutoReleasePool pool;
275 userProfiles.clear();
276
277 NSArray<NSString *> *wifiInterfaces = [CWWiFiClient interfaceNames];
278 for (NSString *ifName in wifiInterfaces) {
279
280 CWInterface *wifiInterface = [[CWWiFiClient sharedWiFiClient] interfaceWithName:ifName];
281
282 NSString *nsInterfaceName = wifiInterface.ssid;
283// add user configured system networks
284 SCDynamicStoreRef dynRef = SCDynamicStoreCreate(kCFAllocatorSystemDefault, (CFStringRef)@"Qt corewlan", nil, nil);
285 NSDictionary * airportPlist = (NSDictionary *)SCDynamicStoreCopyValue(dynRef, (CFStringRef)[NSString stringWithFormat:@"Setup:/Network/Interface/%@/AirPort", nsInterfaceName]);
286 CFRelease(dynRef);
287 if(airportPlist != nil) {
288 NSDictionary *prefNetDict = [airportPlist objectForKey:@"PreferredNetworks"];
289
290 NSArray<NSString *> *thisSsidarray = [prefNetDict valueForKey:@"SSID_STR"];
291 for (NSString *ssidkey in thisSsidarray) {
292 QString thisSsid = QString::fromNSString(ssidkey);
293 if(!userProfiles.contains(thisSsid)) {
294 QMap <QString,QString> map;
295 map.insert(thisSsid, QString::fromNSString(nsInterfaceName));
296 userProfiles.insert(thisSsid, map);
297 }
298 }
299 CFRelease(airportPlist);
300 }
301
302 // remembered networks
303 CWConfiguration *userConfig = [wifiInterface configuration];
304 NSOrderedSet *networkProfiles = [userConfig networkProfiles];
305 NSEnumerator *enumerator = [networkProfiles objectEnumerator];
306 CWNetworkProfile *wProfile;
307 while ((wProfile = [enumerator nextObject])) {
308 QString networkName = QString::fromNSString([wProfile ssid]);
309
310 if (!userProfiles.contains(networkName)) {
311 QMap<QString,QString> map;
312 map.insert(networkName, QString::fromNSString(nsInterfaceName));
313 userProfiles.insert(networkName, map);
314 }
315 }
316
317 // 802.1X user profiles
318 QString userProfilePath = QDir::homePath() + "/Library/Preferences/com.apple.eap.profiles.plist";
319 NSDictionary* eapDict = [[[NSDictionary alloc] initWithContentsOfFile:userProfilePath.toNSString()] autorelease];
320 if(eapDict != nil) {
321 NSString *profileStr= @"Profiles";
322 NSString *nameStr = @"UserDefinedName";
323 NSString *networkSsidStr = @"Wireless Network";
324 for (id profileKey in eapDict) {
325 if ([profileStr isEqualToString:profileKey]) {
326 NSDictionary *itemDict = [eapDict objectForKey:profileKey];
327 for (id itemKey in itemDict) {
328
329 NSInteger dictSize = [itemKey count];
330 id objects[dictSize];
331 id keys[dictSize];
332
333 [itemKey getObjects:objects andKeys:keys];
334 QString networkName;
335 QString ssid;
336 for (int i = 0; i < dictSize; i++) {
337 if([nameStr isEqualToString:keys[i]]) {
338 networkName = QString::fromNSString(objects[i]);
339 }
340 if ([networkSsidStr isEqualToString:keys[i]]) {
341 ssid = QString::fromNSString(objects[i]);
342 }
343 if (!userProfiles.contains(networkName)
344 && !ssid.isEmpty()) {
345 QMap<QString,QString> map;
346 map.insert(ssid, QString::fromNSString(nsInterfaceName));
347 userProfiles.insert(networkName, map);
348 }
349 }
350 }
351 }
352 }
353 }
354 }
355}
356
357QString QScanThread::getSsidFromNetworkName(const QString &name) const
358{
359 QMutexLocker locker(&mutex);
360
361 for (auto i = userProfiles.cbegin(), end = userProfiles.cend(); i != end; ++i) {
362 for (auto ij = i.value().cbegin(), end = i.value().cend(); ij != end; ++ij) {
363 const QString networkNameHash = QString::number(qHash(QLatin1String("corewlan:") +i.key()));
364 if(name == i.key() || name == networkNameHash) {
365 return ij.key();
366 }
367 }
368 }
369 return QString();
370}
371
372QString QScanThread::getNetworkNameFromSsid(const QString &ssid) const
373{
374 QMutexLocker locker(&mutex);
375
376 for (auto i = userProfiles.cbegin(), end = userProfiles.cend(); i != end; ++i) {
377 if (i.value().contains(ssid))
378 return i.key();
379 }
380 return QString();
381}
382
383bool QScanThread::isKnownSsid(const QString &ssid) const
384{
385 QMutexLocker locker(&mutex);
386
387 for (auto i = userProfiles.cbegin(), end = userProfiles.cend(); i != end; ++i) {
388 if (i.value().contains(ssid))
389 return true;
390 }
391 return false;
392}
393
394
395QCoreWlanEngine::QCoreWlanEngine(QObject *parent)
396: QBearerEngineImpl(parent), scanThread(0)
397{
398 scanThread = new QScanThread(this);
399 connect(scanThread, SIGNAL(networksChanged()),
400 this, SLOT(networksChanged()));
401}
402
403QCoreWlanEngine::~QCoreWlanEngine()
404{
405 scanThread->wait();
406
407 qDeleteAll(qExchange(foundConfigurations, {}));
408 [listener remove];
409 [listener release];
410}
411
412void QCoreWlanEngine::initialize()
413{
414 QMutexLocker locker(&mutex);
415 QMacAutoReleasePool pool;
416
417 if ([[CWWiFiClient interfaceNames] count] > 0 && !listener) {
418 listener = [[QT_MANGLE_NAMESPACE(QNSListener) alloc] init];
419 listener.engine = this;
420 hasWifi = true;
421 } else {
422 hasWifi = false;
423 }
424 storeSession = NULL;
425
426 startNetworkChangeLoop();
427}
428
429
430QString QCoreWlanEngine::getInterfaceFromId(const QString &id)
431{
432 QMutexLocker locker(&mutex);
433
434 return scanThread->configurationInterface.value(id);
435}
436
437bool QCoreWlanEngine::hasIdentifier(const QString &id)
438{
439 QMutexLocker locker(&mutex);
440
441 return scanThread->configurationInterface.contains(id);
442}
443
444void QCoreWlanEngine::connectToId(const QString &id)
445{
446 QMutexLocker locker(&mutex);
447 QMacAutoReleasePool pool;
448 QString interfaceString = getInterfaceFromId(id);
449
450 CWInterface *wifiInterface =
451 [[CWWiFiClient sharedWiFiClient] interfaceWithName:interfaceString.toNSString()];
452
453 if (wifiInterface.powerOn) {
454 NSError *err = nil;
455 QString wantedSsid;
456 QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
457
458 const QString idHash = QString::number(qHash(QLatin1String("corewlan:") + ptr->name));
459 const QString idHash2 = QString::number(qHash(QLatin1String("corewlan:") + scanThread->getNetworkNameFromSsid(ptr->name)));
460
461 QString wantedNetwork;
462 for (auto i = scanThread->userProfiles.cbegin(), end = scanThread->userProfiles.cend(); i != end; ++i) {
463 wantedNetwork = i.key();
464 const QString networkNameHash = QString::number(qHash(QLatin1String("corewlan:") + wantedNetwork));
465 if (id == networkNameHash) {
466 wantedSsid = scanThread->getSsidFromNetworkName(wantedNetwork);
467 break;
468 }
469 }
470
471 NSSet *scanSet = [wifiInterface scanForNetworksWithName:wantedSsid.toNSString() error:&err];
472
473 if(!err) {
474 for (CWNetwork *apNetwork in scanSet) {
475 NSData *ssidData = [apNetwork ssidData];
476 bool result = false;
477
478 SecIdentityRef identity = 0;
479 // Check first whether we require IEEE 802.1X authentication for the wanted SSID
480 if (CWKeychainCopyWiFiEAPIdentity(kCWKeychainDomainSystem, ssidData, &identity) == errSecSuccess) {
481 NSString *username = nil;
482 NSString *password = nil;
483 if (CWKeychainFindWiFiEAPUsernameAndPassword(kCWKeychainDomainSystem, ssidData, &username, &password) == errSecSuccess) {
484 result = [wifiInterface associateToEnterpriseNetwork:apNetwork
485 identity:identity username:(NSString *)username password:(NSString *)password
486 error:&err];
487 [username release];
488 [password release];
489 }
490 CFRelease(identity);
491 } else {
492 NSString *password = nil;
493 if (CWKeychainFindWiFiPassword(kCWKeychainDomainSystem, ssidData, &password) == errSecSuccess) {
494 result = [wifiInterface associateToNetwork:apNetwork password:(NSString *)password error:&err];
495 [password release];
496 }
497 }
498
499 if (!err) {
500 if (!result) {
501 emit connectionError(id, ConnectError);
502 } else {
503 return;
504 }
505 } else {
506 qDebug() <<"associate ERROR"<< QString::fromNSString([err localizedDescription ]);
507 }
508 } //end scan network
509 } else {
510 qDebug() <<"scan ERROR"<< QString::fromNSString([err localizedDescription ]);
511 }
512 emit connectionError(id, InterfaceLookupError);
513 }
514
515 locker.unlock();
516 emit connectionError(id, InterfaceLookupError);
517}
518
519void QCoreWlanEngine::disconnectFromId(const QString &id)
520{
521 QMutexLocker locker(&mutex);
522
523 QString interfaceString = getInterfaceFromId(id);
524 if (interfaceString.isEmpty()) {
525 locker.unlock();
526 emit connectionError(id, DisconnectionError);
527 return;
528 }
529 QMacAutoReleasePool pool;
530
531 CWInterface *wifiInterface =
532 [[CWWiFiClient sharedWiFiClient] interfaceWithName:interfaceString.toNSString()];
533 disconnectedInterfaceString = interfaceString;
534
535 [wifiInterface disassociate];
536
537 QTimer::singleShot(1000, this,SLOT(checkDisconnect()));
538}
539
540void QCoreWlanEngine::checkDisconnect()
541{
542 QMutexLocker locker(&mutex);
543 if (!disconnectedInterfaceString.isEmpty()) {
544 QMacAutoReleasePool pool;
545
546 CWInterface *wifiInterface = [[CWWiFiClient sharedWiFiClient]
547 interfaceWithName:disconnectedInterfaceString.toNSString()];
548
549 const QString networkSsid = QString::fromNSString([wifiInterface ssid]);
550 if (!networkSsid.isEmpty()) {
551 const QString id = QString::number(qHash(QLatin1String("corewlan:") + networkSsid));
552 locker.unlock();
553 emit connectionError(id, DisconnectionError);
554 locker.relock();
555 }
556 disconnectedInterfaceString.clear();
557 }
558}
559
560void QCoreWlanEngine::requestUpdate()
561{
562 scanThread->getUserConfigurations();
563 doRequestUpdate();
564}
565
566void QCoreWlanEngine::doRequestUpdate()
567{
568 QMutexLocker locker(&mutex);
569
570 QMacAutoReleasePool pool;
571
572 NSArray<NSString *> *wifiInterfaces = [CWWiFiClient interfaceNames];
573 for (NSString *ifName in wifiInterfaces) {
574 scanThread->interfaceName = QString::fromNSString(ifName);
575 scanThread->start();
576 }
577 locker.unlock();
578 if ([wifiInterfaces count] == 0)
579 networksChanged();
580}
581
582bool QCoreWlanEngine::isWifiReady(const QString &wifiDeviceName)
583{
584 QMutexLocker locker(&mutex);
585 bool haswifi = false;
586 if(hasWifi) {
587 QMacAutoReleasePool pool;
588 CWInterface *defaultInterface = [[CWWiFiClient sharedWiFiClient]
589 interfaceWithName:wifiDeviceName.toNSString()];
590 if (defaultInterface.powerOn) {
591 haswifi = true;
592 }
593 }
594 return haswifi;
595}
596
597
598QNetworkSession::State QCoreWlanEngine::sessionStateForId(const QString &id)
599{
600 QMutexLocker locker(&mutex);
601 QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
602
603 if (!ptr)
604 return QNetworkSession::Invalid;
605
606 if (!ptr->isValid) {
607 return QNetworkSession::Invalid;
608 } else if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
609 return QNetworkSession::Connected;
610 } else if ((ptr->state & QNetworkConfiguration::Discovered) ==
611 QNetworkConfiguration::Discovered) {
612 return QNetworkSession::Disconnected;
613 } else if ((ptr->state & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) {
614 return QNetworkSession::NotAvailable;
615 } else if ((ptr->state & QNetworkConfiguration::Undefined) ==
616 QNetworkConfiguration::Undefined) {
617 return QNetworkSession::NotAvailable;
618 }
619
620 return QNetworkSession::Invalid;
621}
622
623QNetworkConfigurationManager::Capabilities QCoreWlanEngine::capabilities() const
624{
625 return QNetworkConfigurationManager::ForcedRoaming;
626}
627
628void QCoreWlanEngine::startNetworkChangeLoop()
629{
630
631 SCDynamicStoreContext dynStoreContext = { 0, this/*(void *)storeSession*/, NULL, NULL, NULL };
632 storeSession = SCDynamicStoreCreate(NULL,
633 CFSTR("networkChangeCallback"),
634 networkChangeCallback,
635 &dynStoreContext);
636 if (!storeSession ) {
637 qWarning() << "could not open dynamic store: error:" << SCErrorString(SCError());
638 return;
639 }
640
641 CFMutableArrayRef notificationKeys;
642 notificationKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
643 CFMutableArrayRef patternsArray;
644 patternsArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
645
646 CFStringRef storeKey;
647 storeKey = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
648 kSCDynamicStoreDomainState,
649 kSCEntNetIPv4);
650 CFArrayAppendValue(notificationKeys, storeKey);
651 CFRelease(storeKey);
652
653 storeKey = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
654 kSCDynamicStoreDomainState,
655 kSCCompAnyRegex,
656 kSCEntNetIPv4);
657 CFArrayAppendValue(patternsArray, storeKey);
658 CFRelease(storeKey);
659
660 if (!SCDynamicStoreSetNotificationKeys(storeSession , notificationKeys, patternsArray)) {
661 qWarning() << "register notification error:"<< SCErrorString(SCError());
662 CFRelease(storeSession );
663 CFRelease(notificationKeys);
664 CFRelease(patternsArray);
665 return;
666 }
667 CFRelease(notificationKeys);
668 CFRelease(patternsArray);
669
670 runloopSource = SCDynamicStoreCreateRunLoopSource(NULL, storeSession , 0);
671 if (!runloopSource) {
672 qWarning() << "runloop source error:"<< SCErrorString(SCError());
673 CFRelease(storeSession );
674 return;
675 }
676
677 CFRunLoopAddSource(CFRunLoopGetCurrent(), runloopSource, kCFRunLoopDefaultMode);
678 return;
679}
680
681QNetworkSessionPrivate *QCoreWlanEngine::createSessionBackend()
682{
683 return new QNetworkSessionPrivateImpl;
684}
685
686QNetworkConfigurationPrivatePointer QCoreWlanEngine::defaultConfiguration()
687{
688 return QNetworkConfigurationPrivatePointer();
689}
690
691bool QCoreWlanEngine::requiresPolling() const
692{
693 return true;
694}
695
696void QCoreWlanEngine::networksChanged()
697{
698 QMutexLocker locker(&mutex);
699
700 QStringList previous = accessPointConfigurations.keys();
701
702 QList<QNetworkConfigurationPrivate *> foundConfigurations = scanThread->getConfigurations();
703 while (!foundConfigurations.isEmpty()) {
704 QNetworkConfigurationPrivate *cpPriv = foundConfigurations.takeFirst();
705
706 previous.removeAll(cpPriv->id);
707
708 if (accessPointConfigurations.contains(cpPriv->id)) {
709 QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(cpPriv->id);
710
711 bool changed = false;
712
713 ptr->mutex.lock();
714
715 if (ptr->isValid != cpPriv->isValid) {
716 ptr->isValid = cpPriv->isValid;
717 changed = true;
718 }
719
720 if (ptr->name != cpPriv->name) {
721 ptr->name = cpPriv->name;
722 changed = true;
723 }
724
725 if (ptr->bearerType != cpPriv->bearerType) {
726 ptr->bearerType = cpPriv->bearerType;
727 changed = true;
728 }
729
730 if (ptr->state != cpPriv->state) {
731 ptr->state = cpPriv->state;
732 changed = true;
733 }
734
735 ptr->mutex.unlock();
736
737 if (changed) {
738 locker.unlock();
739 emit configurationChanged(ptr);
740 locker.relock();
741 }
742
743 delete cpPriv;
744 } else {
745 QNetworkConfigurationPrivatePointer ptr(cpPriv);
746
747 accessPointConfigurations.insert(ptr->id, ptr);
748
749 locker.unlock();
750 emit configurationAdded(ptr);
751 locker.relock();
752 }
753 }
754
755 while (!previous.isEmpty()) {
756 QNetworkConfigurationPrivatePointer ptr =
757 accessPointConfigurations.take(previous.takeFirst());
758
759 locker.unlock();
760 emit configurationRemoved(ptr);
761 locker.relock();
762 }
763
764 locker.unlock();
765 emit updateCompleted();
766
767}
768
769quint64 QCoreWlanEngine::bytesWritten(const QString &id)
770{
771 QMutexLocker locker(&mutex);
772 const QString interfaceStr = getInterfaceFromId(id);
773 return getBytes(interfaceStr,false);
774}
775
776quint64 QCoreWlanEngine::bytesReceived(const QString &id)
777{
778 QMutexLocker locker(&mutex);
779 const QString interfaceStr = getInterfaceFromId(id);
780 return getBytes(interfaceStr,true);
781}
782
783quint64 QCoreWlanEngine::startTime(const QString &identifier)
784{
785 QMutexLocker locker(&mutex);
786 QMacAutoReleasePool pool;
787 quint64 timestamp = 0;
788
789 NSString *filePath = @"/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist";
790 NSDictionary* plistDict = [[[NSDictionary alloc] initWithContentsOfFile:filePath] autorelease];
791 if(plistDict == nil)
792 return timestamp;
793 NSString *input = @"KnownNetworks";
794 NSString *timeStampStr = @"_timeStamp";
795
796 NSString *ssidStr = @"SSID_STR";
797
798 for (id key in plistDict) {
799 if ([input isEqualToString:key]) {
800
801 NSDictionary *knownNetworksDict = [plistDict objectForKey:key];
802 if(knownNetworksDict == nil)
803 return timestamp;
804 for (id networkKey in knownNetworksDict) {
805 bool isFound = false;
806 NSDictionary *itemDict = [knownNetworksDict objectForKey:networkKey];
807 if(itemDict == nil)
808 return timestamp;
809 NSInteger dictSize = [itemDict count];
810 id objects[dictSize];
811 id keys[dictSize];
812
813 [itemDict getObjects:objects andKeys:keys];
814 bool ok = false;
815 for(int i = 0; i < dictSize; i++) {
816 if([ssidStr isEqualToString:keys[i]]) {
817 const QString ident = QString::number(qHash(QLatin1String("corewlan:") + QString::fromNSString(objects[i])));
818 if(ident == identifier) {
819 ok = true;
820 }
821 }
822 if(ok && [timeStampStr isEqualToString:keys[i]]) {
823 timestamp = (quint64)[objects[i] timeIntervalSince1970];
824 isFound = true;
825 break;
826 }
827 }
828 if(isFound)
829 break;
830 }
831 }
832 }
833 return timestamp;
834}
835
836quint64 QCoreWlanEngine::getBytes(const QString &interfaceName, bool b)
837{
838 struct ifaddrs *ifAddressList, *ifAddress;
839 struct if_data *if_data;
840
841 quint64 bytes = 0;
842 ifAddressList = nil;
843 if(getifaddrs(&ifAddressList) == 0) {
844 for(ifAddress = ifAddressList; ifAddress; ifAddress = ifAddress->ifa_next) {
845 if(interfaceName == ifAddress->ifa_name) {
846 if_data = (struct if_data*)ifAddress->ifa_data;
847 if(b) {
848 bytes = if_data->ifi_ibytes;
849 break;
850 } else {
851 bytes = if_data->ifi_obytes;
852 break;
853 }
854 }
855 }
856 freeifaddrs(ifAddressList);
857 }
858 return bytes;
859}
860
861QT_END_NAMESPACE
862
863#endif
864

Warning: That file was not part of the compilation database. It may have many parsing errors.