blob: 26719ebf54928a2e21b0fa30d409992e1adc3b0d [file] [log] [blame]
/****************************************************************************
**
** 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 <QtNetwork/qnetworkproxy.h>
#ifndef QT_NO_NETWORKPROXY
#include <metadatabase.h> // CMDBSession
#include <commsdattypeinfov1_1.h> // CCDIAPRecord, CCDProxiesRecord
#include <commsdattypesv1_1.h> // KCDTIdIAPRecord, KCDTIdProxiesRecord
#include <QtNetwork/QNetworkConfigurationManager>
#include <QFlags>
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<States> iapState;
TUint32 id;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(SymbianIapId::States)
class SymbianProxyQuery
{
public:
static QNetworkConfiguration findCurrentConfiguration(QNetworkConfigurationManager& configurationManager);
static SymbianIapId getIapId(QNetworkConfigurationManager& configurationManager);
static CCDIAPRecord *getIapRecordLC(TUint32 aIAPId, CMDBSession &aDb);
static CMDBRecordSet<CCDProxiesRecord> *prepareQueryLC(TUint32 serviceId, TDesC& serviceType);
static QList<QNetworkProxy> proxyQueryL(TUint32 aIAPId, const QNetworkProxyQuery &query);
};
QNetworkConfiguration SymbianProxyQuery::findCurrentConfiguration(QNetworkConfigurationManager& configurationManager)
{
QList<QNetworkConfiguration> 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<QNetworkConfiguration> 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)
{
SymbianIapId iapId;
QNetworkConfiguration 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<CCDIAPRecord*> (CCDRecordBase::RecordFactoryL(KCDTIdIAPRecord));
CleanupStack::PushL(iap);
iap->SetRecordId(aIAPId);
iap->LoadL(aDb);
return iap;
}
CMDBRecordSet<CCDProxiesRecord> *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<CCDProxiesRecord> *proxyRecords = new (ELeave) CMDBRecordSet<CCDProxiesRecord> (
KCDTIdProxiesRecord);
CleanupStack::PushL(proxyRecords);
CCDProxiesRecord *primingProxyRecord =
static_cast<CCDProxiesRecord *> (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<QNetworkProxy> SymbianProxyQuery::proxyQueryL(TUint32 aIAPId, const QNetworkProxyQuery &query)
{
QList<QNetworkProxy> 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<CCDProxiesRecord> *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<CCDProxiesRecord *> (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<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkProxyQuery &query)
{
QList<QNetworkProxy> proxies;
SymbianIapId iapId;
TInt error;
QNetworkConfigurationManager manager;
iapId = SymbianProxyQuery::getIapId(manager);
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