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