various fixes to deal with CI gate failures
[qt:qt.git] / src / network / kernel / qnetworkproxy_symbian.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the FOO module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 /**
43  * Some notes about the code:
44  *
45  * ** It is assumed that the system proxies are for url based requests
46  *  ie. HTTP/HTTPS based.
47  * ** It is assumed that proxies don't use authentication.
48  * ** It is assumed that there is no exceptions to proxy use (Symbian side
49  *  does have the field for it but it is not user modifiable by default).
50  * ** There is no checking for protocol name.
51  */
52
53 #include <QtNetwork/qnetworkproxy.h>
54
55 #ifndef QT_NO_NETWORKPROXY
56
57 #include <metadatabase.h> // CMDBSession
58 #include <commsdattypeinfov1_1.h> // CCDIAPRecord, CCDProxiesRecord
59 #include <commsdattypesv1_1.h> // KCDTIdIAPRecord, KCDTIdProxiesRecord
60 #include <QtNetwork/QNetworkConfigurationManager>
61 #include <QFlags>
62
63 using namespace CommsDat;
64
65 QT_BEGIN_NAMESPACE
66
67 class SymbianIapId
68 {
69 public:
70     enum State{
71         NotValid,
72         Valid
73     };
74     Q_DECLARE_FLAGS(States, State)
75     SymbianIapId() {}
76     ~SymbianIapId() {}
77     void setIapId(TUint32 iapId) { iapState |= Valid; id = iapId; }
78     bool isValid() { return iapState == Valid; }
79     TUint32 iapId() { return id; }
80 private:
81     QFlags<States> iapState;
82     TUint32 id;
83 };
84
85 Q_DECLARE_OPERATORS_FOR_FLAGS(SymbianIapId::States)
86
87 class SymbianProxyQuery
88 {
89 public:
90     static QNetworkConfiguration findCurrentConfiguration(QNetworkConfigurationManager& configurationManager);
91     static SymbianIapId getIapId(QNetworkConfigurationManager& configurationManager);
92     static CCDIAPRecord *getIapRecordLC(TUint32 aIAPId, CMDBSession &aDb);
93     static CMDBRecordSet<CCDProxiesRecord> *prepareQueryLC(TUint32 serviceId, TDesC& serviceType);
94     static QList<QNetworkProxy> proxyQueryL(TUint32 aIAPId, const QNetworkProxyQuery &query);
95 };
96
97 QNetworkConfiguration SymbianProxyQuery::findCurrentConfiguration(QNetworkConfigurationManager& configurationManager)
98 {
99     QList<QNetworkConfiguration> activeConfigurations = configurationManager.allConfigurations(
100         QNetworkConfiguration::Active);
101     QNetworkConfiguration currentConfig;
102     if (activeConfigurations.count() > 0) {
103         currentConfig = activeConfigurations.at(0);
104     } else {
105         // No active configurations, try default one
106         QNetworkConfiguration defaultConfiguration = configurationManager.defaultConfiguration();
107         if (defaultConfiguration.isValid()) {
108             switch (defaultConfiguration.type()) {
109             case QNetworkConfiguration::InternetAccessPoint:
110                 currentConfig = defaultConfiguration;
111                 break;
112             case QNetworkConfiguration::ServiceNetwork:
113             {
114                 // Note: This code assumes that the only unambigious way to
115                 // find current proxy config is if there is only one access point
116                 // or if the found access point is immediately usable.
117                 QList<QNetworkConfiguration> childConfigurations = defaultConfiguration.children();
118                 if (childConfigurations.count() == 1) {
119                     currentConfig = childConfigurations.at(0);
120                 } else {
121                     for (int index = 0; index < childConfigurations.count(); index++) {
122                         QNetworkConfiguration childConfig = childConfigurations.at(index);
123                         if (childConfig.isValid() && childConfig.state() == QNetworkConfiguration::Discovered) {
124                             currentConfig = childConfig;
125                             break;
126                         }
127                     }
128                 }
129             }
130                 break;
131             case QNetworkConfiguration::UserChoice:
132                 // User choice is not a valid configuration for proxy discovery
133                 break;
134             }
135         }
136     }
137     return currentConfig;
138 }
139
140 SymbianIapId SymbianProxyQuery::getIapId(QNetworkConfigurationManager& configurationManager)
141 {
142     SymbianIapId iapId;
143
144     QNetworkConfiguration currentConfig = findCurrentConfiguration(configurationManager);
145     if (currentConfig.isValid()) {
146         // Note: the following code assumes that the identifier is in format
147         // I_xxxx where xxxx is the identifier of IAP. This is meant as a
148         // temporary solution until there is a support for returning
149         // implementation specific identifier.
150         const int generalPartLength = 2;
151         const int identifierNumberLength = currentConfig.identifier().length() - generalPartLength;
152         QString idString(currentConfig.identifier().right(identifierNumberLength));
153         bool success;
154         uint id = idString.toUInt(&success);
155         if (success)
156             iapId.setIapId(id);
157         else
158             qWarning() << "Failed to convert identifier to access point identifier: "
159                 << currentConfig.identifier();
160     }
161
162     return iapId;
163 }
164
165 CCDIAPRecord *SymbianProxyQuery::getIapRecordLC(TUint32 aIAPId, CMDBSession &aDb)
166 {
167     CCDIAPRecord *iap = static_cast<CCDIAPRecord*> (CCDRecordBase::RecordFactoryL(KCDTIdIAPRecord));
168     CleanupStack::PushL(iap);
169     iap->SetRecordId(aIAPId);
170     iap->LoadL(aDb);
171     return iap;
172 }
173
174 CMDBRecordSet<CCDProxiesRecord> *SymbianProxyQuery::prepareQueryLC(TUint32 serviceId, TDesC& serviceType)
175 {
176     // Create a recordset of type CCDProxiesRecord
177     // for priming search.
178     // This will ultimately contain record(s)
179     // matching the priming record attributes
180     CMDBRecordSet<CCDProxiesRecord> *proxyRecords = new (ELeave) CMDBRecordSet<CCDProxiesRecord> (
181         KCDTIdProxiesRecord);
182     CleanupStack::PushL(proxyRecords);
183
184     CCDProxiesRecord *primingProxyRecord =
185         static_cast<CCDProxiesRecord *> (CCDRecordBase::RecordFactoryL(KCDTIdProxiesRecord));
186     CleanupStack::PushL(primingProxyRecord);
187
188     primingProxyRecord->iServiceType.SetMaxLengthL(serviceType.Length());
189     primingProxyRecord->iServiceType = serviceType;
190     primingProxyRecord->iService = serviceId;
191     primingProxyRecord->iUseProxyServer = ETrue;
192
193     proxyRecords->iRecords.AppendL(primingProxyRecord);
194     // Ownership of primingProxyRecord is transferred to
195     // proxyRecords, just remove it from the CleanupStack
196     CleanupStack::Pop(primingProxyRecord);
197     return proxyRecords;
198 }
199
200 QList<QNetworkProxy> SymbianProxyQuery::proxyQueryL(TUint32 aIAPId, const QNetworkProxyQuery &query)
201 {
202     QList<QNetworkProxy> foundProxies;
203     if (query.queryType() != QNetworkProxyQuery::UrlRequest) {
204         return foundProxies;
205     }
206
207     CMDBSession *iDb = CMDBSession::NewLC(KCDVersion1_1);
208     CCDIAPRecord *iap = getIapRecordLC(aIAPId, *iDb);
209
210     // Read service table id and service type
211     // from the IAP record found
212     TUint32 serviceId = iap->iService;
213     RBuf serviceType;
214     serviceType.CreateL(iap->iServiceType);
215     CleanupStack::PopAndDestroy(iap);
216     CleanupClosePushL(serviceType);
217
218     CMDBRecordSet<CCDProxiesRecord> *proxyRecords = prepareQueryLC(serviceId, serviceType);
219
220     // Now to find a proxy table matching our criteria
221     if (proxyRecords->FindL(*iDb)) {
222         TInt count = proxyRecords->iRecords.Count();
223         for(TInt index = 0; index < count; index++) {
224             CCDProxiesRecord *proxyRecord = static_cast<CCDProxiesRecord *> (proxyRecords->iRecords[index]);
225             RBuf serverName;
226             serverName.CreateL(proxyRecord->iServerName);
227             CleanupClosePushL(serverName);
228             if (serverName.Length() == 0)
229                 User::Leave(KErrNotFound);
230             QString serverNameQt((const QChar*)serverName.Ptr(), serverName.Length());
231             CleanupStack::Pop(); // serverName
232             TUint32 port = proxyRecord->iPortNumber;
233
234             QNetworkProxy proxy(QNetworkProxy::HttpProxy, serverNameQt, port);
235             foundProxies.append(proxy);
236         }
237     }
238
239     CleanupStack::PopAndDestroy(proxyRecords);
240     CleanupStack::Pop(); // serviceType
241     CleanupStack::PopAndDestroy(iDb);
242
243     return foundProxies;
244 }
245
246 QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkProxyQuery &query)
247 {
248     QList<QNetworkProxy> proxies;
249     SymbianIapId iapId;
250     TInt error;
251     QNetworkConfigurationManager manager;
252     iapId = SymbianProxyQuery::getIapId(manager);
253     if (iapId.isValid()) {
254         TRAP(error, proxies = SymbianProxyQuery::proxyQueryL(iapId.iapId(), query))
255         if (error != KErrNone) {
256             qWarning() << "Error while retrieving proxies: '" << error << '"';
257             proxies.clear();
258         }
259     }
260     proxies << QNetworkProxy::NoProxy;
261
262     return proxies;
263 }
264
265 QT_END_NAMESPACE
266
267 #endif