diff --git a/plugins/openpgp/CMakeLists.txt b/plugins/openpgp/CMakeLists.txt index 868a3040..7bd98475 100644 --- a/plugins/openpgp/CMakeLists.txt +++ b/plugins/openpgp/CMakeLists.txt @@ -30,6 +30,7 @@ vala_precompile(OPENPGP_VALA_C SOURCES src/account_settings_entry.vala src/account_settings_widget.vala + src/contact_details_provider.vala src/database.vala src/encryption_list_entry.vala src/manager.vala @@ -37,6 +38,7 @@ SOURCES src/register_plugin.vala src/stream_flag.vala src/stream_module.vala + src/util.vala CUSTOM_VAPIS ${CMAKE_BINARY_DIR}/exports/gpgme.vapi ${CMAKE_BINARY_DIR}/exports/xmpp-vala.vapi @@ -55,4 +57,4 @@ target_link_libraries(openpgp libdino gpgme-vala ${OPENPGP_PACKAGES}) set_target_properties(openpgp PROPERTIES PREFIX "") set_target_properties(openpgp PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins/) -install(TARGETS openpgp ${PLUGIN_INSTALL}) \ No newline at end of file +install(TARGETS openpgp ${PLUGIN_INSTALL}) diff --git a/plugins/openpgp/src/account_settings_widget.vala b/plugins/openpgp/src/account_settings_widget.vala index 9c21f967..35548c0e 100644 --- a/plugins/openpgp/src/account_settings_widget.vala +++ b/plugins/openpgp/src/account_settings_widget.vala @@ -77,10 +77,10 @@ private class AccountSettingsWidget : Stack, Plugins.AccountSettingsWidget { TreeIter iter; list_store.append(out iter); - list_store.set(iter, 0, build_markup_string(_("Key publishing disabled"), _("Select key")), 1, ""); + list_store.set(iter, 0, build_markup_string(_("Key publishing disabled"), _("Select key") + " \n "), 1, ""); for (int i = 0; i < keys.size; i++) { list_store.append(out iter); - list_store.set(iter, 0, @"$(Markup.escape_text(keys[i].uids[0].uid))\n0x$(Markup.escape_text(keys[i].fpr[0:16]))"); + list_store.set(iter, 0, @"$(Markup.escape_text(keys[i].uids[0].uid))\n$(markup_colorize_id(keys[i].fpr, true)) "); list_store.set(iter, 1, keys[i].fpr); if (keys[i].fpr == plugin.db.get_account_key(current_account)) { set_label_active(iter, i + 1); @@ -139,7 +139,7 @@ private class AccountSettingsWidget : Stack, Plugins.AccountSettingsWidget { } private string build_markup_string(string primary, string secondary) { - return @"$(Markup.escape_text(primary))\n$(Markup.escape_text(secondary))"; + return @"$(Markup.escape_text(primary))\n$secondary"; } } diff --git a/plugins/openpgp/src/contact_details_provider.vala b/plugins/openpgp/src/contact_details_provider.vala new file mode 100644 index 00000000..39b6de2c --- /dev/null +++ b/plugins/openpgp/src/contact_details_provider.vala @@ -0,0 +1,34 @@ +using Gtk; + +using Dino.Entities; + +namespace Dino.Plugins.OpenPgp { + +public class ContactDetailsProvider : Plugins.ContactDetailsProvider { + public override string id { get { return "pgp_info"; } } + + private StreamInteractor stream_interactor; + + public ContactDetailsProvider(StreamInteractor stream_interactor) { + this.stream_interactor = stream_interactor; + } + + public override void populate(Conversation conversation, Plugins.ContactDetails contact_details) { + if (conversation.type_ == Conversation.Type.CHAT) { + string? key_id = stream_interactor.get_module(Manager.IDENTITY).get_key_id(conversation.account, conversation.counterpart); + if (key_id != null) { + Gee.List keys = GPGHelper.get_keylist(key_id); + if (keys.size > 0) { + Label label = new Label(markup_colorize_id(keys[0].fpr, true)) { use_markup=true, justify=Justification.RIGHT, visible=true }; + contact_details.add(_("Encryption"), _("OpenPGP"), "", label); + } else { + string s = _("Key not in keychain") + "\n" + markup_colorize_id(key_id, false); + Label label = new Label(s) { use_markup=true, justify=Justification.RIGHT, visible=true }; + contact_details.add(_("Encryption"), _("OpenPGP"), "", label); + } + } + } + } +} + +} diff --git a/plugins/openpgp/src/encryption_list_entry.vala b/plugins/openpgp/src/encryption_list_entry.vala index 9aac3db2..584e065b 100644 --- a/plugins/openpgp/src/encryption_list_entry.vala +++ b/plugins/openpgp/src/encryption_list_entry.vala @@ -19,8 +19,9 @@ private class EncryptionListEntry : Plugins.EncryptionListEntry, Object { }} public bool can_encrypt(Entities.Conversation conversation) { - return stream_interactor.get_module(Manager.IDENTITY).get_key_id(conversation.account, conversation.counterpart) != null; + string? key_id = stream_interactor.get_module(Manager.IDENTITY).get_key_id(conversation.account, conversation.counterpart); + return key_id != null && GPGHelper.get_keylist(key_id).size > 0; } } -} \ No newline at end of file +} diff --git a/plugins/openpgp/src/plugin.vala b/plugins/openpgp/src/plugin.vala index a585b206..edf19c96 100644 --- a/plugins/openpgp/src/plugin.vala +++ b/plugins/openpgp/src/plugin.vala @@ -7,36 +7,39 @@ extern const string LOCALE_INSTALL_DIR; namespace Dino.Plugins.OpenPgp { - public class Plugin : Plugins.RootInterface, Object { - public Dino.Application app; - public Database db; - public HashMap modules = new HashMap(Account.hash_func, Account.equals_func); +public class Plugin : Plugins.RootInterface, Object { + public Dino.Application app; + public Database db; + public HashMap modules = new HashMap(Account.hash_func, Account.equals_func); - private EncryptionListEntry list_entry; - private AccountSettingsEntry settings_entry; + private EncryptionListEntry list_entry; + private AccountSettingsEntry settings_entry; + private ContactDetailsProvider contact_details_provider; - public void registered(Dino.Application app) { - this.app = app; - this.db = new Database(Path.build_filename(Application.get_storage_dir(), "pgp.db")); - this.list_entry = new EncryptionListEntry(app.stream_interaction); - this.settings_entry = new AccountSettingsEntry(this); + public void registered(Dino.Application app) { + this.app = app; + this.db = new Database(Path.build_filename(Application.get_storage_dir(), "pgp.db")); + this.list_entry = new EncryptionListEntry(app.stream_interaction); + this.settings_entry = new AccountSettingsEntry(this); + this.contact_details_provider = new ContactDetailsProvider(app.stream_interaction); - app.plugin_registry.register_encryption_list_entry(list_entry); - app.plugin_registry.register_account_settings_entry(settings_entry); - app.stream_interaction.module_manager.initialize_account_modules.connect(on_initialize_account_modules); + app.plugin_registry.register_encryption_list_entry(list_entry); + app.plugin_registry.register_account_settings_entry(settings_entry); + app.plugin_registry.register_contact_details_entry(contact_details_provider); + app.stream_interaction.module_manager.initialize_account_modules.connect(on_initialize_account_modules); - Manager.start(app.stream_interaction, db); + Manager.start(app.stream_interaction, db); - internationalize(GETTEXT_PACKAGE, app.search_path_generator.get_locale_path(GETTEXT_PACKAGE, LOCALE_INSTALL_DIR)); - } - - public void shutdown() { } - - private void on_initialize_account_modules(Account account, ArrayList modules) { - Module module = new Module(db.get_account_key(account)); - this.modules[account] = module; - modules.add(module); - } + internationalize(GETTEXT_PACKAGE, app.search_path_generator.get_locale_path(GETTEXT_PACKAGE, LOCALE_INSTALL_DIR)); } + public void shutdown() { } + + private void on_initialize_account_modules(Account account, ArrayList modules) { + Module module = new Module(db.get_account_key(account)); + this.modules[account] = module; + modules.add(module); + } +} + } diff --git a/plugins/openpgp/src/util.vala b/plugins/openpgp/src/util.vala new file mode 100644 index 00000000..7c42b578 --- /dev/null +++ b/plugins/openpgp/src/util.vala @@ -0,0 +1,50 @@ +using Gtk; + +using Dino.Entities; + +namespace Dino.Plugins.OpenPgp { + +/* Adapted from OpenKeychain */ +public static string markup_colorize_id(string s, bool is_fingerprint) { + string markup = is_fingerprint ? "" : "0x"; + for (int i = 0; i < s.length; i += 4) { + string four_chars = s.substring(i, 4).down(); + + int raw = (int) four_chars.to_long(null, 16); + uint8[] bytes = {(uint8) ((raw >> 8) & 0xff - 128), (uint8) (raw & 0xff - 128)}; + + Checksum checksum = new Checksum(ChecksumType.SHA1); + checksum.update(bytes, bytes.length); + uint8[] digest = new uint8[20]; + size_t len = 20; + checksum.get_digest(digest, ref len); + + uint8 r = digest[0]; + uint8 g = digest[1]; + uint8 b = digest[2]; + + if (r == 0 && g == 0 && b == 0) r = g = b = 1; + + double brightness = 0.2126 * r + 0.7152 * g + 0.0722 * b; + + if (brightness < 80) { + double factor = 80.0 / brightness; + r = uint8.min(255, (uint8) (r * factor)); + g = uint8.min(255, (uint8) (g * factor)); + b = uint8.min(255, (uint8) (b * factor)); + + } else if (brightness > 180) { + double factor = 180.0 / brightness; + r = (uint8) (r * factor); + g = (uint8) (g * factor); + b = (uint8) (b * factor); + } + + if (i == 4 * 5) markup += "\n"; + markup += @"$four_chars"; + if (is_fingerprint) markup += " "; + } + return "" + markup + ""; +} + +}