1/*
2 decryptionresult.cpp - wraps a gpgme keygen result
3 Copyright (C) 2004 Klarälvdalens Datakonsult AB
4
5 This file is part of GPGME++.
6
7 GPGME++ is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 GPGME++ 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
15 GNU Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public License
18 along with GPGME++; see the file COPYING.LIB. If not, write to the
19 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21*/
22
23#include <config-gpgme++.h>
24
25#include <gpgme++/decryptionresult.h>
26#include "result_p.h"
27#include "util.h"
28
29#include <gpgme.h>
30
31#include <algorithm>
32#include <iterator>
33#include <cstring>
34#include <cstdlib>
35#include <istream>
36
37#include <string.h>
38
39class GpgME::DecryptionResult::Private {
40public:
41 explicit Private( const _gpgme_op_decrypt_result & r ) : res( r ) {
42 if ( res.unsupported_algorithm ) {
43 res.unsupported_algorithm = strdup( res.unsupported_algorithm );
44 }
45#ifdef HAVE_GPGME_DECRYPT_RESULT_T_FILE_NAME
46 if ( res.file_name ) {
47 res.file_name = strdup( res.file_name );
48 }
49#endif
50#ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS
51 //FIXME: copying gpgme_recipient_t objects invalidates the keyid member,
52 //thus we use _keyid for now (internal API)
53 for ( gpgme_recipient_t r = res.recipients ; r ; r = r->next ) {
54 recipients.push_back( *r );
55 }
56 res.recipients = 0;
57#endif
58 }
59 ~Private() {
60 if ( res.unsupported_algorithm ) {
61 std::free( res.unsupported_algorithm );
62 }
63 res.unsupported_algorithm = 0;
64#ifdef HAVE_GPGME_DECRYPT_RESULT_T_FILE_NAME
65 if ( res.file_name ) {
66 std::free( res.file_name );
67 }
68 res.file_name = 0;
69#endif
70 }
71
72 _gpgme_op_decrypt_result res;
73#ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS
74 std::vector<_gpgme_recipient> recipients;
75#endif
76};
77
78GpgME::DecryptionResult::DecryptionResult( gpgme_ctx_t ctx, int error )
79 : GpgME::Result( error ), d()
80{
81 init( ctx );
82}
83
84GpgME::DecryptionResult::DecryptionResult( gpgme_ctx_t ctx, const Error & error )
85 : GpgME::Result( error ), d()
86{
87 init( ctx );
88}
89
90void GpgME::DecryptionResult::init( gpgme_ctx_t ctx ) {
91 if ( !ctx ) {
92 return;
93 }
94 gpgme_decrypt_result_t res = gpgme_op_decrypt_result( ctx );
95 if ( !res ) {
96 return;
97 }
98 d.reset( new Private( *res ) );
99}
100
101make_standard_stuff(DecryptionResult)
102
103const char * GpgME::DecryptionResult::unsupportedAlgorithm() const {
104 return d ? d->res.unsupported_algorithm : 0 ;
105}
106
107bool GpgME::DecryptionResult::isWrongKeyUsage() const {
108 return d && d->res.wrong_key_usage;
109}
110
111const char * GpgME::DecryptionResult::fileName() const {
112#ifdef HAVE_GPGME_DECRYPT_RESULT_T_FILE_NAME
113 return d ? d->res.file_name : 0 ;
114#else
115 return 0;
116#endif
117}
118
119unsigned int GpgME::DecryptionResult::numRecipients() const {
120#ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS
121 return d ? d->recipients.size() : 0 ;
122#else
123 return 0;
124#endif
125}
126
127GpgME::DecryptionResult::Recipient GpgME::DecryptionResult::recipient( unsigned int idx ) const {
128#ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS
129 if ( d && idx < d->recipients.size() ) {
130 return Recipient( &d->recipients[idx] );
131 }
132#endif
133 return Recipient();
134}
135
136namespace {
137 struct make_recipient {
138 GpgME::DecryptionResult::Recipient operator()( _gpgme_recipient & t ) { return GpgME::DecryptionResult::Recipient( &t ); }
139 };
140}
141
142std::vector<GpgME::DecryptionResult::Recipient> GpgME::DecryptionResult::recipients() const {
143 std::vector<Recipient> result;
144#ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS
145 if ( d ) {
146 result.reserve( d->recipients.size() );
147 std::transform( d->recipients.begin(), d->recipients.end(),
148 std::back_inserter( result ),
149 make_recipient() );
150 }
151#endif
152 return result;
153}
154
155
156#ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS
157class GpgME::DecryptionResult::Recipient::Private : public _gpgme_recipient {
158public:
159 Private( gpgme_recipient_t reci ) : _gpgme_recipient( *reci ) {}
160};
161#endif
162
163GpgME::DecryptionResult::Recipient::Recipient()
164 : d()
165{
166
167}
168
169GpgME::DecryptionResult::Recipient::Recipient( gpgme_recipient_t r )
170 : d()
171{
172#ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS
173 if ( r ) {
174 d.reset( new Private( r ) );
175 }
176#endif
177}
178
179bool GpgME::DecryptionResult::Recipient::isNull() const {
180 return !d;
181}
182
183const char * GpgME::DecryptionResult::Recipient::keyID() const {
184#ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS
185 //_keyid is internal API, but the public keyid is invalid after copying (see above)
186 if ( d ) {
187 return d->_keyid;
188 }
189#endif
190 return 0;
191}
192
193const char * GpgME::DecryptionResult::Recipient::shortKeyID() const {
194#ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS
195 //_keyid is internal API, but the public keyid is invalid after copying (see above)
196 if ( d ) {
197 return d->_keyid + 8;
198 }
199#endif
200 return 0;
201}
202
203unsigned int GpgME::DecryptionResult::Recipient::publicKeyAlgorithm() const {
204#ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS
205 if ( d ) {
206 return d->pubkey_algo;
207 }
208#endif
209 return 0;
210}
211
212const char * GpgME::DecryptionResult::Recipient::publicKeyAlgorithmAsString() const {
213#ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS
214 if ( d ) {
215 return gpgme_pubkey_algo_name( d->pubkey_algo );
216 }
217#endif
218 return 0;
219}
220
221GpgME::Error GpgME::DecryptionResult::Recipient::status() const {
222#ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS
223 if ( d ) {
224 return Error( d->status );
225 }
226#endif
227 return Error();
228}
229
230std::ostream & GpgME::operator<<( std::ostream & os, const DecryptionResult & result ) {
231 os << "GpgME::DecryptionResult(";
232 if ( !result.isNull() ) {
233 os << "\n error: " << result.error()
234 << "\n fileName: " << protect( result.fileName() )
235 << "\n unsupportedAlgorithm: " << protect( result.unsupportedAlgorithm() )
236 << "\n isWrongKeyUsage: " << result.isWrongKeyUsage()
237 << "\n recipients:\n";
238 const std::vector<DecryptionResult::Recipient> recipients = result.recipients();
239 std::copy( recipients.begin(), recipients.end(),
240 std::ostream_iterator<DecryptionResult::Recipient>( os, "\n" ) );
241 }
242 return os << ')';
243}
244
245std::ostream & GpgME::operator<<( std::ostream & os, const DecryptionResult::Recipient & reci ) {
246 os << "GpgME::DecryptionResult::Recipient(";
247 if ( !reci.isNull() ) {
248 os << "\n keyID: " << protect( reci.keyID() )
249 << "\n shortKeyID: " << protect( reci.shortKeyID() )
250 << "\n publicKeyAlgorithm: " << protect( reci.publicKeyAlgorithmAsString() )
251 << "\n status: " << reci.status();
252 }
253 return os << ')';
254}
255