1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
10 ** GNU Lesser General Public License Usage
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
31 **************************************************************************/
33 #include "s60certificateinfo.h"
34 #include "s60symbiancertificate.h"
36 #include <QtCore/QDateTime>
37 #include <QtCore/QFileInfo>
38 #include <QtCore/QCoreApplication>
39 #include <QtCore/QTextStream>
40 #include <QtCore/QHash>
41 #include <QtCore/QMutableHashIterator>
43 using namespace Qt4ProjectManager;
44 using namespace Qt4ProjectManager::Internal;
47 const char * const SIMPLE_DATE_FORMAT = "dd.MM.yyyy";
55 static const Capability capability[] =
57 { "LocalServices", S60CertificateInfo::LocalServices },
58 { "Location", S60CertificateInfo::Location },
59 { "NetworkServices", S60CertificateInfo::NetworkServices },
60 { "ReadUserData", S60CertificateInfo::ReadUserData },
61 { "UserEnvironment", S60CertificateInfo::UserEnvironment },
62 { "WriteUserData", S60CertificateInfo::WriteUserData },
63 { "PowerMgmt", S60CertificateInfo::PowerMgmt },
64 { "ProtServ", S60CertificateInfo::ProtServ },
65 { "ReadDeviceData", S60CertificateInfo::ReadDeviceData },
66 { "SurroundingsDD", S60CertificateInfo::SurroundingsDD },
67 { "SwEvent", S60CertificateInfo::SwEvent },
68 { "TrustedUI", S60CertificateInfo::TrustedUI },
69 { "WriteDeviceData", S60CertificateInfo::WriteDeviceData },
70 { "CommDD", S60CertificateInfo::CommDD },
71 { "DiskAdmin", S60CertificateInfo::DiskAdmin },
72 { "NetworkControl", S60CertificateInfo::NetworkControl },
73 { "MultimediaDD", S60CertificateInfo::MultimediaDD },
74 { "AllFiles", S60CertificateInfo::AllFiles },
75 { "DRM", S60CertificateInfo::DRM },
76 { "TCB", S60CertificateInfo::TCB }
79 struct CapabilitySet {
84 static const CapabilitySet capabilitySet[] =
86 { "green", S60CertificateInfo::UserCapabilities },
87 { "darkorange", S60CertificateInfo::SystemCapabilities },
88 { "orangered", S60CertificateInfo::RestrictedCapabilities },
89 { "red", S60CertificateInfo::ManufacturerCapabilities }
92 QHash<int, QStringList> createCapabilityMap(uint capabilities)
94 const int capabilityCount = sizeof(capability)/sizeof(capability[0]);
95 const int capabilitySetCount = sizeof(capabilitySet)/sizeof(capabilitySet[0]);
97 QHash<int, QStringList> capabilityMap; //to separate the groups of capabilities
98 for(int i = 0; i < capabilityCount; ++i)
99 if (capabilities&capability[i].value) {
100 for (int j = 0; j < capabilitySetCount; ++j)
101 if (capability[i].value&capabilitySet[j].value) {
102 capabilityMap[capabilitySet[j].value] << capability[i].name;
107 QMutableHashIterator<int, QStringList> i(capabilityMap);
108 while (i.hasNext()) {
113 return capabilityMap;
116 QStringList createCapabilityList(uint capabilities)
118 QHash<int, QStringList> capabilityMap(createCapabilityMap(capabilities));
120 return capabilityMap[S60CertificateInfo::UserCapabilities]
121 + capabilityMap[S60CertificateInfo::SystemCapabilities]
122 + capabilityMap[S60CertificateInfo::RestrictedCapabilities]
123 + capabilityMap[S60CertificateInfo::ManufacturerCapabilities];
126 QStringList createHtmlCapabilityList(uint capabilities)
128 const int capabilitySetCount = sizeof(capabilitySet)/sizeof(capabilitySet[0]);
129 QHash<int, QStringList> capabilityMap(createCapabilityMap(capabilities));
132 for (int j = 0; j < capabilitySetCount; ++j) {
133 QHashIterator<int, QStringList> i(capabilityMap);
134 while (i.hasNext()) {
136 if (i.key() == capabilitySet[j].value) {
137 foreach (const QString &capability, i.value()) {
138 result << QString::fromAscii("<font color=\"%1\">%2</font>")
139 .arg(capabilitySet[j].color).arg(capability);
148 S60CertificateInfo::S60CertificateInfo(const QString &filePath, QObject* parent)
150 m_certificate(new S60SymbianCertificate(filePath)),
151 m_filePath(filePath),
152 m_capabilities(NoInformation)
154 if (!m_certificate->isValid())
157 m_imeiList = m_certificate->subjectInfo(QLatin1String("1.2.826.0.1.1796587.1.1.1.1"));
159 const QStringList capabilityList(m_certificate->subjectInfo(QLatin1String("1.2.826.0.1.1796587.1.1.1.6")));
160 if (capabilityList.isEmpty())
163 m_capabilities = capabilityList.at(0).toLong();
166 S60CertificateInfo::~S60CertificateInfo()
168 delete m_certificate;
171 S60CertificateInfo::CertificateState S60CertificateInfo::validateCertificate()
173 CertificateState result = CertificateValid;
174 if (m_certificate->isValid()) {
175 QDateTime currentTime(QDateTime::currentDateTimeUtc());
176 QDateTime endTime(m_certificate->endTime());
177 QDateTime startTime(m_certificate->startTime());
178 if (currentTime > endTime) {
179 m_errorString = tr("The certificate \"%1\" has already expired and cannot be used."
180 "\nExpiration date: %2.")
181 .arg(QFileInfo(m_filePath).fileName())
182 .arg(endTime.toLocalTime().toString(QLatin1String(SIMPLE_DATE_FORMAT)));
183 result = CertificateError;
184 } else if (currentTime < startTime) {
185 m_errorString = tr("The certificate \"%1\" is not yet valid.\nValid from: %2.")
186 .arg(QFileInfo(m_filePath).fileName())
187 .arg(startTime.toLocalTime().toString(QLatin1String(SIMPLE_DATE_FORMAT)));
188 result = CertificateWarning; //This certificate may be valid in the near future
191 m_errorString = tr("The certificate \"%1\" is not a valid X.509 certificate.")
192 .arg(QFileInfo(m_filePath).baseName());
193 result = CertificateError;
198 bool S60CertificateInfo::compareCapabilities(const QStringList &givenCaps, QStringList &unsupportedCaps) const
200 if (!m_certificate->isValid())
202 unsupportedCaps.clear();
203 if (capabilitiesSupported() == NoInformation)
206 QStringList capabilities(createCapabilityList(capabilitiesSupported()));
207 foreach (const QString &capability, givenCaps) {
208 if (!capabilities.contains(capability, Qt::CaseInsensitive))
209 unsupportedCaps << capability;
214 QString S60CertificateInfo::errorString() const
216 return m_errorString.isEmpty()?m_certificate->errorString():m_errorString;
219 QStringList S60CertificateInfo::devicesSupported() const
224 quint32 S60CertificateInfo::capabilitiesSupported() const
226 return m_capabilities;
229 bool S60CertificateInfo::isDeveloperCertificate() const
231 return !devicesSupported().isEmpty() || capabilitiesSupported();
234 QString S60CertificateInfo::toHtml(bool keepShort)
236 if (!m_certificate->isValid())
237 return errorString();
240 QTextStream str(&htmlString);
241 str << "<html><body><table>"
242 << "<tr><td><b>" << tr("Type: ") << "</b></td>";
244 if (isDeveloperCertificate())
245 str << "<td>" << tr("Developer certificate") << "</td>";
246 if (m_certificate->isSelfSigned())
247 str << "<td>" << tr("Self signed certificate") << "</td>";
251 QStringList issuerOrganizationList(m_certificate->issuerInfo("X520.Organization"));
252 if (!issuerOrganizationList.isEmpty())
253 issuer = issuerOrganizationList.join(QString(" "));
256 QStringList subjectOrganizationList(m_certificate->subjectInfo("X520.Organization"));
257 if (!subjectOrganizationList.isEmpty())
258 subject = subjectOrganizationList.join(QString(" "));
260 QDateTime startDate(m_certificate->startTime().toLocalTime());
261 QDateTime endDate(m_certificate->endTime().toLocalTime());
263 str << "<tr><td><b>" << tr("Issued by: ")
264 << "</b></td><td>" << issuer << "</td></tr>"
265 << "<tr><td><b>" << tr("Issued to: ")
266 << "</b></td><td>" << subject << "</td></tr>"
267 << "<tr><td><b>" << tr("Valid from: ")
268 << "</b></td><td>" << startDate.toString(QLatin1String(SIMPLE_DATE_FORMAT)) << "</td></tr>"
269 << "<tr><td><b>" << tr("Valid to: ")
270 << "</b></td><td>" << endDate.toString(QLatin1String(SIMPLE_DATE_FORMAT)) << "</td></tr>";
272 if (capabilitiesSupported()) {
273 QStringList capabilities;
275 capabilities = createCapabilityList(capabilitiesSupported());
277 capabilities = createHtmlCapabilityList(capabilitiesSupported());
278 str << "<tr><td><b>" << tr("Capabilities: ")
279 << "</b></td><td><i>" << capabilities.join(" ") << "</i></td></tr>";
282 const QStringList &imeiList(devicesSupported());
283 if (!imeiList.isEmpty()) {
284 QString imeiListString;
286 int MAX_DISPLAYED_IMEI_COUNT = 30;
287 if (imeiList.count() > MAX_DISPLAYED_IMEI_COUNT && keepShort) {//1000 items would be too much :)
288 for (int i = 0; i < MAX_DISPLAYED_IMEI_COUNT; ++i)
289 imeiListString += imeiList.at(i) + space;
290 imeiListString.replace(imeiListString.length()-1, 1, QString("..."));
292 imeiListString = imeiList.join(space);
293 str << "<tr><td><b>" << tr("Supporting %n device(s): ", "", imeiList.count())
294 << "</b></td><td>" << imeiListString << "</td></tr>";