SF.net SVN: geany-plugins:[1938] trunk
alvesh88 at users.sourceforge.net
alvesh88 at xxxxx
Sat Feb 26 17:02:33 UTC 2011
Revision: 1938
http://geany-plugins.svn.sourceforge.net/geany-plugins/?rev=1938&view=rev
Author: alvesh88
Date: 2011-02-26 17:02:33 +0000 (Sat, 26 Feb 2011)
Log Message:
-----------
GeanyPG -- GPG encryption plugin
first commit
Added Paths:
-----------
trunk/geanypg/
trunk/geanypg/src/
trunk/geanypg/src/aux.c
trunk/geanypg/src/decrypt_cb.c
trunk/geanypg/src/encrypt_cb.c
trunk/geanypg/src/geanypg.c
trunk/geanypg/src/geanypg.h
trunk/geanypg/src/key_selection_dialog.c
trunk/geanypg/src/pinentry.c
trunk/geanypg/src/sign_cb.c
trunk/geanypg/src/verify_aux.c
trunk/geanypg/src/verify_cb.c
Added: trunk/geanypg/src/aux.c
===================================================================
--- trunk/geanypg/src/aux.c (rev 0)
+++ trunk/geanypg/src/aux.c 2011-02-26 17:02:33 UTC (rev 1938)
@@ -0,0 +1,163 @@
+// aux.c
+//
+// Copyright 2011 Hans Alves <alves.h88 at gmail.com>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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.
+
+
+#include "geanypg.h"
+
+void geanypg_init_ed(encrypt_data * ed)
+{
+ ed->key_array = NULL;
+ ed->nkeys = 0;
+ ed->skey_array = NULL;
+ ed->nskeys = 0;
+}
+
+int geanypg_get_keys(encrypt_data * ed)
+{
+ gpgme_error_t err;
+ unsigned long size = SIZE;
+ //initialize index to 0
+ unsigned long index = 0;
+ //allocate array of size 1N
+ ed->key_array = (gpgme_key_t*) malloc(SIZE * sizeof(gpgme_key_t));
+ err = gpgme_op_keylist_start(ed->ctx, NULL, 0);
+ while (!err)
+ {
+ err = gpgme_op_keylist_next(ed->ctx, ed->key_array + index);
+ if (err)
+ break;
+ ++index;
+ if (index >= size)
+ {
+ size += SIZE;
+ ed->key_array = (gpgme_key_t*) realloc(ed->key_array, size * sizeof(gpgme_key_t));
+ }
+ }
+ ed->nkeys = index;
+ if (gpg_err_code(err) != GPG_ERR_EOF)
+ {
+ geanypg_show_err_msg(err);
+ return 0;
+ }
+ return 1;
+}
+
+int geanypg_get_secret_keys(encrypt_data * ed)
+{
+ gpgme_error_t err;
+ unsigned long size = SIZE;
+ //initialize index to 0
+ unsigned long index = 0;
+ //allocate array of size 1N
+ ed->skey_array = (gpgme_key_t*) malloc(SIZE * sizeof(gpgme_key_t));
+ err = gpgme_op_keylist_start(ed->ctx, NULL, 1);
+ while (!err)
+ {
+ err = gpgme_op_keylist_next(ed->ctx, ed->skey_array + index);
+ if (err)
+ break;
+ ++index;
+ if (index >= size)
+ {
+ size += SIZE;
+ ed->skey_array = (gpgme_key_t*) realloc(ed->skey_array, size * sizeof(gpgme_key_t));
+ }
+ }
+ ed->nskeys = index;
+ if (gpg_err_code(err) != GPG_ERR_EOF)
+ {
+ geanypg_show_err_msg(err);
+ return 0;
+ }
+ return 1;
+}
+
+void geanypg_release_keys(encrypt_data * ed)
+{
+ gpgme_key_t * ptr;
+ if (ed->key_array)
+ {
+ ptr = ed->key_array;
+ while (ptr < ed->key_array + ed->nkeys)
+ gpgme_key_unref(*(ptr++));
+ free(ed->key_array);
+ ed->key_array = NULL;
+ ed->nkeys = 0;
+ }
+ if (ed->skey_array)
+ {
+ ptr = ed->skey_array;
+ while (ptr < ed->skey_array + ed->nskeys)
+ gpgme_key_unref(*(ptr++));
+ free(ed->skey_array);
+ ed->skey_array = NULL;
+ ed->nskeys = 0;
+ }
+}
+
+
+void geanypg_load_buffer(gpgme_data_t * buffer)
+{
+ //gpgme_data_new_from_mem(buffer, text, size, 0);
+ GeanyDocument * doc = document_get_current();
+ //SCI_GETSELECTIONSTART-SCI_GETSELECTIONEND
+ char * data = NULL;
+ unsigned long sstart = scintilla_send_message(doc->editor->sci, SCI_GETSELECTIONSTART, 0, 0);
+ unsigned long send = scintilla_send_message(doc->editor->sci, SCI_GETSELECTIONEND, 0, 0);
+ unsigned long size = 0;
+ if (sstart - send)
+ {
+ size = scintilla_send_message(doc->editor->sci, SCI_GETSELTEXT, 0, 0);
+ data = (char *) malloc(size + 1);
+ scintilla_send_message(doc->editor->sci, SCI_GETSELTEXT, 0, (sptr_t)data);
+ gpgme_data_new_from_mem(buffer, data, size, 1);
+ }
+ else
+ {
+ size = scintilla_send_message(doc->editor->sci, SCI_GETLENGTH, 0, 0);
+ data = (char *) malloc(size + 1);
+ scintilla_send_message(doc->editor->sci, SCI_GETTEXT, (uptr_t)(size + 1), (sptr_t)data);
+ gpgme_data_new_from_mem(buffer, data, size, 1);
+ }
+ if (data) // if there is no text data may still be NULL
+ free(data);
+ gpgme_data_set_encoding(*buffer, GPGME_DATA_ENCODING_BINARY);
+}
+
+void geanypg_write_file(FILE * file)
+{
+ unsigned bufsize = 2048;
+ unsigned long size;
+ char buffer[bufsize];
+ GeanyDocument * doc = document_get_current();
+ if (abs(sci_get_selection_start(doc->editor->sci) - sci_get_selection_end(doc->editor->sci)))
+ { // replace selected text
+ // clear selection, cursor should be at the end or beginneng of the selection
+ scintilla_send_message(doc->editor->sci, SCI_REPLACESEL, 0, (sptr_t)"");
+ while ((size = fread(buffer, 1, bufsize, file)))
+ // add at the cursor
+ scintilla_send_message(doc->editor->sci, SCI_ADDTEXT, (uptr_t) size, (sptr_t) buffer);
+ }
+ else
+ { //replace complete document
+ scintilla_send_message(doc->editor->sci, SCI_CLEARALL, 0, 0);
+ while ((size = fread(buffer, 1, bufsize, file)))
+ scintilla_send_message(doc->editor->sci, SCI_APPENDTEXT, (uptr_t) size, (sptr_t) buffer);
+ }
+}
Added: trunk/geanypg/src/decrypt_cb.c
===================================================================
--- trunk/geanypg/src/decrypt_cb.c (rev 0)
+++ trunk/geanypg/src/decrypt_cb.c 2011-02-26 17:02:33 UTC (rev 1938)
@@ -0,0 +1,76 @@
+// decrypt_cb.c
+//
+// Copyright 2011 Hans Alves <alves.h88 at gmail.com>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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.
+
+
+#include "geanypg.h"
+
+void geanypg_decrypt_verify(encrypt_data * ed)
+{
+ gpgme_data_t plain, cipher;
+ gpgme_error_t err;
+ FILE * tempfile;
+
+ tempfile = tmpfile();
+ if (!(tempfile))
+ {
+ fprintf(stderr, "GEANYPG: couldn't create tempfile: %s.\n", strerror(errno));
+ return ;
+ }
+ gpgme_data_new_from_stream(&plain, tempfile);
+
+ geanypg_load_buffer(&cipher);
+
+ err = gpgme_op_decrypt_verify(ed->ctx, cipher, plain);
+ if (gpgme_err_code(err) == GPG_ERR_NO_DATA) // no encription, but maybe signatures
+ {
+ // maybe reaload cipher
+ gpgme_data_release(cipher);
+ geanypg_load_buffer(&cipher);
+ rewind(tempfile);
+ err = gpgme_op_verify(ed->ctx, cipher, NULL, plain);
+ }
+ if (err != GPG_ERR_NO_ERROR)
+ geanypg_show_err_msg(err);
+ else
+ {
+ rewind(tempfile);
+ geanypg_write_file(tempfile);
+ geanypg_handle_signatures(ed);
+ }
+
+ fclose(tempfile);
+ // release buffers
+ gpgme_data_release(cipher);
+ gpgme_data_release(plain);
+}
+
+void geanypg_decrypt_cb(GtkMenuItem * menuitem, gpointer user_data)
+{
+ encrypt_data ed;
+ geanypg_init_ed(&ed);
+ gpgme_error_t err = gpgme_new(&ed.ctx);
+ if (err && geanypg_show_err_msg(err))
+ return;
+ gpgme_set_protocol(ed.ctx, GPGME_PROTOCOL_OpenPGP);
+ gpgme_set_passphrase_cb(ed.ctx, geanypg_passphrase_cb, NULL);
+ if (geanypg_get_keys(&ed) && geanypg_get_secret_keys(&ed))
+ geanypg_decrypt_verify(&ed);
+ geanypg_release_keys(&ed);
+ gpgme_release(ed.ctx);
+}
Added: trunk/geanypg/src/encrypt_cb.c
===================================================================
--- trunk/geanypg/src/encrypt_cb.c (rev 0)
+++ trunk/geanypg/src/encrypt_cb.c 2011-02-26 17:02:33 UTC (rev 1938)
@@ -0,0 +1,83 @@
+// encrypt_cb.c
+//
+// Copyright 2011 Hans Alves <alves.h88 at gmail.com>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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.
+
+
+#include "geanypg.h"
+
+void geanypg_encrypt(encrypt_data * ed, gpgme_key_t * recp, int sign)
+{ // FACTORIZE
+ gpgme_data_t plain, cipher;
+ gpgme_error_t err;
+ FILE * tempfile;
+ tempfile = tmpfile();
+ if (!(tempfile))
+ {
+ fprintf(stderr, "GEANYPG: couldn't create tempfile: %s.\n", strerror(errno));
+ return ;
+ }
+ gpgme_data_new_from_stream(&cipher, tempfile);
+ gpgme_data_set_encoding(cipher, GPGME_DATA_ENCODING_ARMOR);
+
+ geanypg_load_buffer(&plain);
+
+ // do the actual encryption
+ if (sign)
+ err = gpgme_op_encrypt_sign(ed->ctx, recp, 0, plain, cipher);
+ else
+ err = gpgme_op_encrypt(ed->ctx, recp, 0, plain, cipher);
+ if (err != GPG_ERR_NO_ERROR && gpgme_err_code(err) != GPG_ERR_CANCELED)
+ geanypg_show_err_msg(err);
+ else
+ {
+ rewind(tempfile);
+ geanypg_write_file(tempfile);
+ }
+
+ fclose(tempfile);
+ // release buffers
+ gpgme_data_release(plain);
+ gpgme_data_release(cipher);
+}
+
+void geanypg_encrypt_cb(GtkMenuItem * menuitem, gpointer user_data)
+{
+ int sign;
+ encrypt_data ed;
+ geanypg_init_ed(&ed);
+ gpgme_error_t err = gpgme_new(&ed.ctx);
+ if (err && geanypg_show_err_msg(err))
+ return;
+ gpgme_set_armor(ed.ctx, 1);
+ gpgme_set_passphrase_cb(ed.ctx, geanypg_passphrase_cb, NULL);
+ if (geanypg_get_keys(&ed) && geanypg_get_secret_keys(&ed))
+ {
+ gpgme_key_t * recp = NULL;
+ if (geanypg_encrypt_selection_dialog(&ed, &recp, &sign))
+ {
+ if (*recp)
+ geanypg_encrypt(&ed, recp, sign);
+ else if (dialogs_show_question("No recipients were selected,\nuse symetric cipher?"))
+ geanypg_encrypt(&ed, NULL, sign);
+ }
+ if (recp)
+ free(recp);
+ }
+ geanypg_release_keys(&ed);
+ gpgme_release(ed.ctx);
+}
Added: trunk/geanypg/src/geanypg.c
===================================================================
--- trunk/geanypg/src/geanypg.c (rev 0)
+++ trunk/geanypg/src/geanypg.c 2011-02-26 17:02:33 UTC (rev 1938)
@@ -0,0 +1,110 @@
+// geanypg.c
+//
+// Copyright 2011 Hans Alves <alves.h88 at gmail.com>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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.
+
+#include "geanypg.h"
+
+/* These items are set by Geany before plugin_init() is called. */
+GeanyPlugin *geany_plugin;
+GeanyData *geany_data;
+GeanyFunctions *geany_functions;
+unsigned long fcounter;
+/* Check that the running Geany supports the plugin API version used below, and check
+ * for binary compatibility. */
+PLUGIN_VERSION_CHECK(201)
+
+/* All plugins must set name, description, version and author. */
+PLUGIN_SET_INFO(_("GeanyPG"),
+ _("gpg encryption plugin for geany"),
+ "0.1",
+ _("Hans Alves <alves.h88 at gmail.com>"))
+
+static GtkWidget * main_menu_item = NULL;
+
+static gpgme_error_t geanypg_init_gpgme(void)
+{
+ // Initialize the locale environment.
+ setlocale(LC_ALL, "");
+ fprintf(stderr, "GEANYPG: Using libgpgme version: %s\n",
+ gpgme_check_version("1.1.0"));
+ gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL));
+#ifdef LC_MESSAGES // only necessary for portability to W32 systems
+ gpgme_set_locale(NULL, LC_MESSAGES, setlocale(LC_MESSAGES, NULL));
+#endif
+ return gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
+}
+
+gpgme_error_t geanypg_show_err_msg(gpgme_error_t err)
+{
+ gchar const * msg = (gchar const *)gpgme_strerror(err);
+ gchar const * src = (gchar const *)gpgme_strsource(err);
+ dialogs_show_msgbox(GTK_MESSAGE_ERROR, "Error from %s: %s\n.", src, msg);
+ fprintf(stderr, "GEANYPG: %s\nFrom %s.\n", msg, src);
+ return err;
+}
+
+void plugin_init(GeanyData *data)
+{
+ fcounter = 0;
+ gpgme_error_t err = geanypg_init_gpgme();
+ if (err)
+ {
+ geanypg_show_err_msg(err);
+ return;
+ }
+ // Create a new menu item and show it
+ main_menu_item = gtk_menu_item_new_with_mnemonic("GeanyPG");
+ gtk_widget_show(main_menu_item);
+
+ GtkWidget * submenu = gtk_menu_new();
+ gtk_widget_show(submenu);
+ GtkWidget * encrypt = gtk_menu_item_new_with_mnemonic("Encrypt");
+ GtkWidget * sign = gtk_menu_item_new_with_mnemonic("Sign");
+ GtkWidget * decrypt = gtk_menu_item_new_with_mnemonic("Decrypt / Verify");
+ GtkWidget * verify = gtk_menu_item_new_with_mnemonic("Verify detached signature");
+
+ gtk_widget_show(encrypt);
+ gtk_widget_show(sign);
+ gtk_widget_show(decrypt);
+ gtk_widget_show(verify);
+
+ gtk_menu_append(GTK_MENU(submenu), encrypt);
+ gtk_menu_append(GTK_MENU(submenu), sign);
+ gtk_menu_append(GTK_MENU(submenu), decrypt);
+ gtk_menu_append(GTK_MENU(submenu), verify);
+
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(main_menu_item), submenu);
+
+ // Attach the new menu item to the Tools menu
+ gtk_container_add(GTK_CONTAINER(geany->main_widgets->tools_menu),
+ main_menu_item);
+
+ // Connect the menu item with a callback function
+ // which is called when the item is clicked
+ g_signal_connect(encrypt, "activate", G_CALLBACK(geanypg_encrypt_cb), NULL);
+ g_signal_connect(sign, "activate", G_CALLBACK(geanypg_sign_cb), NULL);
+ g_signal_connect(decrypt, "activate", G_CALLBACK(geanypg_decrypt_cb), NULL);
+ g_signal_connect(verify, "activate", G_CALLBACK(geanypg_verify_cb), NULL);
+}
+
+
+void plugin_cleanup(void)
+{
+ if (main_menu_item)
+ gtk_widget_destroy(main_menu_item);
+}
Added: trunk/geanypg/src/geanypg.h
===================================================================
--- trunk/geanypg/src/geanypg.h (rev 0)
+++ trunk/geanypg/src/geanypg.h 2011-02-26 17:02:33 UTC (rev 1938)
@@ -0,0 +1,80 @@
+// geanypg.h
+//
+// Copyright 2011 Hans Alves <alves.h88 at gmail.com>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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.
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <locale.h>
+
+#include <geanyplugin.h>
+#include <Scintilla.h>
+#include <gpgme.h>
+
+#define SIZE 32
+
+enum
+{
+ READ = 0,
+ WRITE = 1
+};
+
+typedef struct
+{
+ gpgme_ctx_t ctx;
+ gpgme_key_t * key_array;
+ unsigned long nkeys;
+ gpgme_key_t * skey_array;
+ unsigned long nskeys;
+} encrypt_data;
+
+extern GeanyPlugin *geany_plugin;
+extern GeanyData *geany_data;
+extern GeanyFunctions *geany_functions;
+
+// auxiliary functions (aux.c)
+void geanypg_init_ed(encrypt_data * ed);
+int geanypg_get_keys(encrypt_data * ed);
+int geanypg_get_secret_keys(encrypt_data * ed);
+void geanypg_release_keys(encrypt_data * ed);
+void geanypg_load_buffer(gpgme_data_t * buffer);
+void geanypg_write_file(FILE * file);
+
+// some more auxiliary functions (verify_aux.c)
+void geanypg_handle_signatures(encrypt_data * ed);
+void geanypg_check_sig(encrypt_data * ed, gpgme_signature_t sig);
+
+// dialogs
+int geanypg_encrypt_selection_dialog(encrypt_data * ed, gpgme_key_t ** selected, int * sign);
+int geanypg_sign_selection_dialog(encrypt_data * ed);
+gpgme_error_t geanypg_show_err_msg(gpgme_error_t err);
+
+// callback functions
+void geanypg_encrypt_cb(GtkMenuItem * menuitem, gpointer user_data);
+void geanypg_sign_cb(GtkMenuItem * menuitem, gpointer user_data);
+void geanypg_decrypt_cb(GtkMenuItem * menuitem, gpointer user_data);
+void geanypg_verify_cb(GtkMenuItem * menuitem, gpointer user_data);
+
+// pinentry callback
+gpgme_error_t geanypg_passphrase_cb(void *hook,
+ const char *uid_hint,
+ const char *passphrase_info,
+ int prev_was_bad ,
+ int fd);
Added: trunk/geanypg/src/key_selection_dialog.c
===================================================================
--- trunk/geanypg/src/key_selection_dialog.c (rev 0)
+++ trunk/geanypg/src/key_selection_dialog.c 2011-02-26 17:02:33 UTC (rev 1938)
@@ -0,0 +1,244 @@
+// key_selection_dialog.c
+//
+// Copyright 2011 Hans Alves <alves.h88 at gmail.com>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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.
+
+// something about premature optimization, it still needs to be done
+
+#include "geanypg.h"
+
+enum
+{
+ TOGGLE_COLUMN,
+ RECIPIENT_COLUMN,
+ KEYID_COLUMN,
+ N_COLUMNS
+};
+
+typedef struct
+{
+ GtkListStore * store;
+ gint column;
+} listdata;
+
+static void geanypg_toggled_cb(GtkCellRendererToggle * cell_renderer,
+ gchar * path,
+ listdata * udata)
+{
+ GtkTreeIter iter;
+ gboolean value;
+ if (!udata) return;
+ if (gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(udata->store), &iter, path))
+ {
+ gtk_tree_model_get(GTK_TREE_MODEL(udata->store), &iter, udata->column, &value, -1);
+ value = !value;
+ gtk_list_store_set(udata->store, &iter, udata->column, value, -1);
+ }
+}
+
+static GtkListStore * geanypg_makelist(gpgme_key_t * key_array, unsigned long nkeys, int addnone)
+{
+ GtkTreeIter iter;
+ unsigned long index;
+ GtkListStore * list = gtk_list_store_new(N_COLUMNS, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING);
+ if (addnone)
+ {
+ gtk_list_store_append(list, &iter);
+ gtk_list_store_set(list, &iter,
+ TOGGLE_COLUMN, FALSE,
+ RECIPIENT_COLUMN, "None",
+ KEYID_COLUMN, "",
+ -1);
+ }
+ for (index = 0; index < nkeys; ++index)
+ {
+ char * name = (key_array[index]->uids && key_array[index]->uids->name) ? key_array[index]->uids->name : "";
+ char * email = (key_array[index]->uids && key_array[index]->uids->email) ? key_array[index]->uids->email : "";
+ char buffer[strlen(name) + strlen(email) + 7];
+ sprintf(buffer, "%s <%s>", name, email);
+ gtk_list_store_append(list, &iter);
+ gtk_list_store_set(list, &iter,
+ TOGGLE_COLUMN, FALSE,
+ RECIPIENT_COLUMN, buffer,
+ KEYID_COLUMN, key_array[index]->subkeys->keyid,
+ -1);
+ }
+ return list;
+}
+
+static GtkWidget * geanypg_combobox(GtkListStore * list)
+{
+ GtkWidget * combobox = gtk_combo_box_new_with_model(GTK_TREE_MODEL(list));
+ GtkCellRenderer * cell1 = gtk_cell_renderer_text_new();
+ gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combobox), cell1, FALSE);
+ gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(combobox), cell1,
+ "text", RECIPIENT_COLUMN);
+ return combobox;
+}
+
+static GtkWidget * geanypg_listview(GtkListStore * list, listdata * data)
+{
+ GtkTreeViewColumn * column;
+ GtkCellRenderer * togglerenderer, * textrenderer;
+ GtkWidget * listview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list));
+ // checkbox column
+ togglerenderer = gtk_cell_renderer_toggle_new();
+ g_signal_connect(G_OBJECT(togglerenderer), "toggled", G_CALLBACK(geanypg_toggled_cb), NULL);
+ column = gtk_tree_view_column_new_with_attributes("?",
+ togglerenderer,
+ "active", TOGGLE_COLUMN,
+ NULL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(listview), column);
+ data->store = list;
+ data->column = TOGGLE_COLUMN;
+ g_signal_connect(G_OBJECT(togglerenderer), "toggled", G_CALLBACK(geanypg_toggled_cb), (gpointer) data);
+ // recipient column
+ textrenderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes("recipient",
+ textrenderer,
+ "text", RECIPIENT_COLUMN,
+ NULL);
+ gtk_tree_view_column_set_resizable(column, TRUE);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(listview), column);
+ // keyid column
+ column = gtk_tree_view_column_new_with_attributes("keyid",
+ textrenderer,
+ "text", KEYID_COLUMN,
+ NULL);
+ gtk_tree_view_column_set_resizable(column, TRUE);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(listview), column);
+ return listview;
+}
+
+int geanypg_encrypt_selection_dialog(encrypt_data * ed, gpgme_key_t ** selected, int * sign)
+{
+ GtkWidget * dialog = gtk_dialog_new();
+ unsigned long index, sindex, capacity;
+ int response;
+ GtkWidget * contentarea, * listview, * scrollwin, * combobox;
+ GtkTreeIter iter;
+ listdata data;
+ gboolean active;
+
+ *sign = 0;
+
+ GtkListStore * list = geanypg_makelist(ed->key_array, ed->nkeys, 0);
+ listview = geanypg_listview(list, &data);
+ scrollwin = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollwin),
+ listview);
+ gtk_widget_set_size_request(scrollwin, 500, 160);
+ combobox = geanypg_combobox(geanypg_makelist(ed->skey_array, ed->nskeys, 1));
+
+
+ contentarea = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ gtk_box_pack_start(GTK_BOX(contentarea), gtk_label_new("Please select any recipients"), FALSE, FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(contentarea), scrollwin, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(contentarea), gtk_label_new("Sign the message as:"), FALSE, FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(contentarea), combobox, FALSE, FALSE, 0);
+
+
+ // add ok and cancel buttons
+ gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_OK, GTK_RESPONSE_OK);
+ gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+
+ gtk_window_set_title(GTK_WINDOW(dialog), "Select recipients");
+ gtk_widget_show_all(dialog);
+ // make sure dialog is destroyed when user responds
+ response = gtk_dialog_run(GTK_DIALOG(dialog));
+ if (response == GTK_RESPONSE_CANCEL)
+ {
+ gtk_widget_destroy(dialog);
+ return 0;
+ }
+ index = gtk_combo_box_get_active(GTK_COMBO_BOX(combobox));
+ if (index && index <= ed->nskeys)
+ {
+ *sign = 1;
+ gpgme_signers_add(ed->ctx, ed->skey_array[index - 1]); // -1 because the first option is `None'
+ }
+ // try to loop all the keys in the list
+ // if they are active (the user checked the checkbox in front of the key)
+ // add it to the selected array, finaly make sure that the array
+ // is NULL terminated
+ if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(list), &iter))
+ {
+ capacity = SIZE;
+ *selected = (gpgme_key_t*) malloc(SIZE * sizeof(gpgme_key_t));
+ index = 0;
+ sindex = 0;
+ gtk_tree_model_get(GTK_TREE_MODEL(list), &iter, TOGGLE_COLUMN, &active, -1);
+ if (active)
+ (*selected)[sindex++] = ed->key_array[index];
+
+ while (gtk_tree_model_iter_next(GTK_TREE_MODEL(list), &iter))
+ {
+ ++index;
+ gtk_tree_model_get(GTK_TREE_MODEL(list), &iter, TOGGLE_COLUMN, &active, -1);
+ if (active)
+ (*selected)[sindex++] = ed->key_array[index];
+ if (sindex >= capacity - 1)
+ {
+ capacity += SIZE;
+ *selected = (gpgme_key_t*) realloc(*selected, capacity * sizeof(gpgme_key_t));
+ }
+ }
+ (*selected)[sindex] = NULL;
+ }
+ else
+ {
+ gtk_widget_destroy(dialog);
+ return 0;
+ }
+
+ gtk_widget_destroy(dialog);
+ return 1;
+}
+
+int geanypg_sign_selection_dialog(encrypt_data * ed)
+{
+ GtkWidget * dialog = gtk_dialog_new();
+ unsigned long index;
+ int response;
+ GtkWidget * contentarea = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ GtkWidget * combobox = geanypg_combobox(
+ geanypg_makelist(ed->skey_array, ed->nskeys, 0));
+
+ gtk_box_pack_start(GTK_BOX(contentarea), gtk_label_new("Choose a key to sign with:"), FALSE, FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(contentarea), combobox, TRUE, TRUE, 0);
+
+ // add ok and cancel buttons
+ gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_OK, GTK_RESPONSE_OK);
+ gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+
+ gtk_widget_show_all(dialog);
+ gtk_window_set_title(GTK_WINDOW(dialog), "Select signer");
+ // make sure dialog is destroyed when user responds
+ response = gtk_dialog_run(GTK_DIALOG(dialog));
+ if (response == GTK_RESPONSE_CANCEL)
+ {
+ gtk_widget_destroy(dialog);
+ return 0;
+ }
+ index = gtk_combo_box_get_active(GTK_COMBO_BOX(combobox));
+ gpgme_signers_clear(ed->ctx);
+ if (index < ed->nskeys)
+ gpgme_signers_add(ed->ctx, ed->skey_array[index]);
+
+ gtk_widget_destroy(dialog);
+ return 1;
+}
Added: trunk/geanypg/src/pinentry.c
===================================================================
--- trunk/geanypg/src/pinentry.c (rev 0)
+++ trunk/geanypg/src/pinentry.c 2011-02-26 17:02:33 UTC (rev 1938)
@@ -0,0 +1,194 @@
+// pinentry.c
+//
+// Copyright 2011 Hans Alves <alves.h88 at gmail.com>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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.
+
+#include "geanypg.h"
+
+static const char * geanypg_getname(const char * uid_hint)
+{
+ int space = 0;
+ if (!uid_hint)
+ return NULL;
+ while (*uid_hint && !(space && *uid_hint != ' '))
+ {
+ if (*uid_hint == ' ')
+ space = 1;
+ ++uid_hint;
+ }
+ return uid_hint;
+}
+
+#ifdef __unix__
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+static void geanypg_read_till(int fd, char delim)
+{
+ while (1)
+ {
+ char val;
+ unsigned long rv = read(fd, &val, 1);
+ if (!rv || val == delim)
+ break;
+ }
+}
+
+static int geanypg_read(int fd, char delim, int max, char * buffer)
+{
+ int index, rv = 1;
+ char ch = 0;
+ for (index = 0; (index < max - 1) && rv && ch != delim; ++index)
+ {
+ rv = read(fd, &ch, 1);
+ buffer[index] = ch;
+ }
+ buffer[index ? index - 1 : 0] = 0;
+ return index ? index - 1 : 0;
+}
+gpgme_error_t geanypg_passphrase_cb(void * hook,
+ const char * uid_hint,
+ const char * passphrase_info,
+ int prev_was_bad ,
+ int fd)
+{
+ int outpipe[2];
+ int inpipe[2];
+ int childpid;
+ int status;
+ char readbuffer[2080]; // pinentry should at least support passphrases of up to 2048 characters
+ FILE * childin;
+
+ if (pipe(outpipe))
+ {
+ fprintf(stderr, "GEANYPG: %s\n", strerror(errno));
+ return gpgme_error_from_errno(errno);
+ }
+ if (pipe(inpipe))
+ {
+ fprintf(stderr, "GEANYPG: %s\n", strerror(errno));
+ return gpgme_error_from_errno(errno);
+ }
+
+ childpid = fork();
+ if (!childpid)
+ { // pinentry
+ char * argv[] = {"pinentry", NULL};
+
+ close(outpipe[READ]);
+ dup2(outpipe[WRITE], STDOUT_FILENO);
+
+ close(inpipe[WRITE]);
+ dup2(inpipe[READ], STDIN_FILENO);
+
+ execvp(*argv, argv);
+ // shouldn't get here
+ fprintf(stderr, "GEANYPG: could not use pinentry.\n%s\n", strerror(errno));
+ exit(1); // kill the child
+ }
+ // GeanpyPG
+ close(outpipe[WRITE]);
+ close(inpipe[READ]);
+ childin = fdopen(inpipe[WRITE], "w");
+
+ // To understand what's happening here, read the pinentry documentation
+ geanypg_read(outpipe[READ], ' ', 2049, readbuffer);
+ if (strncmp(readbuffer, "OK", 3))
+ {
+ fprintf(stderr, "GEANYPG: unexpected output from pinentry\n");
+ fclose(childin);
+ waitpid(childpid, &status, 0);
+ close(outpipe[READ]);
+ close(fd);
+ return gpgme_err_make(GPG_ERR_SOURCE_PINENTRY, GPG_ERR_GENERAL);
+ }
+ geanypg_read_till(outpipe[READ], '\n'); // read the rest of the first line after OK
+ fprintf(childin, "SETTITLE GeanyPG Passphrase entry\n");
+ fflush(childin);
+ geanypg_read_till(outpipe[READ], '\n');
+
+ fprintf(childin, "SETPROMPT%s\n", (uid_hint && *uid_hint ? "" : " Passphrase:"));
+ fflush(childin);
+ geanypg_read_till(outpipe[READ], '\n');
+
+ fprintf(childin, "SETDESC %s%s\n",
+ (uid_hint && *uid_hint ? "Enter passphrase for:%0A" : ""),
+ (uid_hint && *uid_hint ? geanypg_getname(uid_hint) : ""));
+ fflush(childin);
+ geanypg_read_till(outpipe[READ], '\n');
+
+ fprintf(childin, "GETPIN\n");
+ fflush(childin);
+
+ geanypg_read(outpipe[READ], ' ', 2049, readbuffer);
+ if (!strncmp(readbuffer, "D", 2))
+ {
+ while (1)
+ {
+ char val;
+ register unsigned long rv = read(outpipe[READ], &val, 1);
+ if (!rv || val == '\n')
+ {
+ while (!write(fd, "\n", 1));
+ break;
+ }
+ while (!write(fd, &val, 1));
+ }
+ }
+ else
+ {
+ unsigned long errval;
+ if (!strncmp(readbuffer, "ERR", 4))
+ {
+ geanypg_read(outpipe[READ], ' ', 2049, readbuffer);
+ sscanf(readbuffer, "%lu", &errval);
+ geanypg_read(outpipe[READ], '\n', 2049, readbuffer);
+ fprintf(stderr, "GEANYPG: pinentry gave error %lu %s\n", errval, readbuffer);
+ }
+ else
+ fprintf(stderr, "GEANYPG: unexpected error from pinentry\n");
+ fclose(childin);
+ waitpid(childpid, &status, 0);
+ close(outpipe[READ]);
+ close(fd);
+ return gpgme_err_make(GPG_ERR_SOURCE_PINENTRY,
+ (!strncmp(readbuffer, "canceled", 9) ? GPG_ERR_CANCELED : GPG_ERR_GENERAL));
+ }
+
+
+ fclose(childin);
+ waitpid(childpid, &status, 0);
+ close(outpipe[READ]);
+ close(fd);
+ return GPG_ERR_NO_ERROR;
+}
+
+#else
+
+gpgme_error_t geanypg_passphrase_cb(void *hook,
+ const char *uid_hint,
+ const char *passphrase_info,
+ int prev_was_bad ,
+ int fd)
+{
+ dialogs_show_msgbox(GTK_MESSAGE_ERROR, "Error, Passphrase input without using gpg-agent is not supported on Windows yet.");
+ return gpgme_err_make(GPG_ERR_SOURCE_PINENTRY, GPG_ERR_CANCELED);
+}
+#endif
+
Added: trunk/geanypg/src/sign_cb.c
===================================================================
--- trunk/geanypg/src/sign_cb.c (rev 0)
+++ trunk/geanypg/src/sign_cb.c 2011-02-26 17:02:33 UTC (rev 1938)
@@ -0,0 +1,73 @@
+// sign_cb.c
+//
+// Copyright 2011 Hans Alves <alves.h88 at gmail.com>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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.
+
+
+#include "geanypg.h"
+
+void geanypg_sign(encrypt_data * ed)
+{
+ gpgme_data_t plain, cipher;
+ gpgme_error_t err;
+ FILE * tempfile;
+
+ tempfile = tmpfile();
+ if (!(tempfile))
+ {
+ fprintf(stderr, "GEANYPG: couldn't create tempfile: %s.\n", strerror(errno));
+ return ;
+ }
+ gpgme_data_new_from_stream(&cipher, tempfile);
+ gpgme_data_set_encoding(cipher, GPGME_DATA_ENCODING_ARMOR);
+
+ geanypg_load_buffer(&plain);
+
+ err = gpgme_op_sign(ed->ctx, plain , cipher, GPGME_SIG_MODE_CLEAR);
+ if (err != GPG_ERR_NO_ERROR && gpgme_err_code(err) != GPG_ERR_CANCELED)
+ geanypg_show_err_msg(err);
+ else
+ {
+ rewind(tempfile);
+ geanypg_write_file(tempfile);
+ }
+
+ fclose(tempfile);
+ // release buffers
+ gpgme_data_release(plain);
+ gpgme_data_release(cipher);
+}
+
+void geanypg_sign_cb(GtkMenuItem * menuitem, gpointer user_data)
+{
+ encrypt_data ed;
+ geanypg_init_ed(&ed);
+ gpgme_error_t err = gpgme_new(&ed.ctx);
+ if (err && geanypg_show_err_msg(err))
+ return;
+ ed.key_array = NULL;
+ ed.nkeys = 0;
+ //gpgme_set_armor(ed.ctx, 1);
+ gpgme_set_passphrase_cb(ed.ctx, geanypg_passphrase_cb, NULL);
+ if (geanypg_get_secret_keys(&ed))
+ {
+ if (geanypg_sign_selection_dialog(&ed))
+ geanypg_sign(&ed);
+ }
+ geanypg_release_keys(&ed);
+ gpgme_release(ed.ctx);
+}
Added: trunk/geanypg/src/verify_aux.c
===================================================================
--- trunk/geanypg/src/verify_aux.c (rev 0)
+++ trunk/geanypg/src/verify_aux.c 2011-02-26 17:02:33 UTC (rev 1938)
@@ -0,0 +1,178 @@
+// verify_aux.c
+//
+// Copyright 2011 Hans Alves <alves.h88 at gmail.com>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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.
+
+
+#include "geanypg.h"
+
+
+void geanypg_get_keys_with_fp(encrypt_data * ed, char * buffer)
+{
+ unsigned long index, found = 0;
+ for (index = 0; index < ed->nkeys && ! found; ++index)
+ {
+ gpgme_subkey_t sub = ed->key_array[index]->subkeys;
+ while (sub && !found)
+ {
+ if (sub->fpr && !strncmp(sub->fpr, buffer, 40))
+ {
+
+ char * name = (ed->key_array[index]->uids && ed->key_array[index]->uids->name) ? ed->key_array[index]->uids->name : "";
+ char * email = (ed->key_array[index]->uids && ed->key_array[index]->uids->email) ? ed->key_array[index]->uids->email : "";
+ if (strlen(name) + strlen(email) < 500)
+ sprintf(buffer, "%s <%s>", name, email);
+ else
+ {
+ char tmp[62];
+ strncpy(tmp, buffer, 41);
+ sprintf(buffer, "a key with fingerprint %s", tmp);
+ }
+ found = 1;
+ }
+ sub = sub->next;
+ }
+ }
+}
+
+static const char * geanypg_validity(gpgme_sigsum_t summary)
+{
+ switch (summary)
+ {
+ case GPGME_VALIDITY_UNKNOWN: return "unknown";
+ case GPGME_VALIDITY_UNDEFINED:return "undefined";
+ case GPGME_VALIDITY_NEVER: return "never";
+ case GPGME_VALIDITY_MARGINAL: return "marginal";
+ case GPGME_VALIDITY_FULL: return "full";
+ case GPGME_VALIDITY_ULTIMATE: return "ultimate";
+ default : return "[bad validity value]";
+ }
+ return "[bad validity value]";
+}
+
+static char * geanypg_summary(gpgme_sigsum_t summary, char * buffer)
+{ // buffer should be more than 105 bytes long
+ if (summary & GPGME_SIGSUM_VALID) strcat(buffer, " valid");
+ if (summary & GPGME_SIGSUM_GREEN) strcat(buffer, " green");
+ if (summary & GPGME_SIGSUM_RED) strcat(buffer, " red");
+ if (summary & GPGME_SIGSUM_KEY_REVOKED) strcat(buffer, " revoked");
+ if (summary & GPGME_SIGSUM_KEY_EXPIRED) strcat(buffer, " key-expired");
+ if (summary & GPGME_SIGSUM_SIG_EXPIRED) strcat(buffer, " sig-expired");
+ if (summary & GPGME_SIGSUM_KEY_MISSING) strcat(buffer, " key-missing");
+ if (summary & GPGME_SIGSUM_CRL_MISSING) strcat(buffer, " crl-missing");
+ if (summary & GPGME_SIGSUM_CRL_TOO_OLD) strcat(buffer, " crl-too-old");
+ if (summary & GPGME_SIGSUM_BAD_POLICY) strcat(buffer, " bad-policy");
+ if (summary & GPGME_SIGSUM_SYS_ERROR) strcat(buffer, " sys-error");
+ return buffer;
+}
+
+static char * geanypg_result(gpgme_signature_t sig)
+{
+ char format[] =
+ "status ....: %s\n"
+ "summary ...:%s\n"
+ "fingerprint: %s\n"
+ "created ...: %s"
+ "expires ...: %s"
+ "validity ..: %s\n"
+ "val.reason : %s\n"
+ "pubkey algo: %s\n"
+ "digest algo: %s\n"
+ "pka address: %s\n"
+ "pka trust .: %s\n"
+ "other flags:%s%s\n"
+ "notations .: %s\n"; // 210 characters
+ char * buffer = (char *)calloc(2048, 1); // everything together probably won't be more
+ // than 1061 characters, but we don't want to
+ // take risks
+ char summary[128];
+ const char * pubkey = gpgme_pubkey_algo_name(sig->pubkey_algo);
+ const char * hash = gpgme_hash_algo_name(sig->hash_algo);
+ char created[64];
+ char expires[64];
+ if (sig->timestamp)
+ strncpy(created, ctime((time_t*)&sig->timestamp), 64);
+ else
+ strcpy(created, "Unknown\n");
+
+ if (sig->exp_timestamp)
+ strncpy(expires, ctime((time_t*)&sig->exp_timestamp), 64);
+ else
+ strcpy(expires, "Unknown\n");
+
+ memset(summary, 0, 128);
+ sprintf(buffer, format,
+ gpgme_strerror(sig->status), // probably won't be more than 128
+ geanypg_summary(sig->summary, summary), // max 105 characters
+ sig->fpr ? sig->fpr : "[None]", // max 40 characters
+ created, // probably about 24 characters
+ expires, // probably about 24 characters
+ geanypg_validity(sig->validity), // max 11 characters
+ gpgme_strerror(sig->status), // probably won't be more than 128
+ pubkey ? pubkey : "Unknown", // probably won't be more than 32
+ hash ? hash : "Unknown", // probably won't be more than 32
+ sig->pka_address ? sig->pka_address : "[None]", // probably won't be more than 128
+ sig->pka_trust == 0 ? "n/a" : sig->pka_trust == 1 ? "bad" : sig->pka_trust == 2 ? "okay": "RFU", // max 4 characters
+ sig->wrong_key_usage ? " wrong-key-usage" : "", sig->chain_model ? " chain-model" : "", // max 28 characters
+ sig->notations ? "yes" : "no"); // max 3 characters
+ return buffer;
+}
+void geanypg_check_sig(encrypt_data * ed, gpgme_signature_t sig)
+{
+ GtkWidget * dialog;
+ gpgme_sigsum_t summary;
+ char buffer[512];
+ strncpy(buffer, sig->fpr, 40);
+ buffer[40] = 0;
+ geanypg_get_keys_with_fp(ed, buffer);
+ summary = sig->summary;
+ char * result = geanypg_result(sig);
+
+ dialog = gtk_message_dialog_new_with_markup(GTK_WINDOW(geany->main_widgets->window),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_OK,
+ "Found a signature from %s\n<tt>%s</tt>",
+ buffer,
+ result);
+ gtk_window_set_title(GTK_WINDOW(dialog), "Signature");
+
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ free(result);
+ gtk_widget_destroy(dialog);
+}
+
+void geanypg_handle_signatures(encrypt_data * ed)
+{
+ int verified = 0;
+ gpgme_verify_result_t vres = gpgme_op_verify_result(ed->ctx);
+ if (vres)
+ {
+ gpgme_signature_t sig = vres->signatures;
+ while (sig)
+ {
+ geanypg_check_sig(ed, sig);
+ sig = sig->next;
+ verified = 1;
+ }
+ }
+ if (!verified)
+ {
+ fprintf(stderr, "GEANYPG: could not find verification results\n");
+ dialogs_show_msgbox(GTK_MESSAGE_ERROR, "Error, could not find verification results");
+ }
+}
Added: trunk/geanypg/src/verify_cb.c
===================================================================
--- trunk/geanypg/src/verify_cb.c (rev 0)
+++ trunk/geanypg/src/verify_cb.c 2011-02-26 17:02:33 UTC (rev 1938)
@@ -0,0 +1,81 @@
+// verify_cb.c
+//
+// Copyright 2011 Hans Alves <alves.h88 at gmail.com>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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.
+
+#include "geanypg.h"
+
+char * geanypg_choose_sig()
+{
+ int response;
+ char * file = NULL;
+ GtkWidget * dialog = gtk_file_chooser_dialog_new("Open a signature file",
+ GTK_WINDOW(geany->main_widgets->window),
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_OPEN, GTK_RESPONSE_OK,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ NULL);
+ gtk_widget_show_all(dialog);
+ response = gtk_dialog_run(GTK_DIALOG(dialog));
+ if (response == GTK_RESPONSE_OK)
+ file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
+ gtk_widget_destroy(dialog);
+ return file;
+}
+
+void geanypg_verify(encrypt_data * ed, char * signame)
+{
+ gpgme_data_t sig, text;
+ gpgme_error_t err;
+ FILE * sigfile = fopen(signame, "r");
+ gpgme_data_new_from_stream(&sig, sigfile);
+ geanypg_load_buffer(&text);
+
+ err = gpgme_op_verify(ed->ctx, sig, text, NULL);
+
+ if (err != GPG_ERR_NO_ERROR)
+ geanypg_show_err_msg(err);
+ else
+ geanypg_handle_signatures(ed);
+
+ gpgme_data_release(sig);
+ gpgme_data_release(text);
+ fclose(sigfile);
+}
+
+void geanypg_verify_cb(GtkMenuItem * menuitem, gpointer user_data)
+{
+ char * sigfile = NULL;
+ encrypt_data ed;
+ geanypg_init_ed(&ed);
+ gpgme_error_t err = gpgme_new(&ed.ctx);
+ if (err && geanypg_show_err_msg(err))
+ return;
+ gpgme_set_protocol(ed.ctx, GPGME_PROTOCOL_OpenPGP);
+ gpgme_set_passphrase_cb(ed.ctx, geanypg_passphrase_cb, NULL);
+ if (geanypg_get_keys(&ed) && geanypg_get_secret_keys(&ed))
+ {
+ sigfile = geanypg_choose_sig();
+ if (sigfile)
+ {
+ geanypg_verify(&ed, sigfile);
+ g_free(sigfile);
+ }
+ }
+ geanypg_release_keys(&ed);
+ gpgme_release(ed.ctx);
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Plugins-Commits
mailing list