diff --git a/src/addressbook.cpp b/src/addressbook.cpp index 6c0f4d4..7a92961 100644 --- a/src/addressbook.cpp +++ b/src/addressbook.cpp @@ -1,303 +1,306 @@ /* addressbook.cpp - Functions for the Addressbook * Copyright (C) 2018 Intevation GmbH * * This file is part of GpgOL. * * GpgOL 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. * * GpgOL 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 . */ #include "addressbook.h" #include "oomhelp.h" #include "keycache.h" #include "mail.h" #include "cpphelp.h" #include "windowmessages.h" #include #include #include typedef struct { std::string name; std::string data; HWND hwnd; shared_disp_t contact; } keyadder_args_t; +static std::set s_checked_entries; + static DWORD WINAPI open_keyadder (LPVOID arg) { TSTART; auto adder_args = std::unique_ptr ((keyadder_args_t*) arg); std::vector args; // Collect the arguments char *gpg4win_dir = get_gpg4win_dir (); if (!gpg4win_dir) { TRACEPOINT; TRETURN -1; } const auto keyadder = std::string (gpg4win_dir) + "\\bin\\gpgolkeyadder.exe"; args.push_back (keyadder); args.push_back (std::string ("--hwnd")); args.push_back (std::to_string ((int) (intptr_t) adder_args->hwnd)); args.push_back (std::string ("--username")); args.push_back (adder_args->name); auto ctx = GpgME::Context::createForEngine (GpgME::SpawnEngine); if (!ctx) { // can't happen TRACEPOINT; TRETURN -1; } GpgME::Data mystdin (adder_args->data.c_str(), adder_args->data.size(), false); GpgME::Data mystdout, mystderr; char **cargs = vector_to_cArray (args); log_data ("%s:%s: launching keyadder args:", SRCNAME, __func__); for (size_t i = 0; cargs && cargs[i]; i++) { log_data (SIZE_T_FORMAT ": '%s'", i, cargs[i]); } GpgME::Error err = ctx->spawn (cargs[0], const_cast (cargs), mystdin, mystdout, mystderr, (GpgME::Context::SpawnFlags) ( GpgME::Context::SpawnAllowSetFg | GpgME::Context::SpawnShowWindow)); release_cArray (cargs); if (err) { log_error ("%s:%s: Err code: %i asString: %s", SRCNAME, __func__, err.code(), err.asString()); TRETURN 0; } auto newKey = mystdout.toString (); rtrim(newKey); if (newKey.empty()) { log_debug ("%s:%s: keyadder canceled.", SRCNAME, __func__); TRETURN 0; } if (newKey == "empty") { log_debug ("%s:%s: keyadder empty.", SRCNAME, __func__); newKey = ""; } Addressbook::callback_args_t cb_args; /* cb args are valid in the same scope as newKey */ cb_args.data = newKey.c_str(); cb_args.contact = adder_args->contact; do_in_ui_thread (CONFIG_KEY_DONE, (void*) &cb_args); TRETURN 0; } void Addressbook::update_key_o (void *callback_args) { TSTART; if (!callback_args) { TRACEPOINT; TRETURN; } callback_args_t *cb_args = static_cast (callback_args); LPDISPATCH contact = cb_args->contact.get(); LPDISPATCH user_props = get_oom_object (contact, "UserProperties"); if (!user_props) { TRACEPOINT; TRETURN; } LPDISPATCH pgp_key = find_or_add_text_prop (user_props, "OpenPGP Key"); if (!pgp_key) { TRACEPOINT; TRETURN; } put_oom_string (pgp_key, "Value", cb_args->data); log_debug ("%s:%s: PGP key data updated", SRCNAME, __func__); gpgol_release (pgp_key); + + s_checked_entries.clear (); TRETURN; } void Addressbook::edit_key_o (LPDISPATCH contact) { TSTART; if (!contact) { TRACEPOINT; TRETURN; } LPDISPATCH user_props = get_oom_object (contact, "UserProperties"); if (!user_props) { TRACEPOINT; TRETURN; } auto pgp_key = MAKE_SHARED ( find_or_add_text_prop (user_props, "OpenPGP Key")); gpgol_release (user_props); if (!pgp_key) { TRACEPOINT; TRETURN; } char *key_data = get_oom_string (pgp_key.get(), "Value"); if (!key_data) { TRACEPOINT; TRETURN; } char *name = get_oom_string (contact, "Subject"); if (!name) { TRACEPOINT; name = get_oom_string (contact, "Email1Address"); if (!name) { name = xstrdup (/* TRANSLATORS: Placeholder for a contact without a configured name */ _("Unknown contact")); } } keyadder_args_t *args = new keyadder_args_t; args->name = name; args->data = key_data; args->hwnd = get_active_hwnd (); contact->AddRef (); memdbg_addRef (contact); args->contact = MAKE_SHARED (contact); CloseHandle (CreateThread (NULL, 0, open_keyadder, (LPVOID) args, 0, NULL)); xfree (name); xfree (key_data); TRETURN; } -static std::set s_checked_entries; /* For each new recipient check the address book to look for a potentially configured key for this recipient and import / register it into the keycache. */ void Addressbook::check_o (Mail *mail) { TSTART; if (!mail) { TRACEPOINT; TRETURN; } LPDISPATCH mailitem = mail->item (); if (!mailitem) { TRACEPOINT; TRETURN; } auto recipients_obj = MAKE_SHARED (get_oom_object (mailitem, "Recipients")); if (!recipients_obj) { TRACEPOINT; TRETURN; } bool err = false; const auto recipient_entries = get_oom_recipients_with_addrEntry (recipients_obj.get(), &err); for (const auto pair: recipient_entries) { if (s_checked_entries.find (pair.first) != s_checked_entries.end ()) { continue; } - s_checked_entries.insert (pair.first); if (!pair.second) { TRACEPOINT; continue; } auto contact = MAKE_SHARED (get_oom_object (pair.second.get (), "GetContact")); if (!contact) { log_debug ("%s:%s: failed to resolve contact for %s", SRCNAME, __func__, anonstr (pair.first.c_str())); continue; } + s_checked_entries.insert (pair.first); LPDISPATCH user_props = get_oom_object (contact.get (), "UserProperties"); if (!user_props) { TRACEPOINT; continue; } LPDISPATCH pgp_key = find_or_add_text_prop (user_props, "OpenPGP Key"); gpgol_release (user_props); if (!pgp_key) { continue; } log_debug ("%s:%s: found configured pgp key for %s", SRCNAME, __func__, anonstr (pair.first.c_str())); char *key_data = get_oom_string (pgp_key, "Value"); if (!key_data || !strlen (key_data)) { log_debug ("%s:%s: No key data", SRCNAME, __func__); } KeyCache::instance ()->importFromAddrBook (pair.first, key_data, mail); xfree (key_data); gpgol_release (pgp_key); } TRETURN; }