/**************************************************************************** ** ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the FOO module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage ** This file may be used under the terms of the GNU Lesser General Public ** License version 2.1 as published by the Free Software Foundation and ** appearing in the file LICENSE.LGPL included in the packaging of this ** file. Please review the following information to ensure the GNU Lesser ** General Public License version 2.1 requirements will be met: ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU General ** Public License version 3.0 as published by the Free Software Foundation ** and appearing in the file LICENSE.GPL included in the packaging of this ** file. Please review the following information to ensure the GNU General ** Public License version 3.0 requirements will be met: ** http://www.gnu.org/copyleft/gpl.html. ** ** Other Usage ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ /** * Some notes about the code: * * ** It is assumed that the system proxies are for url based requests * ie. HTTP/HTTPS based. * ** It is assumed that proxies don't use authentication. * ** It is assumed that there is no exceptions to proxy use (Symbian side * does have the field for it but it is not user modifiable by default). * ** There is no checking for protocol name. */ #include #ifndef QT_NO_NETWORKPROXY #include // CMDBSession #include // CCDIAPRecord, CCDProxiesRecord #include // KCDTIdIAPRecord, KCDTIdProxiesRecord #include #include #include using namespace CommsDat; QT_BEGIN_NAMESPACE class SymbianIapId { public: enum State{ NotValid, Valid }; Q_DECLARE_FLAGS(States, State) SymbianIapId() {} ~SymbianIapId() {} void setIapId(TUint32 iapId) { iapState |= Valid; id = iapId; } bool isValid() { return iapState == Valid; } TUint32 iapId() { return id; } private: QFlags iapState; TUint32 id; }; Q_DECLARE_OPERATORS_FOR_FLAGS(SymbianIapId::States) class SymbianProxyQuery { public: static QNetworkConfiguration findCurrentConfiguration(QNetworkConfigurationManager& configurationManager); static SymbianIapId getIapId(QNetworkConfigurationManager &configurationManager, const QNetworkProxyQuery &query); static CCDIAPRecord *getIapRecordLC(TUint32 aIAPId, CMDBSession &aDb); static CMDBRecordSet *prepareQueryLC(TUint32 serviceId, TDesC& serviceType); static QList proxyQueryL(TUint32 aIAPId, const QNetworkProxyQuery &query); }; QNetworkConfiguration SymbianProxyQuery::findCurrentConfiguration(QNetworkConfigurationManager& configurationManager) { QList activeConfigurations = configurationManager.allConfigurations( QNetworkConfiguration::Active); QNetworkConfiguration currentConfig; if (activeConfigurations.count() > 0) { currentConfig = activeConfigurations.at(0); } else { // No active configurations, try default one QNetworkConfiguration defaultConfiguration = configurationManager.defaultConfiguration(); if (defaultConfiguration.isValid()) { switch (defaultConfiguration.type()) { case QNetworkConfiguration::InternetAccessPoint: currentConfig = defaultConfiguration; break; case QNetworkConfiguration::ServiceNetwork: { // Note: This code assumes that the only unambigious way to // find current proxy config is if there is only one access point // or if the found access point is immediately usable. QList childConfigurations = defaultConfiguration.children(); if (childConfigurations.count() == 1) { currentConfig = childConfigurations.at(0); } else { for (int index = 0; index < childConfigurations.count(); index++) { QNetworkConfiguration childConfig = childConfigurations.at(index); if (childConfig.isValid() && childConfig.state() == QNetworkConfiguration::Discovered) { currentConfig = childConfig; break; } } } } break; case QNetworkConfiguration::UserChoice: // User choice is not a valid configuration for proxy discovery break; } } } return currentConfig; } SymbianIapId SymbianProxyQuery::getIapId(QNetworkConfigurationManager& configurationManager, const QNetworkProxyQuery &query) { SymbianIapId iapId; QNetworkConfiguration currentConfig = query.networkConfiguration(); if (!currentConfig.isValid()) { //If config is not specified, then try to find out an active or default one currentConfig = findCurrentConfiguration(configurationManager); } if (currentConfig.isValid()) { // Note: the following code assumes that the identifier is in format // I_xxxx where xxxx is the identifier of IAP. This is meant as a // temporary solution until there is a support for returning // implementation specific identifier. const int generalPartLength = 2; const int identifierNumberLength = currentConfig.identifier().length() - generalPartLength; QString idString(currentConfig.identifier().right(identifierNumberLength)); bool success; uint id = idString.toUInt(&success); if (success) iapId.setIapId(id); else qWarning() << "Failed to convert identifier to access point identifier: " << currentConfig.identifier(); } return iapId; } CCDIAPRecord *SymbianProxyQuery::getIapRecordLC(TUint32 aIAPId, CMDBSession &aDb) { CCDIAPRecord *iap = static_cast (CCDRecordBase::RecordFactoryL(KCDTIdIAPRecord)); CleanupStack::PushL(iap); iap->SetRecordId(aIAPId); iap->LoadL(aDb); return iap; } CMDBRecordSet *SymbianProxyQuery::prepareQueryLC(TUint32 serviceId, TDesC& serviceType) { // Create a recordset of type CCDProxiesRecord // for priming search. // This will ultimately contain record(s) // matching the priming record attributes CMDBRecordSet *proxyRecords = new (ELeave) CMDBRecordSet ( KCDTIdProxiesRecord); CleanupStack::PushL(proxyRecords); CCDProxiesRecord *primingProxyRecord = static_cast (CCDRecordBase::RecordFactoryL(KCDTIdProxiesRecord)); CleanupStack::PushL(primingProxyRecord); primingProxyRecord->iServiceType.SetMaxLengthL(serviceType.Length()); primingProxyRecord->iServiceType = serviceType; primingProxyRecord->iService = serviceId; primingProxyRecord->iUseProxyServer = ETrue; proxyRecords->iRecords.AppendL(primingProxyRecord); // Ownership of primingProxyRecord is transferred to // proxyRecords, just remove it from the CleanupStack CleanupStack::Pop(primingProxyRecord); return proxyRecords; } QList SymbianProxyQuery::proxyQueryL(TUint32 aIAPId, const QNetworkProxyQuery &query) { QList foundProxies; if (query.queryType() != QNetworkProxyQuery::UrlRequest) { return foundProxies; } CMDBSession *iDb = CMDBSession::NewLC(KCDVersion1_1); CCDIAPRecord *iap = getIapRecordLC(aIAPId, *iDb); // Read service table id and service type // from the IAP record found TUint32 serviceId = iap->iService; RBuf serviceType; serviceType.CreateL(iap->iServiceType); CleanupStack::PopAndDestroy(iap); CleanupClosePushL(serviceType); CMDBRecordSet *proxyRecords = prepareQueryLC(serviceId, serviceType); // Now to find a proxy table matching our criteria if (proxyRecords->FindL(*iDb)) { TInt count = proxyRecords->iRecords.Count(); for(TInt index = 0; index < count; index++) { CCDProxiesRecord *proxyRecord = static_cast (proxyRecords->iRecords[index]); RBuf serverName; serverName.CreateL(proxyRecord->iServerName); CleanupClosePushL(serverName); if (serverName.Length() == 0) User::Leave(KErrNotFound); QString serverNameQt((const QChar*)serverName.Ptr(), serverName.Length()); CleanupStack::Pop(); // serverName TUint32 port = proxyRecord->iPortNumber; QNetworkProxy proxy(QNetworkProxy::HttpProxy, serverNameQt, port); foundProxies.append(proxy); } } CleanupStack::PopAndDestroy(proxyRecords); CleanupStack::Pop(); // serviceType CleanupStack::PopAndDestroy(iDb); return foundProxies; } QList QNetworkProxyFactory::systemProxyForQuery(const QNetworkProxyQuery &query) { QList proxies; SymbianIapId iapId; TInt error; QNetworkConfigurationManager manager; iapId = SymbianProxyQuery::getIapId(manager, query); if (iapId.isValid()) { TRAP(error, proxies = SymbianProxyQuery::proxyQueryL(iapId.iapId(), query)) if (error != KErrNone) { qWarning() << "Error while retrieving proxies: '" << error << '"'; proxies.clear(); } } proxies << QNetworkProxy::NoProxy; return proxies; } QT_END_NAMESPACE #endif