• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeutils API Reference
  • KDE Home
  • Contact Us
 

kgpg

  • sources
  • kde-4.14
  • kdeutils
  • kgpg
  • transactions
kgpgverify.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 Rolf Eike Beer <kde@opensource.sf-tec.de>
3  */
4 
5 /***************************************************************************
6  * *
7  * This program is free software; you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation; either version 2 of the License, or *
10  * (at your option) any later version. *
11  * *
12  ***************************************************************************/
13 
14 #include "kgpgverify.h"
15 
16 #include "gpgproc.h"
17 #include "core/KGpgKeyNode.h"
18 #include "model/kgpgitemmodel.h"
19 
20 #include <KGlobal>
21 #include <KLocale>
22 
23 KGpgVerify::KGpgVerify(QObject *parent, const QString &text)
24  : KGpgTextOrFileTransaction(parent, text),
25  m_fileIndex(-1)
26 {
27 }
28 
29 KGpgVerify::KGpgVerify(QObject *parent, const KUrl::List &files)
30  : KGpgTextOrFileTransaction(parent, files),
31  m_fileIndex(0)
32 {
33 }
34 
35 KGpgVerify::~KGpgVerify()
36 {
37 }
38 
39 QStringList
40 KGpgVerify::command() const
41 {
42  QStringList ret(QLatin1String("--verify"));
43 
44  return ret;
45 }
46 
47 bool
48 KGpgVerify::nextLine(const QString &line)
49 {
50  if (line.startsWith(QLatin1String("[GNUPG:] NO_PUBKEY "))) {
51  setSuccess(TS_MISSING_KEY);
52  m_missingId = line.mid(19).simplified();
53  return false;
54  }
55 
56  if (line.startsWith(QLatin1String("[GNUPG:] ")) &&
57  line.contains(QLatin1String("SIG"))) {
58  if (line.startsWith(QLatin1String("[GNUPG:] BADSIG")))
59  setSuccess(KGpgVerify::TS_BAD_SIGNATURE);
60  else
61  setSuccess(KGpgTransaction::TS_OK);
62  }
63 
64  return KGpgTextOrFileTransaction::nextLine(line);
65 }
66 
67 void
68 KGpgVerify::finish()
69 {
70  // GnuPG will return error code 2 if it wasn't able to verify the file.
71  // If it complained about a missing signature before that is fine.
72  if (((getProcess()->exitCode() == 2) && (getSuccess() == TS_MISSING_KEY)) ||
73  ((getProcess()->exitCode() == 1) && (getSuccess() == TS_BAD_SIGNATURE)))
74  return;
75 
76  KGpgTextOrFileTransaction::finish();
77 }
78 
79 static QString
80 sigTimeMessage(const QString &sigtime)
81 {
82  QDateTime stamp;
83  if (sigtime.contains(QLatin1Char('T'))) {
84  stamp = QDateTime::fromString(sigtime, Qt::ISODate);
85  } else {
86  bool ok;
87  qint64 secs = sigtime.toLongLong(&ok);
88  if (ok)
89  stamp = QDateTime::fromMSecsSinceEpoch(secs * 1000);
90  }
91 
92  if (!stamp.isValid())
93  return QString();
94 
95  return i18nc("first argument is formatted date, second argument is formatted time",
96  "The signature was created at %1 %2",
97  KGlobal::locale()->formatDate(stamp.date(), KLocale::LongDate),
98  KGlobal::locale()->formatTime(stamp.time(), KLocale::LongDate)) +
99  QLatin1String("<br/>");
100 }
101 
102 QString
103 KGpgVerify::getReport(const QStringList &log, const KGpgItemModel *model)
104 {
105  QString result;
106  // newer versions of GnuPG emit both VALIDSIG and GOODSIG
107  // for a good signature. Since VALIDSIG has more information
108  // we use that.
109  const QRegExp validsig(QLatin1String("^\\[GNUPG:\\] VALIDSIG([ ]+[^ ]+){10,}.*$"));
110  const bool useGoodSig = (model == NULL) || (log.indexOf(validsig) == -1);
111  QString sigtime; // timestamp of signature creation
112 
113  foreach (const QString &line, log) {
114  if (!line.startsWith(QLatin1String("[GNUPG:] ")))
115  continue;
116 
117  const QString msg = line.mid(9);
118 
119  if (!useGoodSig && msg.startsWith(QLatin1String("VALIDSIG "))) {
120  // from GnuPG source, doc/DETAILS:
121  // VALIDSIG <fingerprint in hex> <sig_creation_date> <sig-timestamp>
122  // <expire-timestamp> <sig-version> <reserved> <pubkey-algo>
123  // <hash-algo> <sig-class> <primary-key-fpr>
124  const QStringList vsig = msg.mid(9).split(QLatin1Char(' '), QString::SkipEmptyParts);
125  Q_ASSERT(vsig.count() >= 10);
126 
127  const KGpgKeyNode *node = model->findKeyNode(vsig[9]);
128 
129  if (node != NULL) {
130  // ignore for now if this is signed with the primary id (vsig[0] == vsig[9]) or not
131  if (node->getEmail().isEmpty())
132  result += i18n("<qt>Good signature from:<br /><b>%1</b><br />Key ID: %2<br /></qt>",
133  node->getName(), vsig[9]);
134  else
135  result += i18nc("Good signature from: NAME <EMAIL>, Key ID: HEXID",
136  "<qt>Good signature from:<br /><b>%1 &lt;%2&gt;</b><br />Key ID: %3<br /></qt>",
137  node->getName(), node->getEmail(), vsig[9]);
138 
139  result += sigTimeMessage(vsig[2]);
140  } else {
141  // this should normally never happen, but one could delete
142  // the key just after the verification. Brute force solution:
143  // do the whole report generation again, but this time make
144  // sure GOODSIG is used.
145  return getReport(log, NULL);
146  }
147  } else if (msg.startsWith(QLatin1String("UNEXPECTED")) ||
148  msg.startsWith(QLatin1String("NODATA"))) {
149  result += i18n("No signature found.") + QLatin1Char('\n');
150  } else if (useGoodSig && msg.startsWith(QLatin1String("GOODSIG "))) {
151  int sigpos = msg.indexOf( ' ' , 8);
152  const QString keyid = msg.mid(8, sigpos - 8);
153 
154  // split the name/email pair to give translators more power to handle this
155  QString email;
156  QString name = msg.mid(sigpos + 1);
157 
158  int oPos = name.indexOf(QLatin1Char('<'));
159  int cPos = name.indexOf(QLatin1Char('>'));
160  if ((oPos >= 0) && (cPos >= 0)) {
161  email = name.mid(oPos + 1, cPos - oPos - 1);
162  name = name.left(oPos).simplified();
163  }
164 
165  if (email.isEmpty())
166  result += i18n("<qt>Good signature from:<br /><b>%1</b><br />Key ID: %2<br /></qt>",
167  name, keyid);
168  else
169  result += i18nc("Good signature from: NAME <EMAIL>, Key ID: HEXID",
170  "<qt>Good signature from:<br /><b>%1 &lt;%2&gt;</b><br />Key ID: %3<br /></qt>",
171  name, email, keyid);
172  if (!sigtime.isEmpty()) {
173  result += sigTimeMessage(sigtime);
174  sigtime.clear();
175  }
176  } else if (msg.startsWith(QLatin1String("SIG_ID "))) {
177  const QStringList parts = msg.simplified().split(QLatin1Char(' '));
178  if (parts.count() > 2)
179  sigtime = parts[2];
180  } else if (msg.startsWith(QLatin1String("BADSIG"))) {
181  int sigpos = msg.indexOf( ' ', 7);
182  result += i18n("<qt><b>BAD signature</b> from:<br /> %1<br />Key id: %2<br /><br /><b>The file is corrupted</b><br /></qt>",
183  msg.mid(sigpos + 1).replace(QLatin1Char('<'), QLatin1String("&lt;")),
184  msg.mid(7, sigpos - 7));
185  } else if (msg.startsWith(QLatin1String("TRUST_UNDEFINED"))) {
186  result += i18n("<qt>The signature is valid, but the key is untrusted<br /></qt>");
187  } else if (msg.startsWith(QLatin1String("TRUST_ULTIMATE"))) {
188  result += i18n("<qt>The signature is valid, and the key is ultimately trusted<br /></qt>");
189  }
190  }
191 
192  return result;
193 }
194 
195 QString
196 KGpgVerify::missingId() const
197 {
198  return m_missingId;
199 }
200 
201 #include "kgpgverify.moc"
KGpgTextOrFileTransaction
feed a text or file through gpg
Definition: kgpgtextorfiletransaction.h:29
KGpgItemModel
Definition: kgpgitemmodel.h:44
KGpgTransaction::getSuccess
int getSuccess() const
get the success value that will be returned with the done signal
Definition: kgpgtransaction.cpp:442
QString::indexOf
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
KGpgTransaction::TS_OK
everything went fine
Definition: kgpgtransaction.h:60
QString::split
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
QString::simplified
QString simplified() const
QDateTime::time
QTime time() const
KGpgVerify::nextLine
virtual bool nextLine(const QString &line)
Called for every line the gpg process writes.
Definition: kgpgverify.cpp:48
QDateTime::fromMSecsSinceEpoch
QDateTime fromMSecsSinceEpoch(qint64 msecs)
KGpgTransaction::getProcess
GPGProc * getProcess()
get a reference to the gpg process object
Definition: kgpgtransaction.cpp:556
KGpgVerify::command
virtual QStringList command() const
Definition: kgpgverify.cpp:40
KGpgKeyNode
A public key with or without corresponding secret key.
Definition: KGpgKeyNode.h:33
QString::clear
void clear()
QRegExp
sigTimeMessage
static QString sigTimeMessage(const QString &sigtime)
Definition: kgpgverify.cpp:80
QObject::name
const char * name() const
KGpgVerify::TS_MISSING_KEY
signing key not in keyring
Definition: kgpgverify.h:38
QList::count
int count(const T &value) const
KGpgItemModel::findKeyNode
KGpgKeyNode * findKeyNode(const QString &id) const
Definition: kgpgitemmodel.cpp:238
QObject
kgpgitemmodel.h
QString::isEmpty
bool isEmpty() const
QString::startsWith
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
gpgproc.h
KGpgTextOrFileTransaction::finish
virtual void finish()
implement special handling for GnuPG return codes
Definition: kgpgtextorfiletransaction.cpp:151
QString
KGpgVerify::TS_BAD_SIGNATURE
the file is signed, but the signature is invalid
Definition: kgpgverify.h:39
QStringList
QString::contains
bool contains(QChar ch, Qt::CaseSensitivity cs) const
QLatin1Char
QDateTime::fromString
QDateTime fromString(const QString &string, Qt::DateFormat format)
KGpgTextOrFileTransaction::nextLine
virtual bool nextLine(const QString &line)
Called for every line the gpg process writes.
Definition: kgpgtextorfiletransaction.cpp:143
KGpgVerify::getReport
static QString getReport(const QStringList &log, const KGpgItemModel *model=NULL)
get verification report
Definition: kgpgverify.cpp:103
QDateTime::isValid
bool isValid() const
QString::replace
QString & replace(int position, int n, QChar after)
QString::mid
QString mid(int position, int n) const
QDateTime::date
QDate date() const
QLatin1String
KGpgTransaction::setSuccess
void setSuccess(const int v)
set the success value that will be returned with the done signal
Definition: kgpgtransaction.cpp:448
KGpgKeyNode.h
QString::left
QString left(int n) const
kgpgverify.h
QStringList::indexOf
int indexOf(const QRegExp &rx, int from) const
KGpgVerify::missingId
QString missingId() const
get the missing key id
Definition: kgpgverify.cpp:196
KGpgVerify::finish
virtual void finish()
implement special handling for GnuPG return codes
Definition: kgpgverify.cpp:68
KGpgVerify::~KGpgVerify
virtual ~KGpgVerify()
destructor
Definition: kgpgverify.cpp:35
QString::toLongLong
qlonglong toLongLong(bool *ok, int base) const
QDateTime
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:42:08 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kgpg

Skip menu "kgpg"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdeutils API Reference

Skip menu "kdeutils API Reference"
  • ark
  • filelight
  • kcalc
  • kcharselect
  • kdf
  • kfloppy
  • kgpg
  • ktimer
  • kwallet
  • sweeper

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal