Fix includes
[kdepim.git] / kleopatra / tests / test_uiserver.cpp
blob99e980447265e03a7948a1a1402cae280ec245b8
1 /* -*- mode: c++; c-basic-offset:4 -*-
2 tests/test_uiserver.cpp
4 This file is part of Kleopatra, the KDE keymanager
5 Copyright (c) 2007 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 your version of the file, but you are not obligated to do so. If
29 you do not wish to do so, delete this exception statement from
30 your version.
34 // Usage: test_uiserver <socket> --verify-detached <signed data> <signature>
37 #include <config-kleopatra.h>
39 #include <kleo-assuan.h>
40 #include <gpg-error.h>
42 #include <Libkleo/Exception>
44 #include "../utils/wsastarter.h"
45 #include "../utils/hex.h"
47 #ifndef Q_OS_WIN32
48 # include <unistd.h>
49 # include <sys/types.h>
50 # include <sys/stat.h>
51 # include <fcntl.h>
52 # include <errno.h>
53 #endif
54 #include <assert.h>
56 #include <cstdlib>
57 #include <iostream>
58 #include <map>
59 #include <string>
60 #include <vector>
62 using namespace Kleo;
64 #ifdef Q_OS_WIN32
65 static const bool HAVE_FD_PASSING = false;
66 #else
67 static const bool HAVE_FD_PASSING = true;
68 #endif
70 static const unsigned int ASSUAN_CONNECT_FLAGS = HAVE_FD_PASSING ? 1 : 0;
72 static std::vector<int> inFDs, outFDs, msgFDs;
73 static std::vector<std::string> inFiles, outFiles, msgFiles;
74 static std::map<std::string, std::string> inquireData;
76 static void usage(const std::string &msg = std::string())
78 std::cerr << msg << std::endl <<
79 "\n"
80 "Usage: test_uiserver <socket> [<io>] [<options>] [<inquire>] command [<args>]\n"
81 "where:\n"
82 #ifdef Q_OS_WIN32
83 " <io>: [--input[-fd] <file>] [--output[-fd] <file>] [--message[-fd] <file>]\n"
84 #else
85 " <io>: [--input <file>] [--output <file>] [--message <file>]\n"
86 #endif
87 " <options>: *[--option name=value]\n"
88 " <inquire>: [--inquire keyword=<file>]\n";
89 exit(1);
92 #ifndef HAVE_ASSUAN2
93 static assuan_error_t data(void *void_ctx, const void *buffer, size_t len)
95 #else
96 static gpg_error_t data(void *void_ctx, const void *buffer, size_t len)
98 #endif
99 (void)void_ctx; (void)buffer; (void)len;
100 return 0; // ### implement me
103 #ifndef HAVE_ASSUAN2
104 static assuan_error_t status(void *void_ctx, const char *line)
106 #else
107 static gpg_error_t status(void *void_ctx, const char *line)
109 #endif
110 (void)void_ctx; (void)line;
111 return 0;
114 #ifndef HAVE_ASSUAN2
115 static assuan_error_t inquire(void *void_ctx, const char *keyword)
117 #else
118 static gpg_error_t inquire(void *void_ctx, const char *keyword)
120 #endif
121 assuan_context_t ctx = (assuan_context_t)void_ctx;
122 assert(ctx);
123 const std::map<std::string, std::string>::const_iterator it = inquireData.find(keyword);
124 if (it == inquireData.end()) {
125 return gpg_error(GPG_ERR_UNKNOWN_COMMAND);
128 if (!it->second.empty() && it->second[0] == '@') {
129 return gpg_error(GPG_ERR_NOT_IMPLEMENTED);
132 if (const gpg_error_t err = assuan_send_data(ctx, it->second.c_str(), it->second.size())) {
133 qDebug("assuan_write_data: %s", gpg_strerror(err));
134 return err;
137 return 0;
140 int main(int argc, char *argv[])
143 const Kleo::WSAStarter _wsastarter;
145 #ifndef HAVE_ASSUAN2
146 assuan_set_assuan_err_source(GPG_ERR_SOURCE_DEFAULT);
147 #else
148 assuan_set_gpg_err_source(GPG_ERR_SOURCE_DEFAULT);
149 #endif
151 if (argc < 3) {
152 usage(); // need socket and command, at least
155 const char *socket = argv[1];
157 std::vector<const char *> options;
159 std::string command;
160 for (int optind = 2; optind < argc; ++optind) {
161 const char *const arg = argv[optind];
162 if (qstrcmp(arg, "--input") == 0) {
163 const std::string file = argv[++optind];
164 inFiles.push_back(file);
165 } else if (qstrcmp(arg, "--output") == 0) {
166 const std::string file = argv[++optind];
167 outFiles.push_back(file);
168 } else if (qstrcmp(arg, "--message") == 0) {
169 const std::string file = argv[++optind];
170 msgFiles.push_back(file);
171 #ifndef Q_OS_WIN32
172 } else if (qstrcmp(arg, "--input-fd") == 0) {
173 int inFD;
174 if ((inFD = open(argv[++optind], O_RDONLY)) == -1) {
175 perror("--input-fd open()");
176 return 1;
178 inFDs.push_back(inFD);
179 } else if (qstrcmp(arg, "--output-fd") == 0) {
180 int outFD;
181 if ((outFD = open(argv[++optind], O_WRONLY | O_CREAT, 0666)) == -1) {
182 perror("--output-fd open()");
183 return 1;
185 outFDs.push_back(outFD);
186 } else if (qstrcmp(arg, "--message-fd") == 0) {
187 int msgFD;
188 if ((msgFD = open(argv[++optind], O_RDONLY)) == -1) {
189 perror("--message-fd open()");
190 return 1;
192 msgFDs.push_back(msgFD);
193 #endif
194 } else if (qstrcmp(arg, "--option") == 0) {
195 options.push_back(argv[++optind]);
196 } else if (qstrcmp(arg, "--inquire") == 0) {
197 const std::string inqval = argv[++optind];
198 const size_t pos = inqval.find('=');
199 // ### implement indirection with "@file"...
200 inquireData[inqval.substr(0, pos)] = inqval.substr(pos + 1);
201 } else {
202 while (optind < argc) {
203 if (!command.empty()) {
204 command += ' ';
206 command += argv[optind++];
210 if (command.empty()) {
211 usage("Command expected, but only options found");
214 assuan_context_t ctx = 0;
216 #ifndef HAVE_ASSUAN2
217 if (const gpg_error_t err = assuan_socket_connect_ext(&ctx, socket, -1, ASSUAN_CONNECT_FLAGS)) {
218 qDebug("%s", Exception(err, "assuan_socket_connect_ext").what());
219 #else
220 if (const gpg_error_t err = assuan_new(&ctx)) {
221 qDebug("%s", Exception(err, "assuan_new").what());
222 return 1;
225 if (const gpg_error_t err = assuan_socket_connect(ctx, socket, -1, ASSUAN_CONNECT_FLAGS)) {
226 qDebug("%s", Exception(err, "assuan_socket_connect").what());
227 #endif
228 return 1;
231 assuan_set_log_stream(ctx, stderr);
233 #ifndef Q_OS_WIN32
234 for (std::vector<int>::const_iterator it = inFDs.begin(), end = inFDs.end(); it != end; ++it) {
235 if (const gpg_error_t err = assuan_sendfd(ctx, *it)) {
236 qDebug("%s", Exception(err, "assuan_sendfd( inFD )").what());
237 return 1;
240 if (const gpg_error_t err = assuan_transact(ctx, "INPUT FD", 0, 0, 0, 0, 0, 0)) {
241 qDebug("%s", Exception(err, "INPUT FD").what());
242 return 1;
246 for (std::vector<int>::const_iterator it = msgFDs.begin(), end = msgFDs.end(); it != end; ++it) {
247 if (const gpg_error_t err = assuan_sendfd(ctx, *it)) {
248 qDebug("%s", Exception(err, "assuan_sendfd( msgFD )").what());
249 return 1;
252 if (const gpg_error_t err = assuan_transact(ctx, "MESSAGE FD", 0, 0, 0, 0, 0, 0)) {
253 qDebug("%s", Exception(err, "MESSAGE FD").what());
254 return 1;
258 for (std::vector<int>::const_iterator it = outFDs.begin(), end = outFDs.end(); it != end; ++it) {
259 if (const gpg_error_t err = assuan_sendfd(ctx, *it)) {
260 qDebug("%s", Exception(err, "assuan_sendfd( outFD )").what());
261 return 1;
264 if (const gpg_error_t err = assuan_transact(ctx, "OUTPUT FD", 0, 0, 0, 0, 0, 0)) {
265 qDebug("%s", Exception(err, "OUTPUT FD").what());
266 return 1;
269 #endif
271 for (std::vector<std::string>::const_iterator it = inFiles.begin(), end = inFiles.end(); it != end; ++it) {
272 char buffer[1024];
273 sprintf(buffer, "INPUT FILE=%s", hexencode(*it).c_str());
275 if (const gpg_error_t err = assuan_transact(ctx, buffer, 0, 0, 0, 0, 0, 0)) {
276 qDebug("%s", Exception(err, buffer).what());
277 return 1;
281 for (std::vector<std::string>::const_iterator it = msgFiles.begin(), end = msgFiles.end(); it != end; ++it) {
282 char buffer[1024];
283 sprintf(buffer, "MESSAGE FILE=%s", hexencode(*it).c_str());
285 if (const gpg_error_t err = assuan_transact(ctx, buffer, 0, 0, 0, 0, 0, 0)) {
286 qDebug("%s", Exception(err, buffer).what());
287 return 1;
291 for (std::vector<std::string>::const_iterator it = outFiles.begin(), end = outFiles.end(); it != end; ++it) {
292 char buffer[1024];
293 sprintf(buffer, "OUTPUT FILE=%s", hexencode(*it).c_str());
295 if (const gpg_error_t err = assuan_transact(ctx, buffer, 0, 0, 0, 0, 0, 0)) {
296 qDebug("%s", Exception(err, buffer).what());
297 return 1;
301 Q_FOREACH (const char *opt, options) {
302 std::string line = "OPTION ";
303 line += opt;
304 if (const gpg_error_t err = assuan_transact(ctx, line.c_str(), 0, 0, 0, 0, 0, 0)) {
305 qDebug("%s", Exception(err, line).what());
306 return 1;
310 if (const gpg_error_t err = assuan_transact(ctx, command.c_str(), data, ctx, inquire, ctx, status, ctx)) {
311 qDebug("%s", Exception(err, command).what());
312 return 1;
315 #ifndef HAVE_ASSUAN2
316 assuan_disconnect(ctx);
317 #else
318 assuan_release(ctx);
319 #endif
321 return 0;