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