1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
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
16 ** 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 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights. These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
32 **************************************************************************/
34 #include "s60certificateinfo.h"
35 #include "s60symbiancertificate.h"
37 #include <QtCore/QDateTime>
38 #include <QtCore/QFileInfo>
39 #include <QtCore/QCoreApplication>
40 #include <QtCore/QTextStream>
41 #include <QtCore/QHash>
42 #include <QtCore/QMutableHashIterator>
44 using namespace Qt4ProjectManager;
45 using namespace Qt4ProjectManager::Internal;
48 const char * const SIMPLE_DATE_FORMAT = "dd.MM.yyyy";
56 static const Capability capability[] =
58 { "LocalServices", S60CertificateInfo::LocalServices },
59 { "Location", S60CertificateInfo::Location },
60 { "NetworkServices", S60CertificateInfo::NetworkServices },
61 { "ReadUserData", S60CertificateInfo::ReadUserData },
62 { "UserEnvironment", S60CertificateInfo::UserEnvironment },
63 { "WriteUserData", S60CertificateInfo::WriteUserData },
64 { "PowerMgmt", S60CertificateInfo::PowerMgmt },
65 { "ProtServ", S60CertificateInfo::ProtServ },
66 { "ReadDeviceData", S60CertificateInfo::ReadDeviceData },
67 { "SurroundingsDD", S60CertificateInfo::SurroundingsDD },
68 { "SwEvent", S60CertificateInfo::SwEvent },
69 { "TrustedUI", S60CertificateInfo::TrustedUI },
70 { "WriteDeviceData", S60CertificateInfo::WriteDeviceData },
71 { "CommDD", S60CertificateInfo::CommDD },
72 { "DiskAdmin", S60CertificateInfo::DiskAdmin },
73 { "NetworkControl", S60CertificateInfo::NetworkControl },
74 { "MultimediaDD", S60CertificateInfo::MultimediaDD },
75 { "AllFiles", S60CertificateInfo::AllFiles },
76 { "DRM", S60CertificateInfo::DRM },
77 { "TCB", S60CertificateInfo::TCB }
80 struct CapabilitySet {
85 static const CapabilitySet capabilitySet[] =
87 { "green", S60CertificateInfo::UserCapabilities },
88 { "darkorange", S60CertificateInfo::SystemCapabilities },
89 { "orangered", S60CertificateInfo::RestrictedCapabilities },
90 { "red", S60CertificateInfo::ManufacturerCapabilities }
93 QHash<int, QStringList> createCapabilityMap(uint capabilities)
95 const int capabilityCount = sizeof(capability)/sizeof(capability[0]);
96 const int capabilitySetCount = sizeof(capabilitySet)/sizeof(capabilitySet[0]);
98 QHash<int, QStringList> capabilityMap; //to separate the groups of capabilities
99 for(int i = 0; i < capabilityCount; ++i)
100 if (capabilities&capability[i].value) {
101 for (int j = 0; j < capabilitySetCount; ++j)
102 if (capability[i].value&capabilitySet[j].value) {
103 capabilityMap[capabilitySet[j].value] << capability[i].name;
108 QMutableHashIterator<int, QStringList> i(capabilityMap);
109 while (i.hasNext()) {
114 return capabilityMap;
117 QStringList createCapabilityList(uint capabilities)
119 QHash<int, QStringList> capabilityMap(createCapabilityMap(capabilities));
121 return capabilityMap[S60CertificateInfo::UserCapabilities]
122 + capabilityMap[S60CertificateInfo::SystemCapabilities]
123 + capabilityMap[S60CertificateInfo::RestrictedCapabilities]
124 + capabilityMap[S60CertificateInfo::ManufacturerCapabilities];
127 QStringList createHtmlCapabilityList(uint capabilities)
129 const int capabilitySetCount = sizeof(capabilitySet)/sizeof(capabilitySet[0]);
130 QHash<int, QStringList> capabilityMap(createCapabilityMap(capabilities));
133 for (int j = 0; j < capabilitySetCount; ++j) {
134 QHashIterator<int, QStringList> i(capabilityMap);
135 while (i.hasNext()) {
137 if (i.key() == capabilitySet[j].value) {
138 foreach (const QString &capability, i.value()) {
139 result << QString::fromAscii("<font color=\"%1\">%2</font>")
140 .arg(capabilitySet[j].color).arg(capability);
149 S60CertificateInfo::S60CertificateInfo(const QString &filePath, QObject* parent)
151 m_certificate(new S60SymbianCertificate(filePath)),
152 m_filePath(filePath),
153 m_capabilities(NoInformation)
155 if (!m_certificate->isValid())
158 m_imeiList = m_certificate->subjectInfo(QLatin1String("1.2.826.0.1.1796587.1.1.1.1"));
160 const QStringList capabilityList(m_certificate->subjectInfo(QLatin1String("1.2.826.0.1.1796587.1.1.1.6")));
161 if (capabilityList.isEmpty())
164 m_capabilities = capabilityList.at(0).toLong();
167 S60CertificateInfo::~S60CertificateInfo()
169 delete m_certificate;
172 S60CertificateInfo::CertificateState S60CertificateInfo::validateCertificate()
174 CertificateState result = CertificateValid;
175 if (m_certificate->isValid()) {
176 QDateTime currentTime(QDateTime::currentDateTimeUtc());
177 QDateTime endTime(m_certificate->endTime());
178 QDateTime startTime(m_certificate->startTime());
179 if (currentTime > endTime) {
180 m_errorString = tr("The certificate \"%1\" has already expired and cannot be used."
181 "\nExpiration date: %2.")
182 .arg(QFileInfo(m_filePath).fileName())
183 .arg(endTime.toLocalTime().toString(QLatin1String(SIMPLE_DATE_FORMAT)));
184 result = CertificateError;
185 } else if (currentTime < startTime) {
186 m_errorString = tr("The certificate \"%1\" is not yet valid.\nValid from: %2.")
187 .arg(QFileInfo(m_filePath).fileName())
188 .arg(startTime.toLocalTime().toString(QLatin1String(SIMPLE_DATE_FORMAT)));
189 result = CertificateWarning; //This certificate may be valid in the near future
192 m_errorString = tr("The certificate \"%1\" is not a valid X.509 certificate.")
193 .arg(QFileInfo(m_filePath).baseName());
194 result = CertificateError;
199 bool S60CertificateInfo::compareCapabilities(const QStringList &givenCaps, QStringList &unsupportedCaps) const
201 if (!m_certificate->isValid())
203 unsupportedCaps.clear();
204 if (capabilitiesSupported() == NoInformation)
207 QStringList capabilities(createCapabilityList(capabilitiesSupported()));
208 foreach (const QString &capability, givenCaps) {
209 if (!capabilities.contains(capability, Qt::CaseInsensitive))
210 unsupportedCaps << capability;
215 QString S60CertificateInfo::errorString() const
217 return m_errorString.isEmpty()?m_certificate->errorString():m_errorString;
220 QStringList S60CertificateInfo::devicesSupported() const
225 quint32 S60CertificateInfo::capabilitiesSupported() const
227 return m_capabilities;
230 bool S60CertificateInfo::isDeveloperCertificate() const
232 return !devicesSupported().isEmpty() || capabilitiesSupported();
235 QString S60CertificateInfo::toHtml(bool keepShort)
237 if (!m_certificate->isValid())
238 return errorString();
241 QTextStream str(&htmlString);
242 str << "<html><body><table>"
243 << "<tr><td><b>" << tr("Type: ") << "</b></td>";
245 if (isDeveloperCertificate())
246 str << "<td>" << tr("Developer certificate") << "</td>";
247 if (m_certificate->isSelfSigned())
248 str << "<td>" << tr("Self signed certificate") << "</td>";
252 QStringList issuerOrganizationList(m_certificate->issuerInfo("X520.Organization"));
253 if (!issuerOrganizationList.isEmpty())
254 issuer = issuerOrganizationList.join(QString(" "));
257 QStringList subjectOrganizationList(m_certificate->subjectInfo("X520.Organization"));
258 if (!subjectOrganizationList.isEmpty())
259 subject = subjectOrganizationList.join(QString(" "));
261 QDateTime startDate(m_certificate->startTime().toLocalTime());
262 QDateTime endDate(m_certificate->endTime().toLocalTime());
264 str << "<tr><td><b>" << tr("Issued by: ")
265 << "</b></td><td>" << issuer << "</td></tr>"
266 << "<tr><td><b>" << tr("Issued to: ")
267 << "</b></td><td>" << subject << "</td></tr>"
268 << "<tr><td><b>" << tr("Valid from: ")
269 << "</b></td><td>" << startDate.toString(QLatin1String(SIMPLE_DATE_FORMAT)) << "</td></tr>"
270 << "<tr><td><b>" << tr("Valid to: ")
271 << "</b></td><td>" << endDate.toString(QLatin1String(SIMPLE_DATE_FORMAT)) << "</td></tr>";
273 if (capabilitiesSupported()) {
274 QStringList capabilities;
276 capabilities = createCapabilityList(capabilitiesSupported());
278 capabilities = createHtmlCapabilityList(capabilitiesSupported());
279 str << "<tr><td><b>" << tr("Capabilities: ")
280 << "</b></td><td><i>" << capabilities.join(" ") << "</i></td></tr>";
283 const QStringList &imeiList(devicesSupported());
284 if (!imeiList.isEmpty()) {
285 QString imeiListString;
287 int MAX_DISPLAYED_IMEI_COUNT = 30;
288 if (imeiList.count() > MAX_DISPLAYED_IMEI_COUNT && keepShort) {//1000 items would be too much :)
289 for (int i = 0; i < MAX_DISPLAYED_IMEI_COUNT; ++i)
290 imeiListString += imeiList.at(i) + space;
291 imeiListString.replace(imeiListString.length()-1, 1, QString("..."));
293 imeiListString = imeiList.join(space);
294 str << "<tr><td><b>" << tr("Supporting %n device(s): ", "", imeiList.count())
295 << "</b></td><td>" << imeiListString << "</td></tr>";