mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-23 18:32:53 +00:00
417 lines
11 KiB
C++
417 lines
11 KiB
C++
/*
|
|
* Copyright (C) 2002 Jean-Baptiste Mardelle <bj@altern.org>
|
|
* Copyright (C) 2007,2008,2009,2010,2011,2012,2013
|
|
* Rolf Eike Beer <kde@opensource.sf-tec.de>
|
|
*/
|
|
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "kgpginterface.h"
|
|
|
|
#include "gpgproc.h"
|
|
#include "core/convert.h"
|
|
#include "core/KGpgKeyNode.h"
|
|
#include "core/KGpgSignNode.h"
|
|
#include "core/KGpgSubkeyNode.h"
|
|
#include "core/KGpgUatNode.h"
|
|
#include "core/KGpgUidNode.h"
|
|
|
|
#include <gpgme.h>
|
|
#include <KConfig>
|
|
#include <KDebug>
|
|
#include <KGlobal>
|
|
#include <KLocale>
|
|
#include <KMessageBox>
|
|
#include <KProcess>
|
|
#include <QFile>
|
|
#include <QString>
|
|
#include <QTextStream>
|
|
|
|
using namespace KgpgCore;
|
|
|
|
QString KgpgInterface::getGpgSetting(const QString &name, const QString &configfile)
|
|
{
|
|
const QString tmp(name.simplified() + QLatin1Char( ' ' ));
|
|
QFile qfile(configfile);
|
|
|
|
if (qfile.open(QIODevice::ReadOnly) && (qfile.exists())) {
|
|
QTextStream t(&qfile);
|
|
while (!t.atEnd()) {
|
|
QString result(t.readLine().simplified());
|
|
if (result.startsWith(tmp)) {
|
|
result = result.mid(tmp.length()).simplified();
|
|
return result.section(QLatin1Char( ' ' ), 0, 0);
|
|
}
|
|
}
|
|
qfile.close();
|
|
}
|
|
|
|
return QString();
|
|
}
|
|
|
|
void KgpgInterface::setGpgSetting(const QString &name, const QString &value, const QString &url)
|
|
{
|
|
QFile qfile(url);
|
|
|
|
if (qfile.open(QIODevice::ReadOnly) && (qfile.exists())) {
|
|
const QString temp(name + QLatin1Char( ' ' ));
|
|
QString texttowrite;
|
|
bool found = false;
|
|
QTextStream t(&qfile);
|
|
|
|
while (!t.atEnd()) {
|
|
QString result = t.readLine();
|
|
if (result.simplified().startsWith(temp)) {
|
|
if (!value.isEmpty())
|
|
result = temp + QLatin1Char( ' ' ) + value;
|
|
else
|
|
result.clear();
|
|
found = true;
|
|
}
|
|
|
|
texttowrite += result + QLatin1Char( '\n' );
|
|
}
|
|
|
|
qfile.close();
|
|
if ((!found) && (!value.isEmpty()))
|
|
texttowrite += QLatin1Char( '\n' ) + temp + QLatin1Char( ' ' ) + value;
|
|
|
|
if (qfile.open(QIODevice::WriteOnly)) {
|
|
QTextStream t(&qfile);
|
|
t << texttowrite;
|
|
qfile.close();
|
|
}
|
|
}
|
|
}
|
|
|
|
bool KgpgInterface::getGpgBoolSetting(const QString &name, const QString &configfile)
|
|
{
|
|
QFile qfile(configfile);
|
|
if (qfile.open(QIODevice::ReadOnly) && (qfile.exists())) {
|
|
QTextStream t(&qfile);
|
|
while (!t.atEnd()) {
|
|
if (t.readLine().simplified().startsWith(name))
|
|
return true;
|
|
}
|
|
qfile.close();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void KgpgInterface::setGpgBoolSetting(const QString &name, const bool enable, const QString &url)
|
|
{
|
|
QFile qfile(url);
|
|
|
|
if (qfile.open(QIODevice::ReadOnly) && (qfile.exists())) {
|
|
QString texttowrite;
|
|
bool found = false;
|
|
QTextStream t(&qfile);
|
|
|
|
while (!t.atEnd()) {
|
|
QString result(t.readLine());
|
|
|
|
if (result.simplified().startsWith(name)) {
|
|
if (enable)
|
|
result = name;
|
|
else
|
|
result.clear();
|
|
|
|
found = true;
|
|
}
|
|
|
|
texttowrite += result + QLatin1Char( '\n' );
|
|
}
|
|
qfile.close();
|
|
|
|
if ((!found) && (enable))
|
|
texttowrite += name;
|
|
|
|
if (qfile.open(QIODevice::WriteOnly)) {
|
|
QTextStream t(&qfile);
|
|
t << texttowrite;
|
|
qfile.close();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param p the process that reads the GnuPG data
|
|
* @param readNode the node where the signatures are read for
|
|
*/
|
|
static KgpgCore::KgpgKeyList
|
|
readPublicKeysProcess(GPGProc &p, KGpgKeyNode *readNode)
|
|
{
|
|
QStringList lsp;
|
|
int items;
|
|
KgpgCore::KgpgKeyList publiclistkeys;
|
|
KgpgCore::KgpgKey *publickey = NULL;
|
|
unsigned int idIndex = 0;
|
|
QString log;
|
|
KGpgSignableNode *currentSNode = NULL; ///< the current (sub)node signatures are read for
|
|
|
|
while ((items = p.readln(lsp)) >= 0) {
|
|
if ((lsp.at(0) == QLatin1String( "pub" )) && (items >= 10)) {
|
|
KgpgSubKeyType subtype;
|
|
KgpgSubKeyType keytype;
|
|
bool enabled = true;
|
|
if (items > 11) {
|
|
const QString &caps = lsp.at(11);
|
|
|
|
enabled = !caps.contains(QLatin1Char('D'), Qt::CaseSensitive);
|
|
|
|
subtype = Convert::toSubType(caps, false);
|
|
keytype = Convert::toSubType(caps, true);
|
|
}
|
|
|
|
publiclistkeys << KgpgKey(lsp.at(4), lsp.at(2).toUInt(), Convert::toTrust(lsp.at(1)),
|
|
Convert::toAlgo(lsp.at(3).toInt()), subtype, keytype,
|
|
QDateTime::fromTime_t(lsp.at(5).toUInt()));
|
|
|
|
publickey = &publiclistkeys.last();
|
|
|
|
const QString &owTrust = lsp.at(8);
|
|
if (owTrust.isEmpty())
|
|
publickey->setOwnerTrust(GPGME_VALIDITY_UNDEFINED);
|
|
else
|
|
publickey->setOwnerTrust(Convert::toOwnerTrust(owTrust[0]));
|
|
|
|
const QString &endDate = lsp.at(6);
|
|
if (endDate.isEmpty())
|
|
publickey->setExpiration(QDateTime());
|
|
else
|
|
publickey->setExpiration(QDateTime::fromTime_t(endDate.toUInt()));
|
|
|
|
publickey->setValid(enabled); // disabled key
|
|
|
|
idIndex = 0;
|
|
} else if (publickey && (lsp.at(0) == QLatin1String( "fpr" )) && (items >= 10)) {
|
|
const QString fingervalue(lsp.at(9));
|
|
|
|
publickey->setFingerprint(fingervalue);
|
|
} else if (publickey && (lsp.at(0) == QLatin1String( "sub" )) && (items >= 7)) {
|
|
KgpgSubKeyType subtype;
|
|
|
|
if (items > 11)
|
|
subtype = Convert::toSubType(lsp.at(11), false);
|
|
|
|
KgpgKeySub sub(lsp.at(4), lsp.at(2).toUInt(), Convert::toTrust(lsp.at(1)),
|
|
Convert::toAlgo(lsp.at(3).toInt()), subtype, QDateTime::fromTime_t(lsp.at(5).toUInt()));
|
|
|
|
// FIXME: Please see kgpgkey.h, KgpgSubKey class
|
|
if (items <= 11)
|
|
sub.setValid(true);
|
|
else
|
|
sub.setValid(!lsp.at(11).contains(QLatin1Char( 'D' )));
|
|
|
|
if (lsp.at(6).isEmpty())
|
|
sub.setExpiration(QDateTime());
|
|
else
|
|
sub.setExpiration(QDateTime::fromTime_t(lsp.at(6).toUInt()));
|
|
|
|
publickey->subList()->append(sub);
|
|
if (readNode == NULL)
|
|
currentSNode = NULL;
|
|
else
|
|
currentSNode = new KGpgSubkeyNode(readNode, sub);
|
|
} else if (publickey && (lsp.at(0) == QLatin1String( "uat" ))) {
|
|
idIndex++;
|
|
if (readNode != NULL) {
|
|
currentSNode = new KGpgUatNode(readNode, idIndex, lsp);
|
|
}
|
|
} else if (publickey && (lsp.at(0) == QLatin1String( "uid" )) && (items >= 10)) {
|
|
if (idIndex == 0) {
|
|
QString fullname(lsp.at(9));
|
|
QString kmail;
|
|
if (fullname.contains(QLatin1Char( '<' )) ) {
|
|
kmail = fullname;
|
|
|
|
if (fullname.contains(QLatin1Char( ')' )) )
|
|
kmail = kmail.section(QLatin1Char( ')' ), 1);
|
|
|
|
kmail = kmail.section(QLatin1Char( '<' ), 1);
|
|
kmail.truncate(kmail.length() - 1);
|
|
|
|
if (kmail.contains(QLatin1Char( '<' ))) {
|
|
// several email addresses in the same key
|
|
kmail = kmail.replace(QLatin1Char( '>' ), QLatin1Char( ';' ));
|
|
kmail.remove(QLatin1Char( '<' ));
|
|
}
|
|
}
|
|
|
|
QString kname(fullname.section( QLatin1String( " <" ), 0, 0));
|
|
QString comment;
|
|
if (fullname.contains(QLatin1Char( '(' )) ) {
|
|
kname = kname.section( QLatin1String( " (" ), 0, 0);
|
|
comment = fullname.section(QLatin1Char( '(' ), 1, 1);
|
|
comment = comment.section(QLatin1Char( ')' ), 0, 0);
|
|
}
|
|
|
|
idIndex++;
|
|
publickey->setEmail(kmail);
|
|
publickey->setComment(comment);
|
|
publickey->setName(kname);
|
|
|
|
currentSNode = readNode;
|
|
} else {
|
|
idIndex++;
|
|
if (readNode != NULL) {
|
|
currentSNode = new KGpgUidNode(readNode, idIndex, lsp);
|
|
}
|
|
}
|
|
} else if (publickey && ((lsp.at(0) == QLatin1String( "sig" )) || (lsp.at(0) == QLatin1String( "rev" ))) && (items >= 11)) {
|
|
// there are no strings here that could have a recoded QLatin1Char( ':' ) in them
|
|
const QString signature = lsp.join(QLatin1String(":"));
|
|
|
|
if (currentSNode != NULL)
|
|
(void) new KGpgSignNode(currentSNode, lsp);
|
|
} else {
|
|
log += lsp.join(QString(QLatin1Char( ':' ))) + QLatin1Char( '\n' );
|
|
}
|
|
}
|
|
|
|
if (p.exitCode() != 0) {
|
|
KMessageBox::detailedError(NULL, i18n("An error occurred while scanning your keyring"), log);
|
|
log.clear();
|
|
}
|
|
|
|
return publiclistkeys;
|
|
}
|
|
|
|
KgpgKeyList KgpgInterface::readPublicKeys(const QStringList &ids)
|
|
{
|
|
GPGProc process;
|
|
process <<
|
|
QLatin1String("--with-colons") <<
|
|
QLatin1String("--with-fingerprint") <<
|
|
QLatin1String("--fixed-list-mode") <<
|
|
QLatin1String("--list-keys") <<
|
|
ids;
|
|
|
|
process.setOutputChannelMode(KProcess::MergedChannels);
|
|
|
|
process.start();
|
|
process.waitForFinished(-1);
|
|
return readPublicKeysProcess(process, NULL);
|
|
}
|
|
|
|
void KgpgInterface::readSignatures(KGpgKeyNode *node)
|
|
{
|
|
GPGProc process;
|
|
process <<
|
|
QLatin1String("--with-colons") <<
|
|
QLatin1String("--with-fingerprint") <<
|
|
QLatin1String("--fixed-list-mode") <<
|
|
QLatin1String("--list-sigs") <<
|
|
node->getId();
|
|
|
|
process.setOutputChannelMode(KProcess::MergedChannels);
|
|
|
|
process.start();
|
|
process.waitForFinished(-1);
|
|
|
|
readPublicKeysProcess(process, node);
|
|
}
|
|
|
|
static KgpgCore::KgpgKeyList
|
|
readSecretKeysProcess(GPGProc &p)
|
|
{
|
|
QStringList lsp;
|
|
int items;
|
|
bool hasuid = false;
|
|
KgpgCore::KgpgKeyList result;
|
|
KgpgCore::KgpgKey *secretkey = NULL;
|
|
|
|
while ( (items = p.readln(lsp)) >= 0 ) {
|
|
if ((lsp.at(0) == QLatin1String( "sec" )) && (items >= 10)) {
|
|
KgpgSubKeyType subtype;
|
|
KgpgSubKeyType keytype;
|
|
|
|
if (items >= 11) {
|
|
const QString &caps = lsp.at(11);
|
|
|
|
subtype = Convert::toSubType(caps, false);
|
|
keytype = Convert::toSubType(caps, true);
|
|
}
|
|
|
|
result << KgpgKey(lsp.at(4), lsp.at(2).toUInt(), Convert::toTrust(lsp.at(1)),
|
|
Convert::toAlgo(lsp.at(3).toInt()), subtype, keytype,
|
|
QDateTime::fromTime_t(lsp.at(5).toUInt()));
|
|
|
|
secretkey = &result.last();
|
|
|
|
secretkey->setSecret(true);
|
|
|
|
if (lsp.at(6).isEmpty())
|
|
secretkey->setExpiration(QDateTime());
|
|
else
|
|
secretkey->setExpiration(QDateTime::fromTime_t(lsp.at(6).toUInt()));
|
|
hasuid = true;
|
|
} else if ((lsp.at(0) == QLatin1String( "uid" )) && (items >= 10)) {
|
|
if (hasuid)
|
|
continue;
|
|
|
|
hasuid = true;
|
|
|
|
const QString fullname(lsp.at(9));
|
|
if (fullname.contains(QLatin1Char( '<' ) )) {
|
|
QString kmail(fullname);
|
|
|
|
if (fullname.contains(QLatin1Char( ')' ) ))
|
|
kmail = kmail.section(QLatin1Char( ')' ), 1);
|
|
|
|
kmail = kmail.section(QLatin1Char( '<' ), 1);
|
|
kmail.truncate(kmail.length() - 1);
|
|
|
|
if (kmail.contains(QLatin1Char( '<' ) )) { // several email addresses in the same key
|
|
kmail = kmail.replace(QLatin1Char( '>' ), QLatin1Char( ';' ));
|
|
kmail.remove(QLatin1Char( '<' ));
|
|
}
|
|
|
|
secretkey->setEmail(kmail);
|
|
} else {
|
|
secretkey->setEmail(QString());
|
|
}
|
|
|
|
QString kname(fullname.section( QLatin1String( " <" ), 0, 0));
|
|
if (fullname.contains(QLatin1Char( '(' ) )) {
|
|
kname = kname.section( QLatin1String( " (" ), 0, 0);
|
|
QString comment = fullname.section(QLatin1Char( '(' ), 1, 1);
|
|
comment = comment.section(QLatin1Char( ')' ), 0, 0);
|
|
|
|
secretkey->setComment(comment);
|
|
} else {
|
|
secretkey->setComment(QString());
|
|
}
|
|
secretkey->setName(kname);
|
|
} else if ((lsp.at(0) == QLatin1String( "fpr" )) && (items >= 10)) {
|
|
secretkey->setFingerprint(lsp.at(9));
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
KgpgKeyList KgpgInterface::readSecretKeys(const QStringList &ids)
|
|
{
|
|
GPGProc process;
|
|
process <<
|
|
QLatin1String("--with-colons") <<
|
|
QLatin1String("--list-secret-keys") <<
|
|
QLatin1String("--with-fingerprint") <<
|
|
QLatin1String("--fixed-list-mode") <<
|
|
ids;
|
|
|
|
process.start();
|
|
process.waitForFinished(-1);
|
|
KgpgCore::KgpgKeyList result = readSecretKeysProcess(process);
|
|
|
|
return result;
|
|
}
|
|
|
|
#include "moc_kgpginterface.cpp"
|