[pan2: 243/268] basic gpg support with gmime 2.6
- From: Heinrich MÃller <henmull src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pan2: 243/268] basic gpg support with gmime 2.6
- Date: Mon, 2 Jan 2012 15:58:26 +0000 (UTC)
commit 5cecf5150b47edde007ff02525dbe3f4fd1c7840
Author: Heinrich MÃller <henmull src gnome org>
Date: Mon Dec 12 22:58:33 2011 +0100
basic gpg support with gmime 2.6
README | 3 +-
configure.in | 13 +-
gtkspell/examples/advanced.c | 82 --
gtkspell/examples/simple.c | 58 -
gtkspell/gtkspell/deprecated.c | 35 -
gtkspell/gtkspell/gtkspell.c | 888 -------------
pan/data-impl/article-filter.cc | 10 +-
pan/data-impl/profiles.cc | 1 -
pan/data/article-cache.cc | 14 +-
pan/data/article-cache.h | 11 +-
pan/gui/Makefile.am | 11 +-
pan/gui/body-pane.cc | 108 +--
pan/gui/body-pane.h | 11 +-
pan/gui/gpg.cc | 133 --
pan/gui/gpg.h | 79 --
pan/gui/gui.cc | 18 +-
pan/gui/pan.cc | 6 +-
pan/gui/post-ui.cc | 51 +-
pan/gui/post-ui.h | 4 -
pan/gui/profiles-dialog.cc | 80 +-
pan/gui/profiles-dialog.h | 3 +-
pan/tasks/task-upload.cc | 2 -
pan/usenet-utils/Makefile.am | 10 +-
pan/usenet-utils/gpg.cc | 134 ++
pan/usenet-utils/gpg.h | 132 ++
pan/usenet-utils/mime-utils.cc | 591 +++------
pan/usenet-utils/mime-utils.h | 40 +-
uulib/uuscan.c | 70 +-
yenclib/crc32.c | 614 ---------
yenclib/crc32.h | 38 -
yenclib/uuencode.c | 2692 ---------------------------------------
yenclib/uunconc.c | 1718 -------------------------
32 files changed, 612 insertions(+), 7048 deletions(-)
---
diff --git a/README b/README
index 0896543..05322cd 100644
--- a/README
+++ b/README
@@ -7,7 +7,7 @@ REQUIREMENTS
Pan requires these libraries:
* GTK+ 2.16.0 or higher (optionally GTK+ 3.0.0 or higher) <http://www.gtk.org/>
- * gmime 2.4.0 or higher <http://spruce.sourceforge.net/gmime/>
+ * gmime 2.6.0 or higher <http://spruce.sourceforge.net/gmime/>
Spellchecking requires the following library:
* gtkspell 2.0.7 or higher <http://gtkspell.sourceforge.net>
@@ -16,7 +16,6 @@ REQUIREMENTS
* Libnotify (0.4.1)
* Gnome-Keyring (3.2.2)
* DBUS
- * GPGME(made-easy) (1.3.0)
Most Linux distributions already have these; they can also be
downloaded from their home pages or installed via packet managers.
diff --git a/configure.in b/configure.in
index a89b89a..1c85995 100644
--- a/configure.in
+++ b/configure.in
@@ -46,7 +46,7 @@ dnl GtkSpell is optional: GTKSPELL_REQUIRED refers to the minimum version
dnl needed if you want to build Pan with spellchecking in the Post window.
GLIB_REQUIRED=2.14.0
-GMIME_REQUIRED=2.4.0
+GMIME_REQUIRED=2.6.0
GTK_REQUIRED=2.16.0
GTK3_REQUIRED=3.0.0
GTKSPELL_REQUIRED=2.0.7
@@ -54,7 +54,6 @@ OPENSSL_REQUIRED=1.0.0
LIBNOTIFY_REQUIRED=0.4.1
LIBGSASL_REQUIRED=1.6.1
LIBGKR_REQUIRED=3.2.2
-LIBGPGME_REQUIRED=1.3.0
AC_SUBST(GLIB_REQUIRED)
AC_SUBST(GMIME_REQUIRED)
AC_SUBST(GTK_REQUIRED)
@@ -156,16 +155,6 @@ if test "x$enable_gkr" = "xyes" ; then
fi
fi
-dnl Check for gpgme for message encryption / signing
-AC_ARG_ENABLE([gpgme],
-AC_HELP_STRING([--enable-gpgme],[enable gpgme support]),[enable_gpgme=$enableval],[enable_gpgme=yes])
-if test "x$enable_gpgme" = "xyes" ; then
- AM_PATH_GPGME([$LIBGPGME_REQUIRED],[HAVE_GPGME="yes"],[HAVE_GPGME="no"])
- if test "x$HAVE_GPGME" = "xyes"; then
- AC_DEFINE([HAVE_GPGME],[1],[gpgme for message encryption / signing])
- fi
-fi
-
dnl Check to see if strftime supports the use of %l and %k
AC_MSG_CHECKING(for %l and %k support in strftime)
AC_TRY_RUN([
diff --git a/pan/data-impl/article-filter.cc b/pan/data-impl/article-filter.cc
index 8bee5a7..82f2dce 100644
--- a/pan/data-impl/article-filter.cc
+++ b/pan/data-impl/article-filter.cc
@@ -189,13 +189,9 @@ ArticleFilter :: test_article (const Data & data,
{
if (cache.contains(article.message_id)) {
ArticleCache::mid_sequence_t mid(1, article.message_id);
-#ifdef HAVE_GPGME
- GPGDecErr unused_for_now;
- GPGSignersInfo unused;
- GMimeMessage *msg = cache.get_message(mid, unused, unused_for_now);
-#else
- GMimeMessage *msg = cache.get_message(mid);
-#endif
+ GPGDecErr err;
+ GMimeMessage *msg = cache.get_message(mid,err);
+
const char *hdr = g_mime_object_get_header(GMIME_OBJECT(msg), criteria._header);
pass = criteria._text.test (hdr);
g_object_unref(msg);
diff --git a/pan/data-impl/profiles.cc b/pan/data-impl/profiles.cc
index b844689..646977a 100644
--- a/pan/data-impl/profiles.cc
+++ b/pan/data-impl/profiles.cc
@@ -105,7 +105,6 @@ namespace
p.use_sigfile = !strcmp (*v, "true");
p.sig_type = p.GPGSIG;
p.use_gpgsig = true;
- std::cerr<<"got profile "<<p.use_sigfile<<" "<<p.use_gpgsig<<"\n";
}
}
}
diff --git a/pan/data/article-cache.cc b/pan/data/article-cache.cc
index f76333c..2d82a31 100644
--- a/pan/data/article-cache.cc
+++ b/pan/data/article-cache.cc
@@ -398,11 +398,7 @@ ArticleCache :: get_message_mem_stream (const Quark& mid) const
}
GMimeMessage*
-#ifdef HAVE_GPGME
-ArticleCache :: get_message (const mid_sequence_t& mids, GPGSignersInfo& signer_info, GPGDecErr& err) const
-#else
-ArticleCache :: get_message (const mid_sequence_t& mids) const
-#endif
+ArticleCache :: get_message (const mid_sequence_t& mids, GPGDecErr& err) const
{
debug ("trying to get a message with " << mids.size() << " parts");
GMimeMessage * retval = NULL;
@@ -423,13 +419,11 @@ ArticleCache :: get_message (const mid_sequence_t& mids) const
streams.push_back (stream);
}
+
// build the message
if (!streams.empty())
-#ifdef HAVE_GPGME
- retval = mime :: construct_message (&streams.front(), streams.size(), signer_info, err);
-#else
- retval = mime :: construct_message (&streams.front(), streams.size());
-#endif
+ retval = mime :: construct_message (&streams.front(), streams.size(), err);
+
// cleanup
foreach (streams_t, streams, it)
g_object_unref (*it);
diff --git a/pan/data/article-cache.h b/pan/data/article-cache.h
index 31937e8..bffe5a7 100644
--- a/pan/data/article-cache.h
+++ b/pan/data/article-cache.h
@@ -28,9 +28,7 @@ extern "C" {
#include <pan/general/string-view.h>
#include <pan/general/quark.h>
-#ifdef HAVE_GPGME
- #include <pan/gui/gpg.h>
-#endif
+#include <pan/usenet-utils/gpg.h>
extern "C"
{
@@ -74,11 +72,8 @@ namespace pan
void resize ();
void clear ();
-#ifdef HAVE_GPGME
- GMimeMessage* get_message (const mid_sequence_t&, GPGSignersInfo&, GPGDecErr&) const;
-#else
- GMimeMessage* get_message (const mid_sequence_t&) const;
-#endif
+ GMimeMessage* get_message (const mid_sequence_t&, GPGDecErr&) const;
+
typedef std::vector<std::string> strings_t;
strings_t get_filenames (const mid_sequence_t&);
diff --git a/pan/gui/Makefile.am b/pan/gui/Makefile.am
index 2e930cf..7730a7c 100644
--- a/pan/gui/Makefile.am
+++ b/pan/gui/Makefile.am
@@ -1,5 +1,5 @@
AM_CPPFLAGS = -I top_srcdir@ @GTKSPELL_CFLAGS@ @GTK_CFLAGS@ @GMIME_CFLAGS@ @GLIB_CFLAGS@ \
- @OPENSSL_CFLAGS@ @LIBNOTIFY_CFLAGS@ @LIBGNOME_KEYRING_1_CFLAGS@ @GPGME_CFLAGS@ -DPANLOCALEDIR=\""$(panlocaledir)"\"
+ @OPENSSL_CFLAGS@ @LIBNOTIFY_CFLAGS@ @LIBGNOME_KEYRING_1_CFLAGS@ -DPANLOCALEDIR=\""$(panlocaledir)"\"
noinst_LIBRARIES = libpangui.a
@@ -33,8 +33,7 @@ libpangui_a_SOURCES = \
server-ui.cc \
task-pane.cc \
xface.c \
- url.cc \
- gpg.cc
+ url.cc
noinst_HEADERS = \
action-manager.h \
@@ -76,8 +75,7 @@ noinst_HEADERS = \
task-pane.h \
url.h \
wait.h \
- xface.h \
- gpg.h
+ xface.h
EXTRA_DIST = \
panrc.rc
@@ -97,8 +95,7 @@ endif
pan_SOURCES = gui.cc pan.cc $(WINRC)
pan_LDADD = ./libpangui.a $(WINRCOBJ) ../data-impl/libpandata.a ../tasks/libtasks.a ../data/libdata.a ../usenet-utils/libusenetutils.a ../general/libgeneralutils.a \
- ../../uulib/libuu.a @GTKSPELL_LIBS@ @GTK_LIBS@ @GMIME_LIBS@ @GLIB_LIBS@ @OPENSSL_LIBS@ @LIBNOTIFY_LIBS@ @LIBGNOME_KEYRING_1_LIBS@ @GPGME_LIBS@
-
+ ../../uulib/libuu.a @GTKSPELL_LIBS@ @GTK_LIBS@ @GMIME_LIBS@ @GLIB_LIBS@ @OPENSSL_LIBS@ @LIBNOTIFY_LIBS@ @LIBGNOME_KEYRING_1_LIBS@
if HAVE_WIN32
pan_LDFLAGS = -mwindows
endif
diff --git a/pan/gui/body-pane.cc b/pan/gui/body-pane.cc
index bd0a79e..55f80c0 100644
--- a/pan/gui/body-pane.cc
+++ b/pan/gui/body-pane.cc
@@ -916,25 +916,6 @@ namespace
}
-#ifdef HAVE_GPGME
-bool
-BodyPane ::get_gpgsig_from_gmime_part (GMimeObject* parent, GMimeObject* base, GMimePart * part)
-{
- GMimeDataWrapper * wrapper (g_mime_part_get_content_object (part));
- GMimeStream * mem_stream (g_mime_stream_mem_new ());
- if (wrapper)
- {
- g_mime_data_wrapper_write_to_stream (wrapper, mem_stream);
- g_mime_stream_reset(mem_stream);
- gpg_decrypt_and_verify(_signer_info, _gpgerr, mem_stream,
- g_mime_multipart_index_of(GMIME_MULTIPART(parent),base),
- parent);
- return true;
- }
- return false;
-}
-#endif
-
void
BodyPane :: append_part (GMimeObject * parent, GMimeObject * obj, GtkAllocation * widget_size)
{
@@ -1000,8 +981,7 @@ BodyPane :: append_part (GMimeObject * parent, GMimeObject * obj, GtkAllocation
}
// or, if it's text, display it
- else if (g_mime_content_type_is_type (type, "text", "*") ||
- (g_mime_content_type_is_type (type, "*", "pgp-signature")))
+ else if (g_mime_content_type_is_type (type, "text", "*"))
{
const char * fallback_charset (_charset.c_str());
const char * p_flowed (g_mime_object_get_content_type_parameter(obj,"format"));
@@ -1017,16 +997,6 @@ BodyPane :: append_part (GMimeObject * parent, GMimeObject * obj, GtkAllocation
const bool do_urls (_prefs.get_flag ("highlight-urls", true));
append_text_buffer_nolock (&_tm, _buffer, str, do_mute, do_smilies, do_markup, do_urls);
is_done = true;
-#ifdef HAVE_GPGME
- /* verify signature */
-
- if (g_mime_content_type_is_type (type, "*", "pgp-signature"))
- {
- bool res = get_gpgsig_from_gmime_part(parent, obj, part);
- std::cerr<<"1023\n";
- if (res) update_sig_valid(_gpgerr.verify_ok);
- }
-#endif
}
// otherwise, bitch and moan.
@@ -1218,6 +1188,7 @@ BodyPane :: set_text_from_message (GMimeMessage * message)
// the all-headers don't get included in the followup
// set the text buffer...
+
if (message)
g_mime_message_foreach (message, foreach_part_cb, this);
@@ -1231,7 +1202,6 @@ BodyPane :: set_text_from_message (GMimeMessage * message)
gtk_text_buffer_get_start_iter (_buffer, &iter);
gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW(_text), &iter, 0.0, true, 0.0, 0.0);
}
- std::cerr<<"1234\n";
}
@@ -1244,17 +1214,23 @@ BodyPane :: refresh ()
namespace
{
- std::string get_email_address(std::string& s)
+ /** Separates user id into name and email address */
+ std::pair<std::string,std::string> get_email_address(std::string& s)
{
+ std::pair<std::string,std::string> ret;
size_t in = s.find("<");
size_t out = s.find(">");
- if (in == std::string::npos || out == std::string::npos) return "...";
+ if (in == std::string::npos ||
+ out == std::string::npos)
+ return ret;
+
+ ret.first = s.substr(0,in-1);
+ ret.second = s.substr (in+1,out-in-1);
- return s.substr (in+1,out-in-1);
+ return ret;
}
}
-#ifdef HAVE_GPGME
gboolean
BodyPane:: on_tooltip_query(GtkWidget *widget,
gint x,
@@ -1265,27 +1241,23 @@ BodyPane:: on_tooltip_query(GtkWidget *widget,
{
BodyPane* pane = static_cast<BodyPane*>(data);
GPGDecErr& err = pane->_gpgerr;
- GPGSignersInfo& info = pane->_signer_info;
-
-// g_return_val_if_fail(err.dec_ok, false);
- g_return_val_if_fail(err.err == GPG_ERR_NO_ERROR || err.err == GPG_ERR_NO_DATA, false);
+ GPGSignersInfo& info = err.signers;
if (err.no_sigs) return false;
- if (!err.v_res) return false;
- if (!err.v_res->signatures) return false;
- if (!err.v_res->signatures->fpr) return false;
+ if (info.signers.empty()) return false;
EvolutionDateMaker ed;
char buf[2048];
+ std::pair<std::string,std::string> name_and_email = get_email_address(info.signers[0].name);
g_snprintf(buf, sizeof(buf),
- "<u>This is a <b>GPG-Signed</b> message.</u>\n\n"
- "<b>Signer</b> : %s (\"%s\")\n"
+ "<u>This is a <b>PGP-Signed</b> message.</u>\n\n"
+ "<b>Signer</b> : %s ('%s')\n"
"<b>Valid until</b> : %s\n"
"<b>Created on</b> : %s",
- info.real_name.c_str(), get_email_address(info.uid).c_str(),
- ed.get_date_string(info.expires),
- ed.get_date_string(info.creation_timestamp)
+ name_and_email.first.c_str(), name_and_email.second.c_str(),
+ (info.signers[0].never_expires ? "always" : ed.get_date_string(info.signers[0].expires)),
+ ed.get_date_string(info.signers[0].created)
);
gtk_tooltip_set_icon_from_stock (tooltip, GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG);
@@ -1299,12 +1271,8 @@ void
BodyPane :: update_sig_valid(int i)
{
- std::cerr<<"update sig "<<i<<"\n";
-
gtk_image_clear(GTK_IMAGE(_sig_icon));
- i = 1;
-
switch (i)
{
case 0:
@@ -1316,36 +1284,30 @@ BodyPane :: update_sig_valid(int i)
break;
}
}
-#endif
void
BodyPane :: set_article (const Article& a)
{
_article = a;
- const char* gpg_sign(0);
-
if (_message)
g_object_unref (_message);
-#ifdef HAVE_GPGME
- _message = _cache.get_message (_article.get_part_mids(), _signer_info, _gpgerr);
- gpg_sign = g_mime_object_get_header(GMIME_OBJECT(_message), "X-GPG-Signed");
-#else
- _message = _cache.get_message (_article.get_part_mids());
-#endif
+
+ _gpgerr.clear();
+
+ _message = _cache.get_message (_article.get_part_mids(), _gpgerr);
int val(-1);
- if (gpg_sign)
{
- if (!strcmp(gpg_sign, "valid"))
+ if (_gpgerr.verify_ok && !_gpgerr.no_sigs)
val = 1;
- else if (!strcmp(gpg_sign, "invalid"))
+ else if (!_gpgerr.verify_ok && !_gpgerr.no_sigs)
val = 0;
+ else
+ val = -1;
}
-#ifdef HAVE_GPGME
- std::cerr<<"1344\n";
+
update_sig_valid(val);
-#endif
refresh ();
_data.mark_read (_article);
@@ -1358,9 +1320,8 @@ BodyPane :: clear ()
g_object_unref (_message);
_message = 0;
refresh ();
-#ifdef HAVE_GPGME
update_sig_valid(-1);
-#endif
+
}
void
@@ -1545,7 +1506,8 @@ BodyPane :: BodyPane (Data& data, ArticleCache& cache, Prefs& prefs):
_cache (cache),
_hscroll_visible (false),
_vscroll_visible (false),
- _message (0)
+ _message (0),
+ _gpgerr(GPG_DECODE)
{
for (guint i=0; i<NUM_ICONS; ++i)
@@ -1585,12 +1547,10 @@ BodyPane :: BodyPane (Data& data, ArticleCache& cache, Prefs& prefs):
gtk_label_set_ellipsize (GTK_LABEL(w), PANGO_ELLIPSIZE_MIDDLE);
gtk_label_set_use_markup (GTK_LABEL(w), true);
gtk_box_pack_start (GTK_BOX(hbox), w, true, true, PAD_SMALL);
-#ifdef HAVE_GPGME
gtk_widget_set_size_request (_sig_icon, 32, 32);
gtk_box_pack_start (GTK_BOX(hbox), _sig_icon, true, true, PAD_SMALL);
gtk_widget_set_has_tooltip (_sig_icon, true);
g_signal_connect(_sig_icon,"query-tooltip",G_CALLBACK(on_tooltip_query), this);
-#endif
w = _xface = gtk_image_new();
gtk_widget_set_size_request (w, 48, 48);
gtk_box_pack_start (GTK_BOX(hbox), w, false, false, PAD_SMALL);
@@ -1887,7 +1847,9 @@ BodyPane :: create_followup_or_reply (bool is_reply)
g_object_unref (wrapper);
g_object_unref (part);
g_object_unref (stream);
-//std::cerr << LINE_ID << " here is the modified clone\n [" << g_mime_object_to_string((GMimeObject *)msg) << ']' << std::endl;
+
+ //std::cerr << LINE_ID << " here is the modified clone\n [" << g_mime_object_to_string((GMimeObject *)msg) << ']' << std::endl;
+
}
return msg;
diff --git a/pan/gui/body-pane.h b/pan/gui/body-pane.h
index 2120f50..8ced5d0 100644
--- a/pan/gui/body-pane.h
+++ b/pan/gui/body-pane.h
@@ -42,15 +42,16 @@ namespace pan
Data& _data;
ArticleCache& _cache;
GtkWidget* _sig_icon;
-#ifdef HAVE_GPGME
+
void update_sig_valid(int i);
+
static gboolean on_tooltip_query(GtkWidget *widget,
gint x,
gint y,
gboolean keyboard_tip,
GtkTooltip *tooltip,
gpointer data);
-#endif
+
public:
BodyPane (Data&, ArticleCache&, Prefs&);
~BodyPane ();
@@ -111,11 +112,6 @@ namespace pan
/* updated with values from gmimemessage */
public:
-#ifdef HAVE_GPGME
- GPGDecErr _gpgerr;
- GPGSignersInfo _signer_info;
- bool get_gpgsig_from_gmime_part (GMimeObject* parent, GMimeObject* base, GMimePart * part);
-#endif
private:
std::string _hover_url;
@@ -135,6 +131,7 @@ namespace pan
GMimeMessage * _message;
TextMassager _tm;
std::string _charset;
+ GPGDecErr _gpgerr;
};
}
diff --git a/pan/gui/gui.cc b/pan/gui/gui.cc
index aa8e1ce..334f7b5 100644
--- a/pan/gui/gui.cc
+++ b/pan/gui/gui.cc
@@ -69,9 +69,7 @@ extern "C" {
#include "profiles-dialog.h"
-#ifdef HAVE_GPGME
- #include "gpg.h"
-#endif
+#include <pan/usenet-utils/gpg.h>
namespace pan
{
@@ -344,9 +342,8 @@ GUI :: GUI (Data& data, Queue& queue, Prefs& prefs, GroupPrefs& group_prefs):
on_queue_task_active_changed (queue, *(*it), true);
}
}
-#ifdef HAVE_GPGME
+
init_gpg();
-#endif
}
namespace
@@ -396,9 +393,7 @@ GUI :: ~GUI ()
g_object_unref (*it);
g_object_unref (G_OBJECT(_ui_manager));
-#ifdef HAVE_GPGME
deinit_gpg();
-#endif
}
/***
@@ -695,13 +690,8 @@ namespace
virtual void on_progress_finished (Progress&, int status)
{
if (status == OK) {
-#ifdef HAVE_GPGME
- GPGDecErr unused;
- GPGSignersInfo unuse;
- GMimeMessage * message = _cache.get_message (_article.get_part_mids(), unuse, unused);
-#else
- GMimeMessage * message = _cache.get_message (_article.get_part_mids());
-#endif
+ GPGDecErr err;
+ GMimeMessage * message = _cache.get_message (_article.get_part_mids(),err);
g_mime_message_foreach (message, foreach_part_cb, this);
g_object_unref (message);
}
diff --git a/pan/gui/pan.cc b/pan/gui/pan.cc
index 9dd8968..bb16456 100644
--- a/pan/gui/pan.cc
+++ b/pan/gui/pan.cc
@@ -51,11 +51,7 @@ extern "C" {
#include <pan/tasks/socket-impl-openssl.h>
#endif
-#ifdef HAVE_GPGME
- #include <gpgme.h>
- #include <pan/gui/gpg.h>
-#endif
-
+#include <pan/usenet-utils/gpg.h>
#include <pan/data/cert-store.h>
#include <pan/tasks/socket-impl-gio.h>
#include <pan/tasks/socket-impl-main.h>
diff --git a/pan/gui/post-ui.cc b/pan/gui/post-ui.cc
index 9d7fd94..ca0247d 100644
--- a/pan/gui/post-ui.cc
+++ b/pan/gui/post-ui.cc
@@ -38,6 +38,7 @@ extern "C" {
#include <pan/general/macros.h>
#include <pan/general/utf8-utils.h>
#include <pan/usenet-utils/gnksa.h>
+#include <pan/usenet-utils/gpg.h>
#include <pan/usenet-utils/message-check.h>
#include <pan/usenet-utils/mime-utils.h>
#include <pan/data/data.h>
@@ -59,11 +60,6 @@ extern "C" {
#define DEFAULT_SPELLCHECK_FLAG false
#endif
-#ifdef HAVE_GPGME
- #include <gpgme.h>
- #include <pan/gui/gpg.h>
-#endif
-
using namespace pan;
#define USER_AGENT_PREFS_KEY "add-user-agent-header-when-posting"
@@ -132,7 +128,6 @@ namespace pan
if (!self->_realized) return;
gpg_sign = gtk_toggle_action_get_active (toggle);
- std::cerr<<"gpg sign toggle "<<gpg_sign<<"\n";
}
void on_spellcheck_toggled (GtkToggleAction * toggle, gpointer post_g)
@@ -1025,44 +1020,19 @@ PostUI :: maybe_post_message (GMimeMessage * message)
if(_file_queue_empty)
{
-#ifdef HAVE_GPGME
- GPGEncErr fail;
- if (user_has_gpg && gpg_enc && !gpg_sign)
- {
- std::cerr<<"encrypt\n";
- Profile p(get_current_profile());
- std::string res = gpg_encrypt(p.gpg_sig_uid, get_body(), fail);
- if (gpgme_err_code(fail.err) == GPG_ERR_NO_ERROR)
- gtk_text_buffer_set_text (_body_buf, res.c_str(), res.size());
- else
- {
- Log::add_err_va("Failed to encode the Message with your key : \"%s\"",gpgme_strerror(fail.err));
- return false;
- }
- }
- if (user_has_gpg && gpg_enc && gpg_sign)
- {
- std::cerr<<"encrypt\n";
- Profile p(get_current_profile());
- std::string res = gpg_encrypt_and_sign(p.gpg_sig_uid,get_body(), fail);
- if (gpgme_err_code(fail.err) == GPG_ERR_NO_ERROR)
- gtk_text_buffer_set_text (_body_buf, res.c_str(), res.size());
- else
- {
- Log::add_err_va("Failed to sign and encode the Message with your key : \"%s\"",gpgme_strerror(fail.err));
- return false;
- }
- }
-#endif
GMimeMessage* msg = new_message_from_ui(POSTING);
bool go_on(true);
-#ifdef HAVE_GPGME
+ GPtrArray * rcp = g_ptr_array_new();
Profile p(get_current_profile());
+ g_ptr_array_add(rcp, (gpointer)p.gpg_sig_uid.c_str());
if (user_has_gpg && gpg_sign && !gpg_enc)
- go_on = go_on && message_add_signed_part(p.gpg_sig_uid, get_body(), msg, fail);
-#endif
+ go_on = go_on && message_add_signed_part(p.gpg_sig_uid, get_body(), msg);
+ else if (user_has_gpg && gpg_enc && !gpg_sign)
+ go_on = go_on && gpg_encrypt(p.gpg_sig_uid, get_body(), msg, rcp, false);
+ else if (user_has_gpg && gpg_enc && gpg_sign)
+ go_on = go_on && gpg_encrypt(p.gpg_sig_uid, get_body(), msg, rcp, true);
if (go_on)
{
@@ -1070,6 +1040,7 @@ PostUI :: maybe_post_message (GMimeMessage * message)
_post_task->add_listener (this);
_queue.add_task (_post_task, Queue::TOP);
}
+
} else {
// prepend header for xml file (if one was chosen)
@@ -1545,7 +1516,7 @@ PostUI :: new_message_from_ui (Mode mode, bool copy_body)
GMimeContentType * type = g_mime_content_type_new_from_string (pch);
g_free (pch);
-// g_mime_object_set_content_type ((GMimeObject *) part, type); // part owns type now. type isn't refcounted.
+ g_mime_object_set_content_type ((GMimeObject *) part, type); // part owns type now. type isn't refcounted.
g_mime_part_set_content_object (part, content_object);
g_mime_part_set_content_encoding (part, GMIME_CONTENT_ENCODING_8BIT);
g_object_unref (content_object);
@@ -1782,7 +1753,7 @@ namespace
}
else if (type == Profile::GPGSIG)
{
- /// TODO : Perhaps show but omit in gmimemessage, or make a multipart ??
+ /// TODO : Perhaps show but omit in gmimemessage ??
}
/* Convert signature to UTF-8. Since the signature is a local file,
diff --git a/pan/gui/post-ui.h b/pan/gui/post-ui.h
index c51319a..4ae458c 100644
--- a/pan/gui/post-ui.h
+++ b/pan/gui/post-ui.h
@@ -31,10 +31,6 @@
#include <pan/usenet-utils/MersenneTwister.h>
-#ifdef HAVE_GPGME
- #include <gpgme.h>
-#endif
-
namespace pan
{
class Profiles;
diff --git a/pan/gui/profiles-dialog.cc b/pan/gui/profiles-dialog.cc
index e6f317d..14716f6 100644
--- a/pan/gui/profiles-dialog.cc
+++ b/pan/gui/profiles-dialog.cc
@@ -35,10 +35,7 @@ extern "C" {
#include "pan-file-entry.h"
#include "profiles-dialog.h"
-#ifdef HAVE_GPGME
- #include <gpgme.h>
- #include <pan/gui/gpg.h>
-#endif
+#include <pan/usenet-utils/gpg.h>
using namespace pan;
@@ -74,13 +71,15 @@ namespace
if (row == 2) // GPG
{
+ gtk_widget_set_tooltip_text(d->_signature_file_combo_box,
+ _("Please choose your Email Address according to your PGP key's user id."));
gtk_widget_hide (d->_signature_file);
- gtk_widget_show (d->_gpg_sig_entry);
+
}
else
{
+ gtk_widget_set_has_tooltip(d->_signature_file_combo_box,false);
gtk_widget_show (d->_signature_file);
- gtk_widget_hide (d->_gpg_sig_entry);
}
}
@@ -115,7 +114,6 @@ namespace
}
}
-/// TODO (perhaps) beautify this!
ProfileDialog :: ProfileDialog (const Data & data,
const StringView & profile_name,
@@ -148,6 +146,7 @@ ProfileDialog :: ProfileDialog (const Data & data,
HIG :: workarea_add_row (t, &row, _("_Full Name:"), w);
w = _address_entry = gtk_entry_new ();
set_entry (w, profile.address);
+ gtk_widget_set_tooltip_text(w, _("Your Email Address. Note that this has to match your GPG Signature's Address to verify messages correctly."));
HIG :: workarea_add_row (t, &row, _("_Email Address:"), w);
w = _server_combo = make_servers_combo (data, profile.posting_server);
HIG :: workarea_add_row (t, &row, _("_Post Articles via:"), w);
@@ -167,49 +166,18 @@ ProfileDialog :: ProfileDialog (const Data & data,
GtkTreeIter iter;
GtkListStore * store;
GtkCellRenderer * renderer;
-#ifdef HAVE_GPGME
- std::map<std::string, int> author_numbers;
- store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
- int cnt(0);
- foreach (signers_m, gpg_signers, it)
- {
- gtk_list_store_append (store, &iter);
- gtk_list_store_set (store, &iter, 0, it->second.real_name.c_str(), 1, it->first.c_str(), -1);
- author_numbers.insert(std::pair<std::string, int>(it->first,cnt++));
- }
- w = gtk_combo_box_new_with_model (GTK_TREE_MODEL(store));
- hbox = gtk_hbox_new(FALSE, 3);
- l = gtk_label_new(_("Signer : "));
- gtk_misc_set_alignment (GTK_MISC(l), 0.0f, 0.5f);
- gtk_box_pack_start(GTK_BOX(hbox), l, false, false, 0);
- gtk_box_pack_start(GTK_BOX(hbox), w, true, true, 0);
- _gpg_sig_entry = hbox;
- _gpg_sig_entry_box = w;
-
- int signer_no(0);
- if (!profile.gpg_sig_uid.empty())
- {
- if (author_numbers.count(profile.gpg_sig_uid) != 0)
- signer_no = author_numbers.find(profile.gpg_sig_uid)->second;
- }
- gtk_combo_box_set_active (GTK_COMBO_BOX(w), signer_no);
- renderer = gtk_cell_renderer_text_new ();
- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (w), renderer, true);
- gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (w), renderer, "text", 0, NULL);
-#endif
store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, _("Text File"), 1, Profile::FILE, -1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, _("Text"), 1, Profile::TEXT, -1);
gtk_list_store_append (store, &iter);
-#ifdef HAVE_GPGME
gtk_list_store_set (store, &iter, 0, _("PGP Signature"),1, Profile::GPGSIG, -1);
gtk_list_store_append (store, &iter);
-#endif
gtk_list_store_set (store, &iter, 0, _("Command"), 1, Profile::COMMAND, -1);
w = gtk_combo_box_new_with_model (GTK_TREE_MODEL(store));
+
hbox = gtk_hbox_new(FALSE, 3);
l = gtk_label_new(_("Signature Type : "));
gtk_misc_set_alignment (GTK_MISC(l), 0.0f, 0.5f);
@@ -217,32 +185,22 @@ ProfileDialog :: ProfileDialog (const Data & data,
gtk_box_pack_start(GTK_BOX(hbox), w, true, true, 0);
_signature_file_combo = hbox;
_signature_file_combo_box = w;
-#ifdef HAVE_GPGME
+
g_signal_connect (w, "changed", G_CALLBACK(on_signature_type_changed), this);
-#endif
+
renderer = gtk_cell_renderer_text_new ();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (w), renderer, true);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (w), renderer, "text", 0, NULL);
int active = ROW_FILE;
if (profile.sig_type == profile.TEXT) active = ROW_TEXT;
-#ifdef HAVE_GPGME
if (profile.sig_type == profile.GPGSIG) active = ROW_GPGSIG;
if (profile.sig_type == profile.COMMAND) active = ROW_COMMAND;
-#else
- if (profile.sig_type == profile.COMMAND) active = ROW_GPGSIG;
-#endif
-
gtk_combo_box_set_active (GTK_COMBO_BOX(w), active);
-
GtkWidget* vbox = gtk_vbox_new(TRUE, 3);
-
gtk_box_pack_start(GTK_BOX(vbox), _signature_file_combo, false, false, 0);
gtk_box_pack_start(GTK_BOX(vbox), _signature_file, false, false, 0);
-#ifdef HAVE_GPGME
- gtk_box_pack_start(GTK_BOX(vbox), _gpg_sig_entry, false, false, 0);
-#endif
HIG :: workarea_add_row (t, &row, "",vbox);
HIG :: workarea_add_section_divider (t, &row);
@@ -302,10 +260,8 @@ ProfileDialog :: ProfileDialog (const Data & data,
gtk_container_add (GTK_CONTAINER(eventbox), scrolled_window);
HIG :: workarea_add_row (t, &row, _("E_xtra Headers:"), eventbox, w);
- /// REMOVED for now!
-// on_sig_file_toggled (GTK_TOGGLE_BUTTON(_signature_file_check), _gpg_sig_entry_box);
-// on_sig_file_toggled (GTK_TOGGLE_BUTTON(_signature_file_check), _signature_file);
-// on_sig_file_toggled (GTK_TOGGLE_BUTTON(_signature_file_check), _signature_file_combo_box);
+ on_sig_file_toggled (GTK_TOGGLE_BUTTON(_signature_file_check), _signature_file);
+ on_sig_file_toggled (GTK_TOGGLE_BUTTON(_signature_file_check), _signature_file_combo_box);
gtk_box_pack_start (GTK_BOX( gtk_dialog_get_content_area( GTK_DIALOG(_root))), t, true, true, 0);
gtk_widget_show_all (t);
@@ -314,9 +270,8 @@ ProfileDialog :: ProfileDialog (const Data & data,
gtk_window_set_transient_for (GTK_WINDOW(_root), parent);
gtk_window_set_position (GTK_WINDOW(_root), GTK_WIN_POS_CENTER_ON_PARENT);
}
-#ifdef HAVE_GPGME
+
on_signature_type_changed(GTK_COMBO_BOX(_signature_file_combo_box), this);
-#endif
}
ProfileDialog :: ~ProfileDialog ()
@@ -380,14 +335,9 @@ ProfileDialog :: get_profile (std::string& profile_name, Profile& profile)
profile.use_gpgsig = (type == profile.GPGSIG);
if (!profile.use_gpgsig)
from_entry (file_entry_gtk_entry(_signature_file), profile.signature_file);
-#ifdef HAVE_GPGME
- char* uid;
- combo = GTK_COMBO_BOX (_gpg_sig_entry_box);
- gtk_combo_box_get_active_iter (combo, &iter);
- model = gtk_combo_box_get_model (combo);
- gtk_tree_model_get (model, &iter, 1, &uid, -1);
- profile.gpg_sig_uid = uid;
-#endif
+
+ profile.gpg_sig_uid = profile.address;
+
char * pch;
combo = GTK_COMBO_BOX (_server_combo);
gtk_combo_box_get_active_iter (combo, &iter);
diff --git a/pan/gui/profiles-dialog.h b/pan/gui/profiles-dialog.h
index b595a4d..28a4296 100644
--- a/pan/gui/profiles-dialog.h
+++ b/pan/gui/profiles-dialog.h
@@ -55,11 +55,10 @@ namespace pan
GtkWidget * _signature_file_check;
GtkWidget * _server_combo;
GtkWidget * _extra_headers_tv;
- GtkWidget * _signature_file_combo_box;
GtkWidget * _signature_file_combo;
- GtkWidget * _gpg_sig_entry_box;
public:
+ GtkWidget * _signature_file_combo_box;
GtkWidget * _signature_file;
GtkWidget * _gpg_sig_entry;
diff --git a/pan/tasks/task-upload.cc b/pan/tasks/task-upload.cc
index e487ca8..d4b1f99 100644
--- a/pan/tasks/task-upload.cc
+++ b/pan/tasks/task-upload.cc
@@ -212,8 +212,6 @@ TaskUpload :: prepend_headers(GMimeMessage* msg, TaskUpload::Needed * n, std::st
all = g_mime_object_to_string ((GMimeObject *) msg);
else if (_first && _queue_pos == 0)
all = g_mime_object_get_headers ((GMimeObject *) msg);
- else
- all = g_mime_object_get_headers ((GMimeObject *) msg);
out << all << "\n";
if (_first && _queue_pos == -1) g_free(all);
diff --git a/pan/usenet-utils/Makefile.am b/pan/usenet-utils/Makefile.am
index 1ebac86..33889ad 100644
--- a/pan/usenet-utils/Makefile.am
+++ b/pan/usenet-utils/Makefile.am
@@ -1,6 +1,4 @@
-AM_CPPFLAGS = -I top_srcdir@ @GMIME_CFLAGS@ @GLIB_CFLAGS@ @GPGME_CFLAGS@
-
-AM_LDFLAGS = @GPGME_LIBS@
+AM_CPPFLAGS = -I top_srcdir@ @GMIME_CFLAGS@ @GLIB_CFLAGS@
noinst_LIBRARIES = libusenetutils.a
@@ -14,7 +12,8 @@ libusenetutils_a_SOURCES = \
scorefile.cc \
text-massager.cc \
url-find.cc \
- blowfish.cc
+ blowfish.cc \
+ gpg.cc
noinst_HEADERS = \
defgroup.h \
@@ -29,7 +28,8 @@ noinst_HEADERS = \
url-find.h \
ssl-utils.h \
blowfish.h \
- blowfish_cyphers.h
+ blowfish_cyphers.h \
+ gpg.h
#noinst_PROGRAMS = \
# gnksa-test \
diff --git a/pan/usenet-utils/gpg.cc b/pan/usenet-utils/gpg.cc
new file mode 100644
index 0000000..869e2c7
--- /dev/null
+++ b/pan/usenet-utils/gpg.cc
@@ -0,0 +1,134 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Pan - A Newsreader for Gtk+
+ * Copyright (C) 2002-2006 Charles Kerr <charles rebelbase 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; version 2 of the License.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <vector>
+#include <iostream>
+#include <pan/general/log.h>
+#include <pan/general/macros.h>
+#include "gpg.h"
+
+extern "C" {
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <string.h>
+}
+
+namespace pan
+{
+
+ static gboolean
+ request_passwd (GMimeCryptoContext *ctx, const char *user_id, const char *prompt_ctx,
+ gboolean reprompt, GMimeStream *response, GError **err)
+ {
+ return TRUE;
+ }
+
+ GMimeCryptoContext *gpg_ctx;
+ bool gpg_inited;
+
+
+ void deinit_gpg()
+ {
+ gpg_inited=false;
+ g_object_unref (gpg_ctx);
+ }
+
+ void fill_signer_info(GPGSignersInfo& info, GMimeSignatureList * sig_list)
+ {
+ g_return_if_fail(sig_list);
+
+ int l = g_mime_signature_list_length(sig_list);
+ info.signers.reserve(l);
+ GMimeSignature * sig(0);
+ Signer signer;
+ for (int i=0;i<l;++i)
+ {
+ sig = g_mime_signature_list_get_signature (sig_list, i);
+
+ signer.name = sig->cert->name ? sig->cert->name : "(null)";
+ signer.key_id = sig->cert->keyid ? sig->cert->keyid : "(null)";
+ signer.fpr = sig->cert->fingerprint ? sig->cert->fingerprint : "(null)";
+
+ switch (sig->cert->trust) {
+ case GMIME_CERTIFICATE_TRUST_NONE:
+ signer.trust = "None";
+ break;
+ case GMIME_CERTIFICATE_TRUST_NEVER:
+ signer.trust = "Never";
+ case GMIME_CERTIFICATE_TRUST_UNDEFINED:
+ signer.trust = "Undefined";
+ break;
+ case GMIME_CERTIFICATE_TRUST_MARGINAL:
+ signer.trust = "Marginal";
+ break;
+ case GMIME_CERTIFICATE_TRUST_FULLY:
+ signer.trust = "Fully";
+ break;
+ case GMIME_CERTIFICATE_TRUST_ULTIMATE:
+ signer.trust = "Ultimate";
+ break;
+ }
+
+ switch (sig->status) {
+ case GMIME_SIGNATURE_STATUS_GOOD:
+ signer.status = "GOOD";
+ break;
+ case GMIME_SIGNATURE_STATUS_BAD:
+ signer.status = "BAD";
+ break;
+ case GMIME_SIGNATURE_STATUS_ERROR:
+ signer.status = "ERROR";
+ break;
+ }
+
+ signer.created = sig->created;
+ signer.expires = sig->expires;
+ if (sig->expires == (time_t) 0)
+ signer.never_expires = true;
+
+ if (sig->errors) {
+
+ if (sig->errors & GMIME_SIGNATURE_ERROR_EXPSIG)
+ signer.error = "Expired";
+ if (sig->errors & GMIME_SIGNATURE_ERROR_NO_PUBKEY)
+ signer.error = "No Pub Key";
+ if (sig->errors & GMIME_SIGNATURE_ERROR_EXPKEYSIG)
+ signer.error = "Key Expired";
+ if (sig->errors & GMIME_SIGNATURE_ERROR_REVKEYSIG)
+ signer.error = "Key Revoked";
+ } else {
+ signer.error = "No errors for this signer";
+ }
+
+ info.signers.push_back(signer);
+ }
+ }
+
+ void init_gpg()
+ {
+ gpg_ctx = g_mime_gpg_context_new (request_passwd, "gpg");
+ if (!gpg_ctx) gpg_inited = false; else gpg_inited = true;
+ g_mime_gpg_context_set_auto_key_retrieve(GMIME_GPG_CONTEXT(gpg_ctx),true);
+ g_mime_gpg_context_set_always_trust(GMIME_GPG_CONTEXT(gpg_ctx),false);
+ g_mime_gpg_context_set_use_agent(GMIME_GPG_CONTEXT(gpg_ctx), true);
+ }
+
+
+}
diff --git a/pan/usenet-utils/gpg.h b/pan/usenet-utils/gpg.h
new file mode 100644
index 0000000..e959597
--- /dev/null
+++ b/pan/usenet-utils/gpg.h
@@ -0,0 +1,132 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Pan - A Newsreader for Gtk+
+ * Copyright (C) 2002-2006 Charles Kerr <charles rebelbase 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; version 2 of the License.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _HAVE_GPGDEFS_H
+#define _HAVE_GPGDEFS_H
+
+#include <gmime/gmime.h>
+#include <map>
+#include <vector>
+
+namespace pan
+{
+
+ struct Signer
+ {
+ std::string name;
+ std::string key_id;
+ std::string fpr;
+ std::string trust;
+ std::string status;
+ std::string error;
+
+ bool ok;
+ bool never_expires;
+ time_t created, expires;
+
+ Signer() : ok(false), never_expires(false), created((time_t)0), expires((time_t)0) {}
+ };
+
+ struct GPGSignersInfo
+ {
+ std::vector<Signer> signers;
+ };
+
+ typedef std::map<std::string,GPGSignersInfo> signers_m;
+
+ extern GMimeCryptoContext* gpg_ctx;
+ extern bool gpg_inited;
+
+ enum GPGDecType
+ {
+ GPG_VERIFY,
+ GPG_DECODE,
+ GPG_VERIFY_AND_DECODE
+ };
+
+ enum GPGEncType
+ {
+ GPG_ENCODE,
+ GPG_SIGN,
+ GPG_ENCODE_AND_SIGN
+ };
+
+ /* Error struct for gpg_decrypt */
+ struct GPGDecErr
+ {
+ GError* err;
+ std::string output;
+ bool dec_ok;
+ bool verify_ok;
+ bool no_sigs;
+ GPGDecType type;
+ GPGSignersInfo signers;
+ GMimeObject * decrypted;
+ GMimeDecryptResult * result;
+
+ GPGDecErr(GPGDecType t) : err(NULL), type(t), decrypted(0), result(g_mime_decrypt_result_new()) {}
+ ~GPGDecErr()
+ {
+ if (err) g_error_free(err);
+ err = NULL;
+ if (decrypted) g_object_unref(decrypted) ;
+ if (result) g_object_unref(result);
+ }
+ GPGDecErr() : no_sigs(true) {}
+
+ void clear()
+ {
+ if (err) g_error_free(err);
+ err = NULL;
+ signers.signers.clear();
+ verify_ok = false;
+ dec_ok = false;
+ no_sigs = true;
+ }
+
+ };
+
+ /* Error struct for gpg_sign_and_encrypt */
+ struct GPGEncErr
+ {
+ GError* err;
+ std::string output;
+ bool enc_ok;
+ bool sign_ok;
+ bool no_sigs;
+ GPGEncType type;
+ GPGSignersInfo signers;
+
+ GPGEncErr(GPGEncType t) : err(NULL), type(t), no_sigs(true) {}
+ ~GPGEncErr()
+ {
+ if (err) g_error_free(err);
+ err = NULL;
+ }
+
+ };
+
+ void init_gpg();
+ void deinit_gpg();
+ void fill_signer_info(GPGSignersInfo& info, GMimeSignatureList * sig_list);
+
+}
+
+#endif
+
diff --git a/pan/usenet-utils/mime-utils.cc b/pan/usenet-utils/mime-utils.cc
index d888773..ee32bd6 100644
--- a/pan/usenet-utils/mime-utils.cc
+++ b/pan/usenet-utils/mime-utils.cc
@@ -35,10 +35,6 @@ extern "C"
#include <pan/general/log.h>
#include "mime-utils.h"
-#ifdef HAVE_GPGME
- #include <pan/gui/gpg.h>
-#endif
-
#define is_nonempty_string(a) ((a) && (*a))
using namespace pan;
@@ -334,53 +330,6 @@ namespace
}
}
-/***
-**** GPG
-***/
-
-namespace
-{
-
- bool
- gpg_is_beginning_line (const StringView& line)
- {
- if (line.len <= 1) return false;
- StringView l(line);
- return !strncmp (l.str, GPG_MARKER_BEGIN, GPG_MARKER_BEGIN_LEN) ||
- !strncmp (l.str, GPG_MARKER_SIGNED_BEGIN, GPG_MARKER_SIGNED_BEGIN_LEN) ;
- }
-
- bool
- gpg_is_ending_line (const StringView& line)
- {
- if (line.len <= 1) return false;
- StringView l(line);
- return !strncmp (l.str, GPG_MARKER_END, GPG_MARKER_END_LEN) ||
- !strncmp (l.str, GPG_MARKER_SIGNED_END, GPG_MARKER_SIGNED_END_LEN);
- }
-
- bool
- gpg_is_signed_begin_line (const StringView& line)
- {
- if (line.len <= 1) return false;
- StringView l(line);
- return !strncmp (l.str, GPG_MARKER_SIGNED_BEGIN, GPG_MARKER_SIGNED_BEGIN_LEN);
- }
-
- bool
- gpg_is_signed_end_line (const StringView& line)
- {
- if (line.len <= 1) return false;
- StringView l(line);
- return !strncmp (l.str, GPG_MARKER_SIGNED_END, GPG_MARKER_SIGNED_END_LEN);
- }
-
-}
-
-/***
-****
-***/
-
namespace
{
guint
@@ -411,11 +360,9 @@ namespace
enum EncType
{
- ENC_PLAIN = 1 ,
- ENC_YENC = 1 << 1,
- ENC_UU = 1 << 2,
- ENC_GPG = 1 << 3,
- ENC_BASE64 = 1<< 4
+ ENC_PLAIN ,
+ ENC_YENC,
+ ENC_UU
};
namespace pan
@@ -483,7 +430,7 @@ namespace pan
if (!part->stream) {
part->stream = g_mime_stream_mem_new ();
- if (part->type != ENC_PLAIN && part->type != ENC_GPG) {
+ if (part->type != ENC_PLAIN) {
part->filter_stream = g_mime_stream_filter_new (part->stream);
switch (part->type)
{
@@ -501,8 +448,8 @@ namespace pan
}
}
- g_mime_stream_write_to_stream (s, (part->type == ENC_PLAIN || part->type == ENC_GPG) ?
- part->stream : part->filter_stream);
+ g_mime_stream_write_to_stream (s, (part->type == ENC_PLAIN ?
+ part->stream : part->filter_stream));
g_object_unref (s);
}
@@ -511,12 +458,7 @@ namespace pan
temp_parts_t master_list;
temp_parts_t current_list;
TempPart *uu_temp;
- std::string gpg_verified;
-#ifdef HAVE_GPGME
- GPGDecErr gpgerr;
- GPGSignersInfo signer_info;
-#endif
- sep_state():uu_temp(NULL), gpg_verified("") {};
+ sep_state():uu_temp(NULL) {};
};
bool
@@ -528,9 +470,6 @@ namespace pan
EncType type = ENC_PLAIN;
GByteArray * line;
gboolean yenc_looking_for_part_line = FALSE;
- gboolean gpg_looking_for_line = FALSE;
- gboolean gpg_is_signed = FALSE;
- gboolean gpg_signed_end_found = FALSE;
gint64 linestart_pos = 0;
gint64 sub_begin = 0;
gint64 signed_msg_start = 0;
@@ -553,17 +492,6 @@ namespace pan
line_len = pch - line_str;
}
- if (gpg_is_signed_begin_line(line_str))
- {
- gpg_is_signed = true;
- signed_msg_start = linestart_pos;
- }
- if (gpg_is_signed_end_line(line_str))
- {
- gboolean gpg_signed_end_found = true;
- signed_msg_end = linestart_pos+line_len;
- }
-
switch (type)
{
case ENC_PLAIN:
@@ -629,14 +557,6 @@ namespace pan
yenc_looking_for_part_line = cur->y_part!=0;
}
}
- else if (gpg_is_beginning_line (line_str))
- {
-
- found = true;
- cur = new TempPart (type = ENC_GPG);
- gpg_looking_for_line = true;
- sub_begin = linestart_pos;
- }
else if (state.uu_temp != NULL && is_uu_line(line_str, line_len) )
{
// continue an incomplete uu decode
@@ -727,36 +647,6 @@ namespace pan
}
break;
}
-#ifdef HAVE_GPGME
- case ENC_GPG:
- {
- if (gpg_is_ending_line(line_str))
- {
- GMimeStream * stream = g_mime_stream_substream (istream, sub_begin, linestart_pos+line_len);
- GMimeStream * dec = gpg_decrypt_and_verify(state.signer_info, state.gpgerr, stream);
- if (state.gpgerr.verify_ok)
- state.gpg_verified = "valid";
- else if (!state.gpgerr.verify_ok && !state.gpgerr.no_sigs)
- state.gpg_verified = "invalid";
-
- gpg_looking_for_line = false;
- if (state.gpgerr.dec_ok)
- {
- apply_source_and_maybe_filter (cur, dec);
- if( append_if_not_present (master, cur) )
- append_if_not_present (appendme, cur);
- }
- cur = NULL;
- type = ENC_PLAIN;
- sub_begin = -1;
- }
- else if (gpg_looking_for_line)
- {
- ++cur->valid_lines;
- }
- break;
- }
-#endif
}
}
@@ -990,12 +880,27 @@ namespace
}
}
-namespace{
+namespace pan
+{
struct temp_p {
GMimeObject *parent,*part;
temp_p(GMimeObject *p, GMimeObject *par):parent(p),part(par) {};
};
+
+ struct QueryMPType
+ {
+ GMimeObject* obj;
+ GPGDecType type;
+ std::string algo;
+
+ QueryMPType() : obj(0), type(GPG_DECODE) {}
+ };
+}
+
+namespace
+{
+
typedef std::vector<temp_p> temp_p_t;
void find_text_cb(GMimeObject *parent, GMimeObject *part, gpointer data)
@@ -1011,18 +916,53 @@ namespace{
v->push_back(temp_p(parent,part) );
}
- void find_gpg_parts_cb(GMimeObject *parent, GMimeObject *part, gpointer data)
+
+ void mixed_mp_cb(GMimeObject *parent, GMimeObject *part, gpointer data)
{
if(!GMIME_IS_PART(part))
return;
- temp_p_t *v( (temp_p_t *) data);
+ QueryMPType * type = static_cast<QueryMPType*>(data);
GMimeContentType * content_type = g_mime_object_get_content_type (part);
- if (!(g_mime_content_type_is_type (content_type, "multipart", "encrypted") ||
- g_mime_content_type_is_type (content_type, "text", "plain")))
+// if (!g_mime_content_type_is_type (content_type, "text", "plain") &&
+// !g_mime_content_type_is_type (content_type, "application", "pgp-signature"))
+// return;
+
+// if (g_mime_content_type_is_type (content_type, "application", "pgp-signature"))
+// {
+// g_mime_object_set_content_type_parameter(part, "micalg", "pgp-sha1");//type->algo.c_str());
+// std::cerr<<g_mime_object_to_string(part)<<"\n";
+// }
+
+ g_mime_multipart_add (GMIME_MULTIPART(type->obj), part);
+ }
+
+
+ void mixed_mp_find_gpg_params_cb (GMimeObject *parent, GMimeObject *part, gpointer data)
+ {
+
+ if(!GMIME_IS_PART(part))
return;
- v->push_back(temp_p(parent,part) );
+
+ QueryMPType * type = static_cast<QueryMPType*>(data);
+
+// const char* micalg = g_mime_object_get_content_type_parameter (GMIME_OBJECT (part), "micalg");
+// if (micalg)
+// {
+// std::cerr<<"micalg found : "<<micalg<<"\n";
+// type->algo = micalg;
+// }
+
+ GMimeContentType * content_type = g_mime_object_get_content_type (part);
+
+ if (!content_type) return;
+
+ if (g_mime_content_type_is_type (content_type, "application", "pgp-signature"))
+ type->type = GPG_VERIFY;
+ else if (g_mime_content_type_is_type (content_type, "application", "pgp-encrypted"))
+ type->type = GPG_DECODE;
+
}
}
@@ -1031,17 +971,10 @@ namespace{
****
***/
-#ifdef HAVE_GPGME
GMimeMessage*
mime :: construct_message (GMimeStream ** istreams,
- int qty,
- GPGSignersInfo & signer_info,
- GPGDecErr & gpgerr)
-#else
-GMimeMessage*
-mime :: construct_message (GMimeStream ** istreams,
- int qty)
-#endif
+ int qty,
+ GPGDecErr & err)
{
const char * message_id = "Foo <bar mum>";
GMimeMessage * retval = 0;
@@ -1049,16 +982,75 @@ mime :: construct_message (GMimeStream ** istreams,
// sanity clause
pan_return_val_if_fail (is_nonempty_string(message_id), NULL);
pan_return_val_if_fail (istreams!=NULL, NULL);
- pan_return_val_if_fail (qty>=1, NULL);
+ pan_return_val_if_fail (qty != 0, NULL);
for (int i=0; i<qty; ++i)
pan_return_val_if_fail (GMIME_IS_STREAM(istreams[i]), NULL);
// build the GMimeMessages
- GMimeParser * parser = g_mime_parser_new ();
+ GMimeParser * parser;// = g_mime_parser_new ();
GMimeMessage ** messages = g_new (GMimeMessage*, qty);
+
for (int i=0; i<qty; ++i) {
- g_mime_parser_init_with_stream (parser, istreams[i]);
- messages[i] = g_mime_parser_construct_message (parser);
+ parser = g_mime_parser_new_with_stream (istreams[i]);
+ messages[i] = g_mime_parser_construct_message(parser);
+ g_object_unref(parser);
+ g_mime_stream_reset(istreams[i]);
+ parser = g_mime_parser_new_with_stream (istreams[i]);
+ GMimeObject* part = g_mime_parser_construct_part(parser);
+ GMimeContentType * type = g_mime_object_get_content_type (part);
+ const bool multipart (GMIME_IS_MULTIPART_SIGNED(part) || GMIME_IS_MULTIPART_ENCRYPTED(part));
+
+ if (GMIME_IS_MULTIPART_SIGNED(part))
+ {
+ err.type = GPG_VERIFY;
+ err.verify_ok = gpg_verify_mps(part, err);
+ }
+ else if (GMIME_IS_MULTIPART_ENCRYPTED(part))
+ {
+ err.type = GPG_DECODE;
+ err.verify_ok = gpg_verify_mps(part, err);
+ }
+
+ if (type)
+ {
+ if (g_mime_content_type_is_type (type, "multipart", "mixed"))
+ {
+ QueryMPType qtype;
+ g_mime_multipart_foreach (GMIME_MULTIPART(part), mixed_mp_find_gpg_params_cb, &qtype);
+ GMimeObject* o(0);
+
+ if (qtype.type == GPG_VERIFY)
+ {
+ GMimeMultipartSigned* new_mp = g_mime_multipart_signed_new();
+ err.type = GPG_VERIFY;
+ qtype.obj = o = GMIME_OBJECT(new_mp);
+ g_mime_multipart_foreach (GMIME_MULTIPART(part), mixed_mp_cb, &qtype);
+ err.verify_ok = gpg_verify_mps(GMIME_OBJECT(new_mp), err);
+ g_mime_message_set_mime_part(messages[i], GMIME_OBJECT(new_mp));
+ std::cerr<<"algo : "<<g_mime_object_to_string(GMIME_OBJECT(new_mp))<<"\n";
+ }
+
+ if (qtype.type == GPG_DECODE)
+ {
+ GMimeMultipartEncrypted* new_mp = g_mime_multipart_encrypted_new();
+ err.type = GPG_DECODE;
+ qtype.obj = o = GMIME_OBJECT(new_mp);
+ g_mime_multipart_foreach (GMIME_MULTIPART(part), mixed_mp_cb, &qtype);
+ err.verify_ok = gpg_verify_mps(GMIME_OBJECT(new_mp), err);
+ g_mime_message_set_mime_part(messages[i], GMIME_OBJECT(new_mp));
+ }
+
+ g_object_unref(o);
+
+ }
+ else if (multipart)
+ {
+ if (err.decrypted)
+ g_mime_message_set_mime_part(messages[i], err.decrypted);
+ } else
+ g_mime_message_set_mime_part(messages[i], part);
+ }
+
}
g_object_unref (parser);
@@ -1084,16 +1076,11 @@ mime :: construct_message (GMimeStream ** istreams,
sep_state state;
if (retval != NULL)
g_mime_message_foreach(retval, find_text_cb, &partslist);
+
foreach(temp_p_t, partslist, it)
{
temp_p &data(*it);
handle_uu_and_yenc_in_text_plain_cb(data.parent, data.part, &state);
- /* set gpg signature verify success/fail flag */
-#ifdef HAVE_GPGME
- g_mime_object_set_header(GMIME_OBJECT(data.parent), "X-GPG-Signed", state.gpg_verified.c_str());
- gpgerr = state.gpgerr;
- signer_info = state.signer_info;
-#endif
}
// cleanup
@@ -1288,6 +1275,7 @@ namespace
GMimeObject *
handle_multipart_mixed (GMimeMultipart *multipart, gboolean *is_html)
{
+
GMimeObject *mime_part, *text_part = NULL;
GMimeContentType *type, *first_type = NULL;
int count = g_mime_multipart_get_count (multipart);
@@ -1421,121 +1409,7 @@ void pan::pan_g_mime_message_set_message_id (GMimeMessage *msg, const char *mid)
}
namespace pan
-
{
- #ifdef HAVE_GPGME
- GMimeStream* gpg_decrypt_and_verify (GPGSignersInfo& signer_info, GPGDecErr& info,
- GMimeStream* s, int index, GMimeObject* parent)
- {
-
- GMimeStream* decrypted = g_mime_stream_mem_new ();
-
- ssize_t stream_len = g_mime_stream_length(s);
-
- char* streambuf = new char[stream_len];
-
- g_mime_stream_read(s, streambuf, stream_len);
- g_object_unref(s);
-
- info.err = GPG_ERR_NO_ERROR;
-
- gpgme_data_t gpg_buf, gpg_out_buf;
- gpgme_key_t key;
-
- StringView v(streambuf);
- gpgme_data_new_from_mem (&gpg_buf, v.str, v.len, 0);
-
- gpgme_strerror(gpgme_data_new (&gpg_out_buf));
-
- gpgme_data_set_encoding (gpg_out_buf, GPGME_DATA_ENCODING_NONE);
-
- info.err = gpgme_op_decrypt_verify (gpg_ctx, gpg_buf, gpg_out_buf);
-
- // no data to decrypt, check for signature validity anyway....
- if (gpgme_err_code(info.err) == GPG_ERR_NO_DATA || gpgme_err_code(info.err) == GPG_ERR_NO_ERROR)
- info.dec_ok = true;
- else
- return decrypted;
-
- info.dec_res = gpgme_op_decrypt_result (gpg_ctx);
- info.v_res = gpgme_op_verify_result (gpg_ctx);
-
- // verify attached sigs, too. that means, no data to decrypt and no signatures found, yet
- if (gpgme_err_code(info.err) == GPG_ERR_NO_DATA &&
- gpgme_err_code(info.v_res->signatures->status) == GPG_ERR_BAD_SIGNATURE && parent)
- {
- int count(0); int no(0);
- size_t len;
- char* body(0);
- count = g_mime_multipart_get_count (GMIME_MULTIPART(parent));
- no = index;
- gpgme_data_t body_data;
-
- for (int i=0;i<count;++i)
- {
-
- if (i == no) continue;
- GMimeObject* part_of = g_mime_multipart_get_part (GMIME_MULTIPART(parent), i);
- if (part_of)
- {
- body = pan_g_mime_part_get_content(GMIME_PART(part_of),&len);
- if (body)
- {
- gpgme_data_new_from_mem (&body_data, body, len, 0);
- info.err = gpgme_op_verify (gpg_ctx, gpg_buf, body_data, 0);
- info.v_res= gpgme_op_verify_result (gpg_ctx);
- gpgme_data_release(body_data);
- g_free(body);
- if (info.err == GPG_ERR_NO_ERROR &&
- gpgme_err_code(info.v_res->signatures->status) == GPG_ERR_NO_ERROR) break;
- }
- }
- }
- }
-
- if (info.v_res->signatures)
- {
- info.no_sigs = false;
- if (gpgme_err_code(info.v_res->signatures->status) == GPG_ERR_NO_ERROR)
- info.verify_ok = true;
- }
- else
- info.no_sigs = true;
-
- delete streambuf;
-
- gpgme_data_seek (gpg_out_buf,SEEK_SET, 0);
-
- ssize_t ret(0);
- char buffer[4096]={0};
- gint64 len(0);
-
- while ((ret = gpgme_data_read (gpg_out_buf, buffer, sizeof(buffer))) > 0)
- {
- len += g_mime_stream_write(decrypted, buffer, ret);
- }
-
- g_mime_stream_flush (decrypted);
- g_mime_stream_reset(decrypted);
-
- gpgme_data_release(gpg_buf);
- gpgme_data_release(gpg_out_buf);
-
- GPGSignersInfo si;
-
- if (!info.no_sigs)
- {
- if (info.v_res->signatures->fpr)
- gpgme_get_key (gpg_ctx, info.v_res->signatures->fpr, &key, 0);
- if (key)
- fill_signer_info(si, key);
- }
-
- signer_info = si;
- info.err = GPG_ERR_NO_ERROR;
-
- return decrypted;
- }
void
mime_part_set_content (GMimePart *part, const char *str)
@@ -1551,167 +1425,126 @@ namespace pan
g_object_unref (content);
}
- GMimeMessage*
- message_add_signed_part (const std::string& uid, const std::string& body_str, GMimeMessage* body, GPGEncErr& fail)
+ GMimeSignatureStatus
+ get_sig_status (GMimeSignatureList *signatures)
{
- if (uid.empty()) return 0;
-
- GMimeMultipart *mp = g_mime_multipart_new_with_subtype ("mixed");
- g_mime_multipart_set_boundary(mp, NULL);
- g_mime_multipart_add(mp,g_mime_message_get_mime_part(body));
+ GMimeSignatureStatus status = GMIME_SIGNATURE_STATUS_GOOD;
+ GMimeSignature *sig;
+ int i;
- gpgme_data_t gpg_buf, gpg_out_buf;
- gpgme_key_t mykey(0), key;
+ if (!signatures || signatures->array->len == 0)
+ return GMIME_SIGNATURE_STATUS_ERROR;
- StringView v(body_str);
- gpgme_data_new_from_mem (&gpg_buf, v.str, v.len, 0);
- gpgme_data_new (&gpg_out_buf);
- // gpgme_data_set_encoding (gpg_out_buf, GPGME_DATA_ENCODING_BASE64);
- // gpgme_data_set_file_name(gpg_out_buf, "signature.asc");
-
- fail.err = gpgme_op_keylist_start (gpg_ctx, 0, 0);
- while (!fail.err)
- {
- fail.err = gpgme_op_keylist_next (gpg_ctx, &key);
- if (fail.err) break;
- if (strcmp(key->subkeys->keyid, uid.c_str()) == 0) { mykey = key; break; }
- }
- if (!mykey) { fail.err = GPG_ERR_NO_PUBKEY; return 0; }
-
- gpgme_signers_clear(gpg_ctx);
- gpgme_signers_add(gpg_ctx, mykey);
-
- fail.err = gpgme_op_sign (gpg_ctx, gpg_buf, gpg_out_buf, GPGME_SIG_MODE_DETACH);
- fail.sign_res = gpgme_op_sign_result (gpg_ctx);
- if (fail.err) return 0;
-
- gpgme_data_seek (gpg_out_buf,SEEK_SET, 0);
- ssize_t ret;
- std::stringstream ret_str;
- char buffer[4096]={0};
-
- while ((ret = gpgme_data_read (gpg_out_buf, buffer, sizeof(buffer))) > 0)
- {
- ret_str << buffer;
+ for (i = 0; i < g_mime_signature_list_length (signatures); i++) {
+ sig = g_mime_signature_list_get_signature (signatures, i);
+ status = MAX (status, sig->status);
}
- GMimePart *sig = g_mime_part_new_with_type("multipart", "signed");
- g_mime_object_set_content_type_parameter(GMIME_OBJECT(sig),"protocol","pgp-signature");
- mime_part_set_content (sig, ret_str.str().c_str());
-
- gpgme_data_release(gpg_buf);
- gpgme_data_release(gpg_out_buf);
-
- g_mime_multipart_add (GMIME_MULTIPART (mp), GMIME_OBJECT (sig));
-
- g_mime_message_set_mime_part(body,GMIME_OBJECT(mp));
- g_object_unref(mp);
-
- fail.err = GPG_ERR_NO_ERROR;
-
- return body;
+ return status;
}
- std::string
- gpg_encrypt(const std::string& uid, const std::string& body, GPGEncErr& fail)
+ bool
+ gpg_verify_mps (GMimeObject* obj, GPGDecErr& info)
{
- fail.err = GPG_ERR_GENERAL;
-
- if (uid.empty()) return "";
- gpgme_data_t gpg_buf, gpg_out_buf;
- gpgme_key_t mykey(0), key;
+ if (!gpg_inited) return false;
- StringView v(body);
- gpgme_data_new_from_mem (&gpg_buf, v.str, v.len, 0);
- gpgme_data_new (&gpg_out_buf);
- gpgme_data_set_encoding (gpg_out_buf, GPGME_DATA_ENCODING_BASE64);
+ GMimeMultipartSigned * mps(0);
+ GMimeMultipartEncrypted * mpe(0);
- /* find key to uid */
- fail.err = gpgme_op_keylist_start (gpg_ctx, 0, 0);
- while (!fail.err)
+ switch (info.type)
{
- fail.err = gpgme_op_keylist_next (gpg_ctx, &key);
- if (fail.err) break;
- if (strcmp(key->subkeys->keyid, uid.c_str()) == 0) { mykey = key; break; }
+ case GPG_VERIFY:
+ mps = (GMimeMultipartSigned *)obj;
+ break;
+
+ case GPG_DECODE:
+ mpe = (GMimeMultipartEncrypted *)obj;
+ break;
}
- if (!mykey) { fail.err = GPG_ERR_NO_PUBKEY; return std::string(""); }
- gpgme_key_t enc_keys[] = { mykey, NULL};
+ info.clear();
- fail.err = gpgme_op_encrypt (gpg_ctx, enc_keys, GPGME_ENCRYPT_PREPARE, gpg_buf, gpg_out_buf);
- fail.enc_res = gpgme_op_encrypt_result (gpg_ctx);
- if (fail.err) return std::string("");
+ if (info.type == GPG_VERIFY)
+ {
+ GMimeSignatureList * sig_list = g_mime_multipart_signed_verify (mps, gpg_ctx, &info.err);
+ if (sig_list) info.no_sigs = false;
+ if (!sig_list) return false;
+ fill_signer_info(info.signers, sig_list);
- gpgme_data_seek (gpg_out_buf,SEEK_SET, 0);
- ssize_t ret;
- std::stringstream ret_str;
- char buffer[4096]={0};
+ return get_sig_status(sig_list) == GMIME_SIGNATURE_STATUS_GOOD;
+ }
- while ((ret = gpgme_data_read (gpg_out_buf, buffer, sizeof(buffer))) > 0)
+ if (info.type == GPG_DECODE)
{
- ret_str << buffer;
- }
+ info.decrypted = g_mime_multipart_encrypted_decrypt (mpe, gpg_ctx, &info.result, &info.err);
+ if (!info.decrypted)
+ if (info.err) return false;
- gpgme_data_release(gpg_buf);
- gpgme_data_release(gpg_out_buf);
+ GMimeSignatureList * sigs = g_mime_decrypt_result_get_signatures (info.result);
+ if (sigs)
+ {
+ info.no_sigs = false;
+ fill_signer_info(info.signers, sigs);
+ }
+ return get_sig_status(info.result->signatures) == GMIME_SIGNATURE_STATUS_GOOD || !info.err;
+ }
+ return false;
- fail.err = GPG_ERR_NO_ERROR;
- return ret_str.str();
}
- std::string
- gpg_encrypt_and_sign(const std::string& uid, const std::string& body, GPGEncErr& fail)
+ GMimeMessage*
+ message_add_signed_part (const std::string& uid, const std::string& body_str, GMimeMessage* body)
{
- fail.err = GPG_ERR_GENERAL;
-
- if (uid.empty()) return "";
+ if (uid.empty()) return 0;
- gpgme_data_t gpg_buf, gpg_out_buf;
- gpgme_key_t mykey(0), key;
+ GMimeMultipartSigned *mps;
+ GError* err(NULL);
+ GMimePart* part = g_mime_part_new_with_type("text", "plain");
+ mime_part_set_content (part, body_str.c_str());
- StringView v(body);
- gpgme_data_new_from_mem (&gpg_buf, v.str, v.len, 0);
- gpgme_data_new (&gpg_out_buf);
- gpgme_data_set_encoding (gpg_out_buf, GPGME_DATA_ENCODING_BASE64);
+ mps = g_mime_multipart_signed_new ();
- /* find key to uid */
- fail.err = gpgme_op_keylist_start (gpg_ctx, 0, 0);
- while (!fail.err)
+ /* sign the part */
+ if (g_mime_multipart_signed_sign (mps, GMIME_OBJECT (part), gpg_ctx, uid.c_str(), GMIME_DIGEST_ALGO_SHA1, &err) <0)
{
- fail.err = gpgme_op_keylist_next (gpg_ctx, &key);
- if (fail.err) break;
- if (strcmp(key->subkeys->keyid, uid.c_str()) == 0) { mykey = key; break; }
+ g_object_unref(mps);
+ g_object_unref(G_OBJECT(part));
+ return 0;
}
- if (!mykey) { fail.err = GPG_ERR_NO_PUBKEY; return std::string(""); }
- gpgme_signers_clear(gpg_ctx);
- gpgme_signers_add(gpg_ctx, mykey);
+ g_mime_message_set_mime_part(body,GMIME_OBJECT(mps));
+ g_object_unref(G_OBJECT(part));
+ g_object_unref(mps);
+
+ return body;
+ }
- gpgme_key_t enc_keys[] = { mykey, NULL};
+ GMimeMessage*
+ gpg_encrypt (const std::string& uid, const std::string& body_str,
+ GMimeMessage* body, GPtrArray* rcp, bool sign)
+ {
- fail.err = gpgme_op_encrypt_sign (gpg_ctx, enc_keys, GPGME_ENCRYPT_PREPARE, gpg_buf, gpg_out_buf);
- fail.enc_res = gpgme_op_encrypt_result (gpg_ctx);
- fail.sign_res= gpgme_op_sign_result (gpg_ctx);
- if (fail.err) return std::string("");
+ GError* err(0);
+ GMimePart* part = g_mime_part_new_with_type("text", "plain");
+ mime_part_set_content (part, body_str.c_str());
- gpgme_data_seek (gpg_out_buf,SEEK_SET, 0);
- ssize_t ret;
- std::stringstream ret_str;
- char buffer[4096]={0};
+ GMimeMultipartEncrypted * mpe = g_mime_multipart_encrypted_new();
- while ((ret = gpgme_data_read (gpg_out_buf, buffer, sizeof(buffer))) > 0)
+ if (g_mime_multipart_encrypted_encrypt(mpe, GMIME_OBJECT (part), gpg_ctx, sign,
+ uid.c_str(), GMIME_DIGEST_ALGO_SHA1, rcp, &err) < 0)
{
- ret_str << buffer;
+ g_object_unref(mpe);
+ g_object_unref(G_OBJECT(part));
+ return 0;
}
- gpgme_data_release(gpg_buf);
- gpgme_data_release(gpg_out_buf);
+ g_mime_message_set_mime_part(body,GMIME_OBJECT(mpe));
+ g_object_unref(G_OBJECT(part));
+ g_object_unref(mpe);
- fail.err = GPG_ERR_NO_ERROR;
- return ret_str.str();
}
-#endif
+
}
diff --git a/pan/usenet-utils/mime-utils.h b/pan/usenet-utils/mime-utils.h
index b43650d..15e2188 100644
--- a/pan/usenet-utils/mime-utils.h
+++ b/pan/usenet-utils/mime-utils.h
@@ -26,11 +26,7 @@
#include <gmime/gmime-stream.h>
#include <gmime/gmime-message.h>
#include <pan/general/string-view.h>
-
-#ifdef HAVE_GPGME
- #include <gpgme.h>
- #include <pan/gui/gpg.h>
-#endif
+#include <pan/usenet-utils/gpg.h>
/***
**** YENC
@@ -60,27 +56,12 @@
#define YENC_SHIFT 42
#define YENC_QUOTE_SHIFT 64
-/***
-**** GPG
-***/
-
-#define GPG_MARKER_BEGIN "-----BEGIN PGP MESSAGE-----"
-#define GPG_MARKER_BEGIN_LEN 27
-#define GPG_MARKER_END "-----END PGP MESSAGE-----"
-#define GPG_MARKER_END_LEN 25
-#define GPG_MARKER_SIGNED_BEGIN "-----BEGIN PGP SIGNED MESSAGE-----"
-#define GPG_MARKER_SIGNED_BEGIN_LEN 34
-#define GPG_MARKER_SIGNED_END "-----END PGP SIGNATURE-----"
-#define GPG_MARKER_SIGNED_END_LEN 27
-
namespace pan
{
-#ifdef HAVE_GPGME
- GMimeStream* gpg_decrypt_and_verify (GPGSignersInfo& signer_info, GPGDecErr& info, GMimeStream* s, int index=0, GMimeObject* parent=0);
- GMimeMessage* message_add_signed_part (const std::string& uid, const std::string& body_str, GMimeMessage* body, GPGEncErr& fail);
- std::string gpg_encrypt(const std::string& uid, const std::string& body, GPGEncErr& fail);
- std::string gpg_encrypt_and_sign(const std::string& uid, const std::string& body, GPGEncErr& fail);
-#endif
+
+ GMimeMessage* message_add_signed_part (const std::string& uid, const std::string& body_str, GMimeMessage* body);
+ GMimeMessage* gpg_encrypt (const std::string& uid, const std::string& body_str, GMimeMessage* body, GPtrArray* rcp, bool sign);
+ bool gpg_verify_mps (GMimeObject*, GPGDecErr&);
/**
* Utilities to build and parse GMimeMessages.
@@ -93,17 +74,10 @@ namespace pan
*/
struct mime
{
-#ifdef HAVE_GPGME
static GMimeMessage *
construct_message (GMimeStream ** istreams,
- int qty,
- GPGSignersInfo & signer_info,
- GPGDecErr & gpgerr);
-#else
- static GMimeMessage *
- construct_message (GMimeStream ** istreams,
- int qty);
-#endif
+ int qty,
+ GPGDecErr &);
static const char *
get_charset (GMimeMessage * message);
diff --git a/uulib/uuscan.c b/uulib/uuscan.c
index 55b0b09..f66868f 100644
--- a/uulib/uuscan.c
+++ b/uulib/uuscan.c
@@ -490,7 +490,7 @@ ParseHeader (headers *theheaders, char *line)
* Some encoders mention the original filename as parameter to
* Content-Type, others as parameter to Content-Disposition. We
* do prefer the first solution, but accept this situation, too.
- * TODO: Read RFC1806
+ * !!Read RFC1806
*/
if ((ptr = _FP_stristr (line, "name")) != NULL) {
if (theheaders->fname == NULL && (thenew=ParseValue(ptr)) != NULL) {
@@ -563,12 +563,12 @@ IsKnownHeader (char *line)
*pch++ = tolower (*line++);
*pch = '\0';
pch = buf;
-
- // search for that in knownmsgheaders
+
+ // search for that in knownmsgheaders
if (bsearch (&pch, knownmsgheaders, n_msg, sizeof(char*), bsearch_strcmp) != NULL)
retval = 1;
- // search for that in knownmimeheaders
+ // search for that in knownmimeheaders
else if (bsearch (&pch, knownmimeheaders, n_mime, sizeof(char*), bsearch_strcmp) != NULL)
retval = 2;
}
@@ -717,7 +717,7 @@ ScanData (FILE *datei, char *fname, int *errcode,
dontcare=0;
}
- if (boundary != NULL &&
+ if (boundary != NULL &&
line[0] == '-' && line[1] == '-' &&
strncmp (line+2, boundary, blen) == 0) {
fseek (datei, oldposition, SEEK_SET);
@@ -746,14 +746,14 @@ ScanData (FILE *datei, char *fname, int *errcode,
fseek (datei, oldposition, SEEK_SET);
break;
}
-
+
if (*line == '<')
ptr = line + 10;
else
ptr = line + 5;
while (*ptr == ' ') ptr++;
- while (isdigit (*ptr))
+ while (isdigit (*ptr))
result->mode = result->mode * 8 + *ptr++ - '0';
while (*ptr == ' ') ptr++;
@@ -801,7 +801,7 @@ ScanData (FILE *datei, char *fname, int *errcode,
ptr += 8;
while (isspace (*ptr)) ptr++;
p2 = ptr;
- while (isalnum(*p2) ||
+ while (isalnum(*p2) ||
*p2 == '.' || *p2=='_' || *p2 == '-' ||
*p2 == '!' || *p2=='@' || *p2 == '$')
p2++;
@@ -874,7 +874,7 @@ ScanData (FILE *datei, char *fname, int *errcode,
}
else {
p2 = ptr;
- while (isalnum(*p2) ||
+ while (isalnum(*p2) ||
*p2 == '.' || *p2=='_' || *p2 == '-' ||
*p2 == '!' || *p2=='@' || *p2 == '$')
p2++;
@@ -908,8 +908,8 @@ ScanData (FILE *datei, char *fname, int *errcode,
*p2 = c;
}
}
-
- /*
+
+ /*
* Handling for very short Base64 files.
*/
if (uu_tinyb64 && !ismime && !uu_more_mime) {
@@ -965,7 +965,7 @@ ScanData (FILE *datei, char *fname, int *errcode,
/*
* name continues to the end of the line
*/
-
+
_FP_free (result->filename);
ptr = _FP_strstr (line, " name=") + 6;
result->filename = _FP_strdup (ptr);
@@ -1007,7 +1007,7 @@ ScanData (FILE *datei, char *fname, int *errcode,
if ((ptr = _FP_strstr (line, " end=")) == NULL) {
break;
}
-
+
yepartends = atoi (ptr + 5);
}
else {
@@ -1113,7 +1113,7 @@ ScanData (FILE *datei, char *fname, int *errcode,
if (vflag == BH_ENCODED && bhnf == 0 && result->filename == NULL) {
if (bhdsp == bhds2 ||
((bhdsp-bhds2) <= (int) bhds2[0] &&
- (bhdsp-bhds2) < 256)) {
+ (bhdsp-bhds2) < 256)) {
dcc = UUDecodeLine (line, bhds1, BH_ENCODED);
UUbhdecomp (bhds1, bhdsp, &bhl, &bhrpc,
dcc, 256-(bhdsp-bhds2), &bhopc);
@@ -1307,7 +1307,7 @@ ScanData (FILE *datei, char *fname, int *errcode,
continue;
}
-
+
/*
* Select the encoding with the best "history"
*/
@@ -1750,7 +1750,7 @@ ScanPart (FILE *datei, char *fname, int *errcode)
blen = strlen (sstate.envelope.boundary);
lcount = 0;
-
+
while (!feof (datei)) {
if (_FP_fgets (line, line_len, datei) == NULL)
break;
@@ -1928,7 +1928,7 @@ ScanPart (FILE *datei, char *fname, int *errcode)
preheaders = prevpos;
lcount = 0;
}
- hcount++;
+ hcount++;
lcount++;
if (hcount >= hlcount.restart) {
@@ -2083,7 +2083,7 @@ ScanPart (FILE *datei, char *fname, int *errcode)
* stack and dive into the new environment, starting with another
* preamble.
*/
-
+
if (sstate.ismime && sstate.mimestate == MS_SUBPART) {
memset (&localenv, 0, sizeof (headers));
result->startpos = ftell (datei);
@@ -2114,18 +2114,18 @@ ScanPart (FILE *datei, char *fname, int *errcode)
}
sstate.isfolder = 0;
sstate.ismime = 0;
-
+
UUkillheaders (&localenv);
*errcode = UURET_NOMEM;
_FP_free (result);
return NULL;
}
-
+
/* Scan subheader. But what if there is no subheader? */
hcount = 0;
lcount = 0;
preheaders = prevpos;
-
+
if (_FP_fgets (line, line_len, datei) == NULL) {
sstate.isfolder = 0;
sstate.ismime = 0;
@@ -2247,7 +2247,7 @@ ScanPart (FILE *datei, char *fname, int *errcode)
prevpos = ftell (datei);
blen = strlen (sstate.envelope.boundary);
lcount = 0;
-
+
while (!feof (datei)) {
if (_FP_fgets (line, line_len, datei) == NULL) {
line[0] = '\0';
@@ -2449,7 +2449,7 @@ ScanPart (FILE *datei, char *fname, int *errcode)
else {
UUMessage (uuscan_id, __LINE__, UUMSG_WARNING,
uustring (S_MIME_B_NOT_FOUND));
-
+
while (mssdepth) {
mssdepth--;
UUkillheaders (&(multistack[mssdepth].envelope));
@@ -2469,7 +2469,7 @@ ScanPart (FILE *datei, char *fname, int *errcode)
* Retry, listening to headers this time
*/
fseek (datei, result->startpos, SEEK_SET);
-
+
UUkillfread (result);
if ((result = (fileread *) malloc (sizeof (fileread))) == NULL) {
*errcode = UURET_NOMEM;
@@ -2575,7 +2575,7 @@ ScanPart (FILE *datei, char *fname, int *errcode)
* kill local envelope
*/
UUkillheaders (&localenv);
-
+
return result;
}
@@ -2718,7 +2718,7 @@ ScanPart (FILE *datei, char *fname, int *errcode)
}
}
- while (!feof (datei) && !IsLineEmpty (line)) {
+ while (!feof (datei) && !IsLineEmpty (line)) {
if (IsKnownHeader (line))
hcount++;
lcount++;
@@ -2819,7 +2819,7 @@ ScanPart (FILE *datei, char *fname, int *errcode)
}
result->partno = sstate.envelope.partno;
result->maxpno = sstate.envelope.numparts;
- result->flags = FL_PARTIAL |
+ result->flags = FL_PARTIAL |
((res==1 || uu_fast_scanning) ? FL_PROPER : 0) |
((uu_fast_scanning) ? FL_TOEND : 0);
result->mimeid = _FP_strdup (sstate.envelope.mimeid);
@@ -2848,7 +2848,7 @@ ScanPart (FILE *datei, char *fname, int *errcode)
sstate.isfolder = 1;
sstate.ismime = 0;
sstate.mimestate = MS_HEADERS;
-
+
UUkillheaders (&sstate.envelope);
memset (&sstate.envelope, 0, sizeof (headers));
}
@@ -2921,7 +2921,7 @@ ScanPart (FILE *datei, char *fname, int *errcode)
}
result->startpos = prevpos = ftell (datei);
-
+
/*
* If this is Quoted-Printable or Plain Text, just try looking
* for the next message header. If uu_fast_scanning, we know
@@ -2951,7 +2951,7 @@ ScanPart (FILE *datei, char *fname, int *errcode)
}
}
- while (!feof (datei) && !IsLineEmpty (line)) {
+ while (!feof (datei) && !IsLineEmpty (line)) {
if (IsKnownHeader (line))
hcount++;
lcount++;
@@ -3131,13 +3131,13 @@ ScanPart (FILE *datei, char *fname, int *errcode)
sstate.envelope.mimevers = _FP_strdup ("1.0");
sstate.envelope.boundary = _FP_strdup (line+2);
-
+
/*
* need restart
*/
-
+
fseek (datei, prevpos, SEEK_SET);
-
+
_FP_free (result);
return NULL;
}
@@ -3158,8 +3158,8 @@ ScanPart (FILE *datei, char *fname, int *errcode)
if (sstate.envelope.ctype)
result->mimetype = _FP_strdup (sstate.envelope.ctype);
-
- if ((res=ScanData (datei, fname, errcode, NULL,
+
+ if ((res=ScanData (datei, fname, errcode, NULL,
sstate.ismime, 1, result))==-1) {
/* oops, something went wrong */
sstate.isfolder = 0;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]