diff options
Diffstat (limited to 'lang/cpp/tests')
-rw-r--r-- | lang/cpp/tests/Makefile.am | 45 | ||||
-rw-r--r-- | lang/cpp/tests/README | 4 | ||||
-rw-r--r-- | lang/cpp/tests/run-getkey.cpp | 158 | ||||
-rw-r--r-- | lang/cpp/tests/run-keylist.cpp | 172 | ||||
-rw-r--r-- | lang/cpp/tests/run-verify.cpp | 185 | ||||
-rw-r--r-- | lang/cpp/tests/run-wkdlookup.cpp | 158 |
6 files changed, 0 insertions, 722 deletions
diff --git a/lang/cpp/tests/Makefile.am b/lang/cpp/tests/Makefile.am deleted file mode 100644 index 9e67dff3..00000000 --- a/lang/cpp/tests/Makefile.am +++ /dev/null @@ -1,45 +0,0 @@ -# Makefile.am - Makefile for GPGME Cpp tests. -# Copyright (C) 2018 Intevation GmbH -# -# This file is part of GPGME. -# -# GPGME is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as -# published by the Free Software Foundation; either version 2.1 of the -# License, or (at your option) any later version. -# -# GPGME is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General -# Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this program; if not, see <https://www.gnu.org/licenses/>. - -## Process this file with automake to produce Makefile.in - -AM_LDFLAGS = -no-install - -LDADD = ../../cpp/src/libgpgmepp.la \ - ../../../src/libgpgme.la @GPG_ERROR_LIBS@ \ - @LDADD_FOR_TESTS_KLUDGE@ -lstdc++ - -AM_CPPFLAGS = -I$(top_srcdir)/lang/cpp/src -I$(top_builddir)/src \ - @GPG_ERROR_CFLAGS@ @GPG_ERROR_CFLAGS@ \ - @LIBASSUAN_CFLAGS@ -DBUILDING_GPGMEPP \ - -DTOP_SRCDIR="$(top_srcdir)" - -run_getkey_SOURCES = run-getkey.cpp -run_keylist_SOURCES = run-keylist.cpp -run_verify_SOURCES = run-verify.cpp -if !HAVE_W32_SYSTEM -run_wkdlookup_SOURCES = run-wkdlookup.cpp -endif - -if HAVE_W32_SYSTEM -programs_unix = -else -programs_unix = run-wkdlookup -endif - -noinst_PROGRAMS = run-getkey run-keylist run-verify $(programs_unix) diff --git a/lang/cpp/tests/README b/lang/cpp/tests/README deleted file mode 100644 index ac74ab00..00000000 --- a/lang/cpp/tests/README +++ /dev/null @@ -1,4 +0,0 @@ -Tests for the C++ bindings. - -Most autotests for the C++ bindings use the QTest framework -and live in lang/qt/tests. diff --git a/lang/cpp/tests/run-getkey.cpp b/lang/cpp/tests/run-getkey.cpp deleted file mode 100644 index 97d863e1..00000000 --- a/lang/cpp/tests/run-getkey.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* - run-getkey.cpp - - This file is part of GpgMEpp's test suite. - Copyright (c) 2018 Intevation GmbH - - QGpgME is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - QGpgME is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - - In addition, as a special exception, the copyright holders give - permission to link the code of this program with any edition of - the Qt library by Trolltech AS, Norway (or with modified versions - of Qt that use the same license as Qt), and distribute linked - combinations including the two. You must obey the GNU General - Public License in all respects for all of the code used other than - Qt. If you modify this file, you may extend this exception to - your version of the file, but you are not obligated to do so. If - you do not wish to do so, delete this exception statement from - your version. -*/ - -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif - -#include "context.h" -#include "key.h" - -#include <memory> -#include <sstream> -#include <iostream> - -using namespace GpgME; - -static int -show_usage (int ex) -{ - fputs ("usage: run-getkey [options] [keyIdOrFingerprint]\n\n" - "Options:\n" - " --verbose run in verbose mode\n" - " --openpgp use the OpenPGP protocol (default)\n" - " --cms use the CMS protocol\n" - " --secret list only secret keys\n" - " --with-secret list pubkeys with secret info filled\n" - " --local use GPGME_KEYLIST_MODE_LOCAL\n" - " --extern use GPGME_KEYLIST_MODE_EXTERN\n" - " --sigs use GPGME_KEYLIST_MODE_SIGS\n" - " --tofu use GPGME_KEYLIST_MODE_TOFU\n" - " --sig-notations use GPGME_KEYLIST_MODE_SIG_NOTATIONS\n" - " --ephemeral use GPGME_KEYLIST_MODE_EPHEMERAL\n" - " --validate use GPGME_KEYLIST_MODE_VALIDATE\n" - " --locate use GPGME_KEYLIST_MODE_LOCATE\n" - " --force-extern use GPGME_KEYLIST_MODE_FORCE_EXTERN\n" - " --locate-external use GPGME_KEYLIST_MODE_LOCATE_EXTERNAL\n" - , stderr); - exit (ex); -} - -int -main (int argc, char **argv) -{ - int last_argc = -1; - Protocol protocol = OpenPGP; - unsigned int mode = 0; - bool only_secret = false; - - if (argc) { - argc--; argv++; - } - - while (argc && last_argc != argc ) { - last_argc = argc; - if (!strcmp (*argv, "--")) { - argc--; argv++; - break; - } else if (!strcmp (*argv, "--help")) { - show_usage (0); - } else if (!strcmp (*argv, "--openpgp")) { - protocol = OpenPGP; - argc--; argv++; - } else if (!strcmp (*argv, "--cms")) { - protocol = CMS; - argc--; argv++; - } else if (!strcmp (*argv, "--secret")) { - only_secret = true; - argc--; argv++; - } else if (!strcmp (*argv, "--local")) { - mode |= KeyListMode::Local; - argc--; argv++; - } else if (!strcmp (*argv, "--extern")) { - mode |= KeyListMode::Extern; - argc--; argv++; - }else if (!strcmp (*argv, "--tofu")) { - mode |= KeyListMode::WithTofu; - argc--; argv++; - } else if (!strcmp (*argv, "--sigs")) { - mode |= KeyListMode::Signatures; - argc--; argv++; - } else if (!strcmp (*argv, "--sig-notations")) { - mode |= KeyListMode::SignatureNotations; - argc--; argv++; - } else if (!strcmp (*argv, "--ephemeral")) { - mode |= KeyListMode::Ephemeral; - argc--; argv++; - } else if (!strcmp (*argv, "--validate")) { - mode |= KeyListMode::Validate; - argc--; argv++; - } else if (!strcmp (*argv, "--locate")) { - argc--; argv++; - mode |= KeyListMode::Locate; - } else if (!strcmp (*argv, "--force-extern")) { - argc--; argv++; - mode |= KeyListMode::ForceExtern; - } else if (!strcmp (*argv, "--locate-external")) { - argc--; argv++; - mode |= KeyListMode::LocateExternal; - } else if (!strncmp (*argv, "--", 2)) { - show_usage (1); - } - } - - if (argc != 1) { - show_usage (1); - } - - GpgME::initializeLibrary(); - auto ctx = std::unique_ptr<Context> (Context::createForProtocol(protocol)); - if (!ctx) { - std::cerr << "Failed to get Context"; - return -1; - } - ctx->setKeyListMode (mode); - if (ctx->keyListMode() != mode) { - // unfortunately, Context::setKeyListMode() does not return the error - // returned by gpgme - std::cerr << "Failed to set keylist mode. You may have used an invalid combination of options."; - return -1; - } - Error err; - const GpgME::Key key = ctx->key (*argv, err, only_secret); - std::stringstream ss; - - ss << "Key " << key << " Err: " << err.asStdString() << "\n"; - - std::cout << ss.str(); - - return 0; -} diff --git a/lang/cpp/tests/run-keylist.cpp b/lang/cpp/tests/run-keylist.cpp deleted file mode 100644 index 6581567c..00000000 --- a/lang/cpp/tests/run-keylist.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/* - run-keylist.cpp - - This file is part of GpgMEpp's test suite. - Copyright (c) 2018 Intevation GmbH - - QGpgME is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - QGpgME is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - - In addition, as a special exception, the copyright holders give - permission to link the code of this program with any edition of - the Qt library by Trolltech AS, Norway (or with modified versions - of Qt that use the same license as Qt), and distribute linked - combinations including the two. You must obey the GNU General - Public License in all respects for all of the code used other than - Qt. If you modify this file, you may extend this exception to - your version of the file, but you are not obligated to do so. If - you do not wish to do so, delete this exception statement from - your version. -*/ - -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif - -#include "context.h" -#include "key.h" -#include "keylistresult.h" - -#include <memory> -#include <sstream> -#include <iostream> - -using namespace GpgME; - -static int -show_usage (int ex) -{ - fputs ("usage: run-keylist [options] [pattern]\n\n" - "Options:\n" - " --verbose run in verbose mode\n" - " --openpgp use the OpenPGP protocol (default)\n" - " --cms use the CMS protocol\n" - " --secret list only secret keys\n" - " --with-secret list pubkeys with secret info filled\n" - " --local use GPGME_KEYLIST_MODE_LOCAL\n" - " --extern use GPGME_KEYLIST_MODE_EXTERN\n" - " --sigs use GPGME_KEYLIST_MODE_SIGS\n" - " --tofu use GPGME_KEYLIST_MODE_TOFU\n" - " --sig-notations use GPGME_KEYLIST_MODE_SIG_NOTATIONS\n" - " --ephemeral use GPGME_KEYLIST_MODE_EPHEMERAL\n" - " --validate use GPGME_KEYLIST_MODE_VALIDATE\n" - " --locate use GPGME_KEYLIST_MODE_LOCATE\n" - " --force-extern use GPGME_KEYLIST_MODE_FORCE_EXTERN\n" - " --locate-external use GPGME_KEYLIST_MODE_LOCATE_EXTERNAL\n" - , stderr); - exit (ex); -} - -int -main (int argc, char **argv) -{ - int last_argc = -1; - Protocol protocol = OpenPGP; - unsigned int mode = 0; - bool only_secret = false; - - if (argc) { - argc--; argv++; - } - - while (argc && last_argc != argc ) { - last_argc = argc; - if (!strcmp (*argv, "--")) { - argc--; argv++; - break; - } else if (!strcmp (*argv, "--help")) { - show_usage (0); - } else if (!strcmp (*argv, "--openpgp")) { - protocol = OpenPGP; - argc--; argv++; - } else if (!strcmp (*argv, "--cms")) { - protocol = CMS; - argc--; argv++; - } else if (!strcmp (*argv, "--secret")) { - only_secret = true; - argc--; argv++; - } else if (!strcmp (*argv, "--local")) { - mode |= KeyListMode::Local; - argc--; argv++; - } else if (!strcmp (*argv, "--extern")) { - mode |= KeyListMode::Extern; - argc--; argv++; - }else if (!strcmp (*argv, "--tofu")) { - mode |= KeyListMode::WithTofu; - argc--; argv++; - } else if (!strcmp (*argv, "--sigs")) { - mode |= KeyListMode::Signatures; - argc--; argv++; - } else if (!strcmp (*argv, "--sig-notations")) { - mode |= KeyListMode::SignatureNotations; - argc--; argv++; - } else if (!strcmp (*argv, "--ephemeral")) { - mode |= KeyListMode::Ephemeral; - argc--; argv++; - } else if (!strcmp (*argv, "--validate")) { - mode |= KeyListMode::Validate; - argc--; argv++; - } else if (!strcmp (*argv, "--locate")) { - argc--; argv++; - mode |= KeyListMode::Locate; - } else if (!strcmp (*argv, "--with-secret")) { - argc--; argv++; - mode |= KeyListMode::WithSecret; - } else if (!strcmp (*argv, "--force-extern")) { - argc--; argv++; - mode |= KeyListMode::ForceExtern; - } else if (!strcmp (*argv, "--locate-external")) { - argc--; argv++; - mode |= KeyListMode::LocateExternal; - } else if (!strncmp (*argv, "--", 2)) { - std::cerr << "Error: Unknown option: " << *argv << std::endl; - show_usage (1); - } - } - - if (argc > 1) { - show_usage (1); - } - - GpgME::initializeLibrary(); - auto ctx = std::unique_ptr<Context> (Context::createForProtocol(protocol)); - if (!ctx) { - std::cerr << "Failed to get Context"; - return -1; - } - ctx->setKeyListMode (mode); - if (ctx->keyListMode() != mode) { - // unfortunately, Context::setKeyListMode() does not return the error - // returned by gpgme - std::cerr << "Failed to set keylist mode. You may have used an invalid combination of options.\n"; - return -1; - } - Error err = ctx->startKeyListing (*argv, only_secret); - if (err) { - std::cout << "Error: " << err.asStdString() << "\n"; - return -1; - } - GpgME::Key key; - std::stringstream ss; - do { - key = ctx->nextKey(err); - if (!err) - { - ss << key << "\n\n"; - } - } while (!err && !key.isNull()); - - std::cout << ss.str(); - - return 0; -} diff --git a/lang/cpp/tests/run-verify.cpp b/lang/cpp/tests/run-verify.cpp deleted file mode 100644 index 50131fb8..00000000 --- a/lang/cpp/tests/run-verify.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* - run-keylist.cpp - - This file is part of GpgMEpp's test suite. - Copyright (c) 2018 Intevation GmbH - - QGpgME is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - QGpgME is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - - In addition, as a special exception, the copyright holders give - permission to link the code of this program with any edition of - the Qt library by Trolltech AS, Norway (or with modified versions - of Qt that use the same license as Qt), and distribute linked - combinations including the two. You must obey the GNU General - Public License in all respects for all of the code used other than - Qt. If you modify this file, you may extend this exception to - your version of the file, but you are not obligated to do so. If - you do not wish to do so, delete this exception statement from - your version. -*/ -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif - -#include "context.h" -#include "key.h" -#include "data.h" -#include "verificationresult.h" - -#include <memory> -#include <iostream> - -using namespace GpgME; -static int -show_usage (int ex) -{ - fputs ("usage: run-verify [options] [DETACHEDSIGFILE] FILE\n\n" - "Options:\n" - " --verbose run in verbose mode\n" - " --openpgp use the OpenPGP protocol (default)\n" - " --cms use the CMS protocol\n" - " --sender MBOX use MBOX as sender address\n" - " --repeat N repeat it N times\n" - " --list-key list the signing key afterwards\n" - , stderr); - exit (ex); -} - -int -main (int argc, char **argv) -{ - int last_argc = -1; - Protocol protocol = OpenPGP; - std::string sender; - int repeats = 1; - bool verbose = false; - bool list_key = false; - - if (argc) - { argc--; argv++; } - - while (argc && last_argc != argc ) - { - last_argc = argc; - if (!strcmp (*argv, "--")) - { - argc--; argv++; - break; - } - else if (!strcmp (*argv, "--help")) - show_usage (0); - else if (!strcmp (*argv, "--verbose")) - { - verbose = true; - argc--; argv++; - } - else if (!strcmp (*argv, "--list-key")) - { - list_key = true; - argc--; argv++; - } - else if (!strcmp (*argv, "--openpgp")) - { - protocol = OpenPGP; - argc--; argv++; - } - else if (!strcmp (*argv, "--cms")) - { - protocol = CMS; - argc--; argv++; - } - else if (!strcmp (*argv, "--sender")) - { - argc--; argv++; - if (!argc) - show_usage (1); - sender = *argv; - argc--; argv++; - } - else if (!strcmp (*argv, "--repeat")) - { - argc--; argv++; - if (!argc) - show_usage (1); - repeats = atoi (*argv); - argc--; argv++; - } - else if (!strncmp (*argv, "--", 2)) - show_usage (1); - } - - if (argc < 1 || argc > 2) - show_usage (1); - - GpgME::initializeLibrary(); - - for (int i = 0; i < repeats; i++) { - std::cout << "Starting run: " << i << std::endl; - auto ctx = std::unique_ptr<Context> (Context::createForProtocol(protocol)); - if (!ctx) { - std::cerr << "Failed to get Context"; - return -1; - } - - std::FILE *fp_sig = fopen (argv[0], "rb"); - if (!fp_sig) { - std::cerr << "Failed to open sig file"; - exit (1); - } - - std::FILE *fp_msg = nullptr; - if (argc > 1) - { - fp_msg = fopen (argv[1], "rb"); - if (!fp_msg) { - std::cerr << "Failed to open msg file"; - exit (1); - } - } - Data dSig(fp_sig); - Data dMsg; - bool is_opaque = true; - if (fp_msg) { - dMsg = Data(fp_msg); - is_opaque = false; - } - - if (!sender.empty()) { - ctx->setSender(sender.c_str()); - } - - Data output; - VerificationResult result; - if (is_opaque) { - result = ctx->verifyOpaqueSignature(dSig, output); - } else { - result = ctx->verifyDetachedSignature(dSig, dMsg); - } - - Signature sig; - if (result.numSignatures()) { - sig = result.signature(0); - } - - if (list_key && !sig.isNull()) { - sig.key(true, false); - } - - if (verbose) { - std::cout << "Result: " << result << std::endl; - } else { - std::cout << "Err:" << result.error() << std::endl; - } - } -} diff --git a/lang/cpp/tests/run-wkdlookup.cpp b/lang/cpp/tests/run-wkdlookup.cpp deleted file mode 100644 index 1e18c9a8..00000000 --- a/lang/cpp/tests/run-wkdlookup.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* - run-wkdlookup.cpp - - This file is part of GpgMEpp's test suite. - Copyright (c) 2021 g10 Code GmbH - Software engineering by Ingo Klöcker <[email protected]> - - GPGME++ is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - GPGME++ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with GPGME++; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif - -#include "context.h" -#include "data.h" -#include "defaultassuantransaction.h" -#include "key.h" - -#include <memory> -#include <iostream> -#include <thread> - -using namespace GpgME; - -static int -show_usage (int ex) -{ - fputs ("usage: run-wkdlookup <email address>\n\n" - , stderr); - exit (ex); -} - -int -main (int argc, char **argv) -{ - int last_argc = -1; - - if (argc) { - argc--; argv++; - } - - while (argc && last_argc != argc ) { - last_argc = argc; - if (!strcmp (*argv, "--")) { - argc--; argv++; - break; - } else if (!strcmp (*argv, "--help")) { - show_usage (0); - } else if (!strncmp (*argv, "--", 2)) { - show_usage (1); - } - } - - if (argc != 1) { - show_usage (1); - } - - const std::string email{*argv}; - - GpgME::initializeLibrary(); - Error err; - auto ctx = std::unique_ptr<Context>{Context::createForEngine(AssuanEngine, &err)}; - if (!ctx) { - std::cerr << "Failed to get context (Error: " << err.asStdString() << ")\n"; - return -1; - } - - const std::string dirmngrSocket = GpgME::dirInfo("dirmngr-socket"); - if ((err = ctx->setEngineFileName(dirmngrSocket.c_str()))) { - std::cerr << "Failed to set engine file name (Error: " << err.asStdString() << ")\n"; - return -1; - } - if ((err = ctx->setEngineHomeDirectory(""))) { - std::cerr << "Failed to set engine home directory (Error: " << err.asStdString() << ")\n"; - return -1; - } - - // try to connect to dirmngr - err = ctx->assuanTransact("GETINFO version"); - if (err && err.code() != GPG_ERR_ASS_CONNECT_FAILED) { - std::cerr << "Failed to start assuan transaction (Error: " << err.asStdString() << ")\n"; - return -1; - } - if (err.code() == GPG_ERR_ASS_CONNECT_FAILED) { - std::cerr << "Starting dirmngr ...\n"; - auto spawnCtx = std::unique_ptr<Context>{Context::createForEngine(SpawnEngine, &err)}; - if (!spawnCtx) { - std::cerr << "Failed to get context for spawn engine (Error: " << err.asStdString() << ")\n"; - return -1; - } - - const auto gpgconfProgram = GpgME::dirInfo("gpgconf-name"); - // replace backslashes with forward slashes in homedir to work around bug T6833 - std::string homedir{GpgME::dirInfo("homedir")}; - std::replace(homedir.begin(), homedir.end(), '\\', '/'); - const char *argv[] = { - gpgconfProgram, - "--homedir", - homedir.c_str(), - "--launch", - "dirmngr", - NULL - }; - auto ignoreIO = Data{Data::null}; - err = spawnCtx->spawn(gpgconfProgram, argv, - ignoreIO, ignoreIO, ignoreIO, - Context::SpawnDetached); - if (err) { - std::cerr << "Failed to start dirmngr (Error: " << err.asStdString() << ")\n"; - return -1; - } - - // wait for socket to become available - int cnt = 0; - do { - ++cnt; - std::cerr << "Waiting for dirmngr to start ...\n"; - std::this_thread::sleep_for(std::chrono::milliseconds{250 * cnt}); - err = ctx->assuanTransact("GETINFO version"); - } while (err.code() == GPG_ERR_ASS_CONNECT_FAILED && cnt < 5); - } - - const auto cmd = std::string{"WKD_GET "} + email; - err = ctx->assuanTransact(cmd.c_str()); - if (err && err.code() != GPG_ERR_NO_NAME && err.code() != GPG_ERR_NO_DATA) { - std::cerr << "Error: WKD_GET returned " << err.asStdString() << "\n"; - return -1; - } - - const auto transaction = std::unique_ptr<DefaultAssuanTransaction>(dynamic_cast<DefaultAssuanTransaction*>(ctx->takeLastAssuanTransaction().release())); - const auto source = transaction->firstStatusLine("SOURCE"); - const auto rawData = transaction->data(); - if (rawData.size() == 0) { - std::cout << "No key found for " << email << "\n"; - } else { - const auto data = GpgME::Data{rawData.c_str(), rawData.size()}; - const auto keys = data.toKeys(GpgME::OpenPGP); - for (const auto &key : keys) { - std::cout << "Found key for " << email << " at " << source << ":\n" << key << "\n"; - } - } - - return 0; -} |