Better wording
[kdepim.git] / kleopatra / uiserver / signcommand.cpp
blobba787b40f8b9dec1a59bc29f68a182cbb013401f
1 /* -*- mode: c++; c-basic-offset:4 -*-
2 uiserver/signcommand.cpp
4 This file is part of Kleopatra, the KDE keymanager
5 Copyright (c) 2010 Klarälvdalens Datakonsult AB
7 Kleopatra 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.
12 Kleopatra is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 In addition, as a special exception, the copyright holders give
22 permission to link the code of this program with any edition of
23 the Qt library by Trolltech AS, Norway (or with modified versions
24 of Qt that use the same license as Qt), and distribute linked
25 combinations including the two. You must obey the GNU General
26 Public License in all respects for all of the code used other than
27 Qt. If you modify this file, you may extend this exception to
28 you do not wish to do so, delete this exception statement from
29 your version of the file, but you are not obligated to do so. If
30 your version.
33 #include <config-kleopatra.h>
35 #include "signcommand.h"
37 #include <crypto/newsignencryptemailcontroller.h>
39 #include <utils/kleo_assert.h>
40 #include <utils/input.h>
41 #include <utils/output.h>
43 #include <kleo/exception.h>
45 #include <KLocale>
47 #include <QTimer>
49 using namespace Kleo;
50 using namespace Kleo::Crypto;
51 using namespace boost;
53 class SignCommand::Private : public QObject {
54 Q_OBJECT
55 private:
56 friend class ::Kleo::SignCommand;
57 SignCommand * const q;
58 public:
59 explicit Private( SignCommand * qq )
60 : q( qq ), controller()
65 private:
66 void checkForErrors() const;
68 private Q_SLOTS:
69 void slotSignersResolved();
70 void slotMicAlgDetermined( const QString & );
71 void slotDone();
72 void slotError( int, const QString & );
74 private:
75 shared_ptr<NewSignEncryptEMailController> controller;
78 SignCommand::SignCommand()
79 : AssuanCommandMixin<SignCommand>(), d( new Private( this ) )
84 SignCommand::~SignCommand() {}
86 void SignCommand::Private::checkForErrors() const {
88 if ( q->numFiles() )
89 throw Exception( makeError( GPG_ERR_CONFLICT ),
90 i18n( "SIGN is an email mode command, connection seems to be in filemanager mode" ) );
92 if ( !q->recipients().empty() && !q->informativeRecipients() )
93 throw Exception( makeError( GPG_ERR_CONFLICT ),
94 i18n( "RECIPIENT may not be given prior to SIGN, except with --info" ) );
96 if ( q->inputs().empty() )
97 throw Exception( makeError( GPG_ERR_ASS_NO_INPUT ),
98 i18n( "At least one INPUT must be present" ) );
100 if ( q->outputs().size() != q->inputs().size() )
101 throw Exception( makeError( GPG_ERR_ASS_NO_INPUT ),
102 i18n( "INPUT/OUTPUT count mismatch" ) );
104 if ( !q->messages().empty() )
105 throw Exception( makeError( GPG_ERR_INV_VALUE ),
106 i18n( "MESSAGE command is not allowed before SIGN" ) );
108 const shared_ptr<NewSignEncryptEMailController> m = q->mementoContent< shared_ptr<NewSignEncryptEMailController> >( NewSignEncryptEMailController::mementoName() );
110 if ( m && m->isSigning() ) {
112 if ( m->protocol() != q->checkProtocol( EMail ) )
113 throw Exception( makeError( GPG_ERR_CONFLICT ),
114 i18n( "Protocol given conflicts with protocol determined by PREP_ENCRYPT in this session" ) );
116 // ### check that any SENDER here is the same as the one for PREP_ENCRYPT
118 // ### ditto RECIPIENT
120 } else {
122 // ### support the stupid "default signer" semantics of GpgOL
123 // ### where SENDER is missing
124 if ( false )
125 if ( q->senders().empty() || q->informativeSenders() )
126 throw Exception( makeError( GPG_ERR_MISSING_VALUE ),
127 i18n( "No senders given, or only with --info" ) );
133 static void connectController( const QObject * controller, const QObject * d ) {
134 QObject::connect( controller, SIGNAL(certificatesResolved()), d, SLOT(slotSignersResolved()) );
135 QObject::connect( controller, SIGNAL(reportMicAlg(QString)), d, SLOT(slotMicAlgDetermined(QString)) );
136 QObject::connect( controller, SIGNAL(done()), d, SLOT(slotDone()) );
137 QObject::connect( controller, SIGNAL(error(int,QString)), d, SLOT(slotError(int,QString)) );
140 int SignCommand::doStart() {
142 d->checkForErrors();
144 const shared_ptr<NewSignEncryptEMailController> seec = mementoContent< shared_ptr<NewSignEncryptEMailController> >( NewSignEncryptEMailController::mementoName() );
146 if ( seec && seec->isSigning() ) {
147 // reuse the controller from a previous PREP_ENCRYPT --expect-sign, if available:
148 d->controller = seec;
149 connectController( seec.get(), d.get() );
150 if ( !seec->isEncrypting() )
151 removeMemento( NewSignEncryptEMailController::mementoName() );
152 seec->setExecutionContext( shared_from_this() );
153 if ( seec->areCertificatesResolved() )
154 QTimer::singleShot( 0, d.get(), SLOT(slotSignersResolved()) );
155 else
156 kleo_assert( seec->isResolvingInProgress() );
157 } else {
158 // use a new controller
159 d->controller.reset( new NewSignEncryptEMailController( shared_from_this() ) );
161 const QString session = sessionTitle();
162 if ( !session.isEmpty() )
163 d->controller->setSubject( session );
165 d->controller->setSigning( true );
166 d->controller->setEncrypting( false );
167 d->controller->setProtocol( checkProtocol( EMail, AssuanCommand::AllowProtocolMissing ) );
168 connectController( d->controller.get(), d.get() );
169 d->controller->startResolveCertificates( recipients(), senders() );
173 return 0;
176 void SignCommand::Private::slotSignersResolved() {
177 //hold local shared_ptr to member as q->done() deletes *this
178 const shared_ptr<NewSignEncryptEMailController> cont( controller );
180 try {
181 const QString sessionTitle = q->sessionTitle();
182 if ( !sessionTitle.isEmpty() )
183 Q_FOREACH ( const shared_ptr<Input> & i, q->inputs() )
184 i->setLabel( sessionTitle );
186 cont->setDetachedSignature( q->hasOption("detached" ) );
187 cont->startSigning( q->inputs(), q->outputs() );
189 return;
191 } catch ( const Exception & e ) {
192 q->done( e.error(), e.message() );
193 } catch ( const std::exception & e ) {
194 q->done( makeError( GPG_ERR_UNEXPECTED ),
195 i18n("Caught unexpected exception in SignCommand::Private::slotRecipientsResolved: %1",
196 QString::fromLocal8Bit( e.what() ) ) );
197 } catch ( ... ) {
198 q->done( makeError( GPG_ERR_UNEXPECTED ),
199 i18n("Caught unknown exception in SignCommand::Private::slotRecipientsResolved") );
201 cont->cancel();
204 void SignCommand::Private::slotMicAlgDetermined( const QString & micalg ) {
205 //hold local shared_ptr to member as q->done() deletes *this
206 const shared_ptr<NewSignEncryptEMailController> cont( controller );
208 try {
210 q->sendStatus( "MICALG", micalg );
211 return;
213 } catch ( const Exception & e ) {
214 q->done( e.error(), e.message() );
215 } catch ( const std::exception & e ) {
216 q->done( makeError( GPG_ERR_UNEXPECTED ),
217 i18n("Caught unexpected exception in SignCommand::Private::slotMicAlgDetermined: %1",
218 QString::fromLocal8Bit( e.what() ) ) );
219 } catch ( ... ) {
220 q->done( makeError( GPG_ERR_UNEXPECTED ),
221 i18n("Caught unknown exception in SignCommand::Private::slotMicAlgDetermined") );
223 cont->cancel();
226 void SignCommand::Private::slotDone() {
227 q->done();
230 void SignCommand::Private::slotError( int err, const QString & details ) {
231 q->done( err, details );
234 void SignCommand::doCanceled() {
235 if ( d->controller )
236 d->controller->cancel();
239 #include "signcommand.moc"