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 | |
39 | class GpgME::DecryptionResult::Private { |
40 | public: |
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 | |
78 | GpgME::DecryptionResult::DecryptionResult( gpgme_ctx_t ctx, int error ) |
79 | : GpgME::Result( error ), d() |
80 | { |
81 | init( ctx ); |
82 | } |
83 | |
84 | GpgME::DecryptionResult::DecryptionResult( gpgme_ctx_t ctx, const Error & error ) |
85 | : GpgME::Result( error ), d() |
86 | { |
87 | init( ctx ); |
88 | } |
89 | |
90 | void 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 | |
101 | make_standard_stuff(DecryptionResult) |
102 | |
103 | const char * GpgME::DecryptionResult::unsupportedAlgorithm() const { |
104 | return d ? d->res.unsupported_algorithm : 0 ; |
105 | } |
106 | |
107 | bool GpgME::DecryptionResult::isWrongKeyUsage() const { |
108 | return d && d->res.wrong_key_usage; |
109 | } |
110 | |
111 | const 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 | |
119 | unsigned 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 | |
127 | GpgME::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 | |
136 | namespace { |
137 | struct make_recipient { |
138 | GpgME::DecryptionResult::Recipient operator()( _gpgme_recipient & t ) { return GpgME::DecryptionResult::Recipient( &t ); } |
139 | }; |
140 | } |
141 | |
142 | std::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 |
157 | class GpgME::DecryptionResult::Recipient::Private : public _gpgme_recipient { |
158 | public: |
159 | Private( gpgme_recipient_t reci ) : _gpgme_recipient( *reci ) {} |
160 | }; |
161 | #endif |
162 | |
163 | GpgME::DecryptionResult::Recipient::Recipient() |
164 | : d() |
165 | { |
166 | |
167 | } |
168 | |
169 | GpgME::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 | |
179 | bool GpgME::DecryptionResult::Recipient::isNull() const { |
180 | return !d; |
181 | } |
182 | |
183 | const 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 | |
193 | const 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 | |
203 | unsigned 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 | |
212 | const 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 | |
221 | GpgME::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 | |
230 | std::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 | |
245 | std::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 | |