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
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"
49 # include <sys/types.h>
50 # include <sys/stat.h>
65 static const bool HAVE_FD_PASSING
= false;
67 static const bool HAVE_FD_PASSING
= true;
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
<<
80 "Usage: test_uiserver <socket> [<io>] [<options>] [<inquire>] command [<args>]\n"
83 " <io>: [--input[-fd] <file>] [--output[-fd] <file>] [--message[-fd] <file>]\n"
85 " <io>: [--input <file>] [--output <file>] [--message <file>]\n"
87 " <options>: *[--option name=value]\n"
88 " <inquire>: [--inquire keyword=<file>]\n";
93 static assuan_error_t
data(void *void_ctx
, const void *buffer
, size_t len
)
96 static gpg_error_t
data(void *void_ctx
, const void *buffer
, size_t len
)
99 (void)void_ctx
; (void)buffer
; (void)len
;
100 return 0; // ### implement me
104 static assuan_error_t
status(void *void_ctx
, const char *line
)
107 static gpg_error_t
status(void *void_ctx
, const char *line
)
110 (void)void_ctx
; (void)line
;
115 static assuan_error_t
inquire(void *void_ctx
, const char *keyword
)
118 static gpg_error_t
inquire(void *void_ctx
, const char *keyword
)
121 assuan_context_t ctx
= (assuan_context_t
)void_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
));
140 int main(int argc
, char *argv
[])
143 const Kleo::WSAStarter _wsastarter
;
146 assuan_set_assuan_err_source(GPG_ERR_SOURCE_DEFAULT
);
148 assuan_set_gpg_err_source(GPG_ERR_SOURCE_DEFAULT
);
152 usage(); // need socket and command, at least
155 const char *socket
= argv
[1];
157 std::vector
<const char *> options
;
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
);
172 } else if (qstrcmp(arg
, "--input-fd") == 0) {
174 if ((inFD
= open(argv
[++optind
], O_RDONLY
)) == -1) {
175 perror("--input-fd open()");
178 inFDs
.push_back(inFD
);
179 } else if (qstrcmp(arg
, "--output-fd") == 0) {
181 if ((outFD
= open(argv
[++optind
], O_WRONLY
| O_CREAT
, 0666)) == -1) {
182 perror("--output-fd open()");
185 outFDs
.push_back(outFD
);
186 } else if (qstrcmp(arg
, "--message-fd") == 0) {
188 if ((msgFD
= open(argv
[++optind
], O_RDONLY
)) == -1) {
189 perror("--message-fd open()");
192 msgFDs
.push_back(msgFD
);
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);
202 while (optind
< argc
) {
203 if (!command
.empty()) {
206 command
+= argv
[optind
++];
210 if (command
.empty()) {
211 usage("Command expected, but only options found");
214 assuan_context_t ctx
= 0;
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());
220 if (const gpg_error_t err
= assuan_new(&ctx
)) {
221 qDebug("%s", Exception(err
, "assuan_new").what());
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());
231 assuan_set_log_stream(ctx
, stderr
);
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());
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());
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());
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());
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());
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());
271 for (std::vector
<std::string
>::const_iterator it
= inFiles
.begin(), end
= inFiles
.end(); it
!= end
; ++it
) {
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());
281 for (std::vector
<std::string
>::const_iterator it
= msgFiles
.begin(), end
= msgFiles
.end(); it
!= end
; ++it
) {
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());
291 for (std::vector
<std::string
>::const_iterator it
= outFiles
.begin(), end
= outFiles
.end(); it
!= end
; ++it
) {
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());
301 Q_FOREACH (const char *opt
, options
) {
302 std::string line
= "OPTION ";
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());
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());
316 assuan_disconnect(ctx
);