78a2b1b6ea7249ccb0495da387c5219f9603c01a
[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
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 <decryptionresult.h>
24 #include "result_p.h"
25 #include "util.h"
26
27 #include <gpgme.h>
28
29 #include <algorithm>
30 #include <iterator>
31 #include <cstring>
32 #include <cstdlib>
33 #include <istream>
34
35 #include <string.h>
36
37 class GpgME::DecryptionResult::Private
38 {
39 public:
40     explicit Private(const _gpgme_op_decrypt_result &r) : res(r)
41     {
42         if (res.unsupported_algorithm) {
43             res.unsupported_algorithm = strdup(res.unsupported_algorithm);
44         }
45         if (res.file_name) {
46             res.file_name = strdup(res.file_name);
47         }
48         //FIXME: copying gpgme_recipient_t objects invalidates the keyid member,
49         //thus we use _keyid for now (internal API)
50         for (gpgme_recipient_t r = res.recipients ; r ; r = r->next) {
51             recipients.push_back(*r);
52         }
53         res.recipients = 0;
54     }
55     ~Private()
56     {
57         if (res.unsupported_algorithm) {
58             std::free(res.unsupported_algorithm);
59         }
60         res.unsupported_algorithm = 0;
61         if (res.file_name) {
62             std::free(res.file_name);
63         }
64         res.file_name = 0;
65     }
66
67     _gpgme_op_decrypt_result res;
68     std::vector<_gpgme_recipient> recipients;
69 };
70
71 GpgME::DecryptionResult::DecryptionResult(gpgme_ctx_t ctx, int error)
72     : GpgME::Result(error), d()
73 {
74     init(ctx);
75 }
76
77 GpgME::DecryptionResult::DecryptionResult(gpgme_ctx_t ctx, const Error &error)
78     : GpgME::Result(error), d()
79 {
80     init(ctx);
81 }
82
83 void GpgME::DecryptionResult::init(gpgme_ctx_t ctx)
84 {
85     if (!ctx) {
86         return;
87     }
88     gpgme_decrypt_result_t res = gpgme_op_decrypt_result(ctx);
89     if (!res) {
90         return;
91     }
92     d.reset(new Private(*res));
93 }
94
95 make_standard_stuff(DecryptionResult)
96
97 const char *GpgME::DecryptionResult::unsupportedAlgorithm() const
98 {
99     return d ? d->res.unsupported_algorithm : 0 ;
100 }
101
102 bool GpgME::DecryptionResult::isWrongKeyUsage() const
103 {
104     return d && d->res.wrong_key_usage;
105 }
106
107 const char *GpgME::DecryptionResult::fileName() const
108 {
109     return d ? d->res.file_name : 0 ;
110 }
111
112 unsigned int GpgME::DecryptionResult::numRecipients() const
113 {
114     return d ? d->recipients.size() : 0 ;
115 }
116
117 GpgME::DecryptionResult::Recipient GpgME::DecryptionResult::recipient(unsigned int idx) const
118 {
119     if (d && idx < d->recipients.size()) {
120         return Recipient(&d->recipients[idx]);
121     }
122     return Recipient();
123 }
124
125 namespace
126 {
127 struct make_recipient {
128     GpgME::DecryptionResult::Recipient operator()(_gpgme_recipient &t)
129     {
130         return GpgME::DecryptionResult::Recipient(&t);
131     }
132 };
133 }
134
135 std::vector<GpgME::DecryptionResult::Recipient> GpgME::DecryptionResult::recipients() const
136 {
137     std::vector<Recipient> result;
138     if (d) {
139         result.reserve(d->recipients.size());
140         std::transform(d->recipients.begin(), d->recipients.end(),
141                        std::back_inserter(result),
142                        make_recipient());
143     }
144     return result;
145 }
146
147 class GpgME::DecryptionResult::Recipient::Private : public _gpgme_recipient
148 {
149 public:
150     Private(gpgme_recipient_t reci) : _gpgme_recipient(*reci) {}
151 };
152
153 GpgME::DecryptionResult::Recipient::Recipient()
154     : d()
155 {
156
157 }
158
159 GpgME::DecryptionResult::Recipient::Recipient(gpgme_recipient_t r)
160     : d()
161 {
162     if (r) {
163         d.reset(new Private(r));
164     }
165 }
166
167 bool GpgME::DecryptionResult::Recipient::isNull() const
168 {
169     return !d;
170 }
171
172 const char *GpgME::DecryptionResult::Recipient::keyID() const
173 {
174     //_keyid is internal API, but the public keyid is invalid after copying (see above)
175     if (d) {
176         return d->_keyid;
177     }
178     return 0;
179 }
180
181 const char *GpgME::DecryptionResult::Recipient::shortKeyID() const
182 {
183     //_keyid is internal API, but the public keyid is invalid after copying (see above)
184     if (d) {
185         return d->_keyid + 8;
186     }
187     return 0;
188 }
189
190 unsigned int GpgME::DecryptionResult::Recipient::publicKeyAlgorithm() const
191 {
192     if (d) {
193         return d->pubkey_algo;
194     }
195     return 0;
196 }
197
198 const char *GpgME::DecryptionResult::Recipient::publicKeyAlgorithmAsString() const
199 {
200     if (d) {
201         return gpgme_pubkey_algo_name(d->pubkey_algo);
202     }
203     return 0;
204 }
205
206 GpgME::Error GpgME::DecryptionResult::Recipient::status() const
207 {
208     if (d) {
209         return Error(d->status);
210     }
211     return Error();
212 }
213
214 std::ostream &GpgME::operator<<(std::ostream &os, const DecryptionResult &result)
215 {
216     os << "GpgME::DecryptionResult(";
217     if (!result.isNull()) {
218         os << "\n error:                " << result.error()
219            << "\n fileName:             " << protect(result.fileName())
220            << "\n unsupportedAlgorithm: " << protect(result.unsupportedAlgorithm())
221            << "\n isWrongKeyUsage:      " << result.isWrongKeyUsage()
222            << "\n recipients:\n";
223         const std::vector<DecryptionResult::Recipient> recipients = result.recipients();
224         std::copy(recipients.begin(), recipients.end(),
225                   std::ostream_iterator<DecryptionResult::Recipient>(os, "\n"));
226     }
227     return os << ')';
228 }
229
230 std::ostream &GpgME::operator<<(std::ostream &os, const DecryptionResult::Recipient &reci)
231 {
232     os << "GpgME::DecryptionResult::Recipient(";
233     if (!reci.isNull()) {
234         os << "\n keyID:              " << protect(reci.keyID())
235            << "\n shortKeyID:         " << protect(reci.shortKeyID())
236            << "\n publicKeyAlgorithm: " << protect(reci.publicKeyAlgorithmAsString())
237            << "\n status:             " << reci.status();
238     }
239     return os << ')';
240 }