[pan2: 228/268] * cleanups and fixes + pgp encrypt and sign messages inline (text/plain) (todo : decode signed) + re
- From: Heinrich MÃller <henmull src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pan2: 228/268] * cleanups and fixes + pgp encrypt and sign messages inline (text/plain) (todo : decode signed) + re
- Date: Mon, 2 Jan 2012 15:57:10 +0000 (UTC)
commit 056337d5a21a4f9fd2df8c64cddcad87d0f087c9
Author: Heinrich MÃller <henmull src gnome org>
Date: Tue Dec 6 19:58:24 2011 +0100
* cleanups and fixes
+ pgp encrypt and sign messages inline (text/plain) (todo : decode signed)
+ revert "download all flagged", is unneeded
configure.in | 10 +-
gtkspell/gtkspell/gtkspell.c | 44 ++--
pan/data-impl/data-impl.cc | 47 +---
pan/data-impl/data-impl.h | 4 +-
pan/data-impl/profiles.cc | 26 ++-
pan/data-impl/server.cc | 57 +++--
pan/data/data.h | 11 +-
pan/gui/Makefile.am | 10 +-
pan/gui/actions.cc | 6 -
pan/gui/body-pane.cc | 10 +-
pan/gui/gui.cc | 36 +--
pan/gui/gui.h | 1 -
pan/gui/pan-file-entry.cc | 2 +-
pan/gui/pan-ui.h | 1 -
pan/gui/pan.cc | 10 +-
pan/gui/pan.ui.h | 4 -
pan/gui/post-ui.cc | 294 +++++++++++------------
pan/gui/post-ui.h | 7 +-
pan/gui/post.ui.h | 2 +
pan/gui/prefs-ui.cc | 4 +-
pan/gui/profiles-dialog.cc | 138 +++++++++--
pan/gui/profiles-dialog.h | 10 +-
pan/gui/server-ui.cc | 4 +-
pan/tasks/nntp.cc | 20 +-
pan/tasks/nntp.h | 2 +-
pan/tasks/task-upload.h | 16 --
pan/usenet-utils/Makefile.am | 4 +-
pan/usenet-utils/mime-utils.cc | 517 ++++++++++++++++++++++++++--------------
pan/usenet-utils/mime-utils.h | 11 +
uulib/uulib.c | 32 ++--
30 files changed, 786 insertions(+), 554 deletions(-)
---
diff --git a/configure.in b/configure.in
index b95f646..9175c81 100644
--- a/configure.in
+++ b/configure.in
@@ -46,14 +46,15 @@ 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
OPENSSL_REQUIRED=1.0.0
LIBNOTIFY_REQUIRED=0.4.1
LIBGSASL_REQUIRED=1.6.1
-LIBGKR_REQUIRED=6.2.2
+LIBGKR_REQUIRED=3.2.2
+LIBGPGME_REQUIRED=1.3.0
AC_SUBST(GLIB_REQUIRED)
AC_SUBST(GMIME_REQUIRED)
AC_SUBST(GTK_REQUIRED)
@@ -147,6 +148,11 @@ if test "x$HAVE_GKR" = "xyes"; then
AC_DEFINE([HAVE_GKR],[1],[gnome-keyring-1 for password storage])
fi
+dnl Check for gpgme for message encryption / signing
+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
dnl Check to see if strftime supports the use of %l and %k
AC_MSG_CHECKING(for %l and %k support in strftime)
diff --git a/gtkspell/gtkspell/gtkspell.c b/gtkspell/gtkspell/gtkspell.c
index ecca064..a648f1e 100644
--- a/gtkspell/gtkspell/gtkspell.c
+++ b/gtkspell/gtkspell/gtkspell.c
@@ -51,7 +51,7 @@ static gboolean
gtkspell_text_iter_forward_word_end(GtkTextIter *i) {
GtkTextIter iter;
-/* heuristic:
+/* heuristic:
* if we're on an singlequote/apostrophe and
* if the next letter is alphanumeric,
* this is an apostrophe. */
@@ -122,7 +122,7 @@ static void
check_range(GtkSpell *spell, GtkTextBuffer *buffer,
GtkTextIter start, GtkTextIter end, gboolean force_all) {
/* we need to "split" on word boundaries.
- * luckily, pango knows what "words" are
+ * luckily, pango knows what "words" are
* so we don't have to figure it out. */
GtkTextIter wstart, wend, cursor, precursor;
@@ -134,7 +134,7 @@ check_range(GtkSpell *spell, GtkTextBuffer *buffer,
if (gtk_text_iter_inside_word(&end))
gtk_text_iter_forward_word_end(&end);
if (!gtk_text_iter_starts_word(&start)) {
- if (gtk_text_iter_inside_word(&start) ||
+ if (gtk_text_iter_inside_word(&start) ||
gtk_text_iter_ends_word(&start)) {
gtk_text_iter_backward_word_start(&start);
} else {
@@ -153,7 +153,7 @@ check_range(GtkSpell *spell, GtkTextBuffer *buffer,
gtk_text_iter_backward_char(&precursor);
highlight = gtk_text_iter_has_tag(&cursor, spell->tag_highlight) ||
gtk_text_iter_has_tag(&precursor, spell->tag_highlight);
-
+
gtk_text_buffer_remove_tag(buffer, spell->tag_highlight, &start, &end);
/* Fix a corner case when replacement occurs at beginning of buffer:
@@ -173,11 +173,11 @@ check_range(GtkSpell *spell, GtkTextBuffer *buffer,
wend = wstart;
gtk_text_iter_forward_word_end(&wend);
- inword = (gtk_text_iter_compare(&wstart, &cursor) < 0) &&
+ inword = (gtk_text_iter_compare(&wstart, &cursor) < 0) &&
(gtk_text_iter_compare(&cursor, &wend) <= 0);
if (inword && !force_all) {
- /* this word is being actively edited,
+ /* this word is being actively edited,
* only check if it's already highligted,
* otherwise defer this check until later. */
if (highlight)
@@ -232,7 +232,7 @@ insert_text_after(GtkTextBuffer *buffer, GtkTextIter *iter,
/* we need to check a range of text. */
gtk_text_buffer_get_iter_at_mark(buffer, &start, spell->mark_insert_start);
check_range(spell, buffer, start, *iter, FALSE);
-
+
gtk_text_buffer_move_mark(buffer, spell->mark_insert_end, iter);
}
@@ -251,7 +251,7 @@ delete_range_after(GtkTextBuffer *buffer,
}
static void
-mark_set(GtkTextBuffer *buffer, GtkTextIter *iter,
+mark_set(GtkTextBuffer *buffer, GtkTextIter *iter,
GtkTextMark *mark, GtkSpell *spell) {
/* if the cursor has moved and there is a deferred check so handle it now */
if ((mark == gtk_text_buffer_get_insert(buffer)) && spell->deferred_check)
@@ -262,7 +262,7 @@ static void
get_word_extents_from_mark(GtkTextBuffer *buffer,
GtkTextIter *start, GtkTextIter *end, GtkTextMark *mark) {
gtk_text_buffer_get_iter_at_mark(buffer, start, mark);
- if (!gtk_text_iter_starts_word(start))
+ if (!gtk_text_iter_starts_word(start))
gtk_text_iter_backward_word_start(start);
*end = *start;
if (gtk_text_iter_inside_word(end))
@@ -276,7 +276,7 @@ add_to_dictionary(GtkWidget *menuitem, GtkSpell *spell) {
get_word_extents_from_mark(spell->buffer, &start, &end, spell->mark_click);
word = gtk_text_buffer_get_text(spell->buffer, &start, &end, FALSE);
-
+
enchant_dict_add_to_pwl( spell->speller, word, strlen(word));
gtkspell_recheck_all(spell);
@@ -291,7 +291,7 @@ ignore_all(GtkWidget *menuitem, GtkSpell *spell) {
get_word_extents_from_mark(spell->buffer, &start, &end, spell->mark_click);
word = gtk_text_buffer_get_text(spell->buffer, &start, &end, FALSE);
-
+
enchant_dict_add_to_session(spell->speller, word, strlen(word));
gtkspell_recheck_all(spell);
@@ -304,7 +304,7 @@ replace_word(GtkWidget *menuitem, GtkSpell *spell) {
char *oldword;
const char *newword;
GtkTextIter start, end;
-
+
if (!spell->speller)
return;
@@ -324,7 +324,7 @@ replace_word(GtkWidget *menuitem, GtkSpell *spell) {
gtk_text_buffer_insert(spell->buffer, &start, newword, -1);
gtk_text_buffer_end_user_action(spell->buffer);
- enchant_dict_store_replacement(spell->speller,
+ enchant_dict_store_replacement(spell->speller,
oldword, strlen(oldword),
newword, strlen(newword));
@@ -340,7 +340,7 @@ add_suggestion_menus(GtkSpell *spell, GtkTextBuffer *buffer,
char **suggestions;
size_t n_suggs, i;
char *label;
-
+
menu = topmenu;
if (!spell->speller)
@@ -389,7 +389,7 @@ add_suggestion_menus(GtkSpell *spell, GtkTextBuffer *buffer,
label = g_strdup_printf(_("Add \"%s\" to Dictionary"), word);
mi = gtk_image_menu_item_new_with_label(label);
g_free(label);
- gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi),
+ gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi),
gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_MENU));
g_signal_connect(G_OBJECT(mi), "activate",
G_CALLBACK(add_to_dictionary), spell);
@@ -398,7 +398,7 @@ add_suggestion_menus(GtkSpell *spell, GtkTextBuffer *buffer,
/* - Ignore All */
mi = gtk_image_menu_item_new_with_label(_("Ignore All"));
- gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi),
+ gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi),
gtk_image_new_from_stock(GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU));
g_signal_connect(G_OBJECT(mi), "activate",
G_CALLBACK(ignore_all), spell);
@@ -500,7 +500,7 @@ populate_popup(GtkTextView *textview, GtkMenu *menu, GtkSpell *spell) {
/* we need to figure out if they picked a misspelled word. */
get_word_extents_from_mark(spell->buffer, &start, &end, spell->mark_click);
- /* if our highlight algorithm ever messes up,
+ /* if our highlight algorithm ever messes up,
* this isn't correct, either. */
if (!gtk_text_iter_has_tag(&start, spell->tag_highlight))
return; /* word wasn't misspelled. */
@@ -524,8 +524,8 @@ button_press_event(GtkTextView *view, GdkEventButton *event, GtkSpell *spell) {
if (spell->deferred_check)
check_deferred_range(spell, spell->buffer, TRUE);
- gtk_text_view_window_to_buffer_coords(view,
- GTK_TEXT_WINDOW_TEXT,
+ gtk_text_view_window_to_buffer_coords(view,
+ GTK_TEXT_WINDOW_TEXT,
event->x, event->y,
&x, &y);
gtk_text_view_get_iter_at_location(view, &iter, x, y);
@@ -542,7 +542,7 @@ static gboolean
popup_menu_event(GtkTextView *view, GtkSpell *spell) {
GtkTextIter iter;
- gtk_text_buffer_get_iter_at_mark(spell->buffer, &iter,
+ gtk_text_buffer_get_iter_at_mark(spell->buffer, &iter,
gtk_text_buffer_get_insert(spell->buffer));
gtk_text_buffer_move_mark(spell->buffer, spell->mark_click, &iter);
return FALSE; /* false: let gtk process this event, too. */
@@ -693,7 +693,7 @@ gtkspell_set_buffer(GtkSpell *spell, GtkTextBuffer *buffer)
#ifdef HAVE_PANGO_UNDERLINE_ERROR
"underline", PANGO_UNDERLINE_ERROR,
#else
- "foreground", "red",
+ "foreground", "red",
"underline", PANGO_UNDERLINE_SINGLE,
#endif
NULL);
@@ -711,7 +711,7 @@ gtkspell_set_buffer(GtkSpell *spell, GtkTextBuffer *buffer)
spell->mark_click = gtk_text_buffer_create_mark(spell->buffer,
"gtkspell-click",
&start, TRUE);
-
+
spell->deferred_check = FALSE;
/* now check the entire text buffer. */
diff --git a/pan/data-impl/data-impl.cc b/pan/data-impl/data-impl.cc
index 65e7e73..6d822ee 100644
--- a/pan/data-impl/data-impl.cc
+++ b/pan/data-impl/data-impl.cc
@@ -125,35 +125,9 @@ DataImpl :: save_state ()
}
}
-
-namespace
-{
-
- static void
- stored_password (GnomeKeyringResult res, gpointer user_data)
- {
- if (res == GNOME_KEYRING_RESULT_OK)
- g_print ("password saved successfully!\n");
- else
- g_print ("couldn't save password: %s", gnome_keyring_result_to_message (res));
- }
-
- static void
- found_password (GnomeKeyringResult res, const gchar* password, gpointer user_data)
- {
- if (res == GNOME_KEYRING_RESULT_OK)
- g_print ("password found was: %s\n", password);
- else
- g_print ("couldn't find password: %s", gnome_keyring_result_to_message (res));
-
- /* Once this function returns |password| will be freed */
- }
-
-}
-
#ifdef HAVE_GKR
GnomeKeyringResult
-DataImpl :: password_encrypt (const PasswordData& pw)
+DataImpl :: password_encrypt (const PasswordData* pw)
{
g_return_val_if_fail (gnome_keyring_is_available(), GNOME_KEYRING_RESULT_NO_KEYRING_DAEMON);
@@ -161,17 +135,17 @@ DataImpl :: password_encrypt (const PasswordData& pw)
gnome_keyring_store_password_sync (
GNOME_KEYRING_NETWORK_PASSWORD,
GNOME_KEYRING_DEFAULT,
- _("Pan server password"),
- pw.pw.str,
- "user", pw.user.str,
- "server", pw.server.c_str(),
+ _("Pan newsreader server passwords"),
+ pw->pw.str,
+ "user", pw->user.str,
+ "server", pw->server.c_str(),
NULL)
);
}
GnomeKeyringResult
-DataImpl :: password_decrypt (PasswordData& pw) const
+DataImpl :: password_decrypt (PasswordData* pw) const
{
gchar* pwd(0);
@@ -181,13 +155,14 @@ DataImpl :: password_decrypt (PasswordData& pw) const
gnome_keyring_find_password_sync (
GNOME_KEYRING_NETWORK_PASSWORD,
&pwd,
- "user", pw.user.str,
- "server", pw.server.c_str(),
+ "user", pw->user.str,
+ "server", pw->server.c_str(),
NULL);
- std::string tmp(pwd);
+ std::string tmp;
+ if (pwd) tmp = pwd;
gnome_keyring_free_password(pwd);
- pw.pw = tmp;
+ pw->pw = tmp;
return ret;
}
diff --git a/pan/data-impl/data-impl.h b/pan/data-impl/data-impl.h
index 8590fd9..2929477 100644
--- a/pan/data-impl/data-impl.h
+++ b/pan/data-impl/data-impl.h
@@ -111,8 +111,8 @@ namespace pan
public:
#ifdef HAVE_GKR
- GnomeKeyringResult password_encrypt (const PasswordData&);
- GnomeKeyringResult password_decrypt (PasswordData&) const;
+ GnomeKeyringResult password_encrypt (const PasswordData*);
+ GnomeKeyringResult password_decrypt (PasswordData*) const;
#endif
private:
diff --git a/pan/data-impl/profiles.cc b/pan/data-impl/profiles.cc
index 3ad36b3..b31c9b4 100644
--- a/pan/data-impl/profiles.cc
+++ b/pan/data-impl/profiles.cc
@@ -86,7 +86,7 @@ namespace
mc.profiles[mc.profile_name].clear ();
}
- if ((element_name == "signature_file") && !mc.profile_name.empty()) {
+ if ((element_name == "signature-file") && !mc.profile_name.empty()) {
Profile& p (mc.profiles[mc.profile_name]);
for (const char **k(attribute_names), **v(attribute_vals); *k; ++k, ++v) {
if (!strcmp(*k,"active"))
@@ -98,6 +98,15 @@ namespace
}
}
}
+ if ((element_name == "gpg-signature") && !mc.profile_name.empty()) {
+ Profile& p (mc.profiles[mc.profile_name]);
+ for (const char **k(attribute_names), **v(attribute_vals); *k; ++k, ++v) {
+ if (!strcmp(*k,"active"))
+ p.use_sigfile = false;
+ p.sig_type = p.GPGSIG;
+ p.use_gpgsig = true;
+ }
+ }
}
// Called for close tags </foo>
@@ -113,7 +122,8 @@ namespace
if (!mc.profile_name.empty()) {
Profile& p (mc.profiles[mc.profile_name]);
- if (element_name == "signature_file") p.signature_file.assign (t.str, t.len);
+ if (element_name == "signature-file") p.signature_file.assign (t.str, t.len);
+ else if (element_name == "gpg-signature") p.gpg_sig_uid.assign (t.str, t.len);
else if (element_name == "attribution") p.attribution.assign (t.str, t.len);
else if (element_name == "fqdn") p.fqdn.assign (t.str, t.len);
else if (element_name == "xface") p.xface.assign (t.str, t.len);
@@ -200,17 +210,23 @@ ProfilesImpl :: serialize (std::ostream& out) const
out << indent(depth) << "<address>" << escaped(it->second.address) << "</address>\n";
out << indent(depth) << "<server>" << escaped(it->second.posting_server.to_view()) << "</server>\n";
out << indent(depth) << "<xface>" << escaped(it->second.xface) << "</xface>\n";
- if (!it->second.signature_file.empty()) {
+ if (!it->second.signature_file.empty() && it->second.sig_type != Profile::GPGSIG) {
const char * type;
switch (it->second.sig_type) {
case Profile::FILE: type = "file"; break;
case Profile::COMMAND: type = "command"; break;
default: type = "text"; break;
}
- out << indent(depth) << "<signature_file"
+ out << indent(depth) << "<signature-file"
<< " active=\"" << (it->second.use_sigfile ? "true" : "false") << '"'
<< " type=\"" << type << '"'
- << ">" << escaped(it->second.signature_file) << "</signature_file>\n";
+ << ">" << escaped(it->second.signature_file) << "</signature-file>\n";
+ }
+ if (it->second.use_gpgsig && !it->second.gpg_sig_uid.empty())
+ {
+ out << indent(depth) << "<gpg-signature"
+ << " active=\"" << (it->second.use_sigfile ? "true" : "false") << '"'
+ << ">" << escaped(it->second.gpg_sig_uid) << "</gpg-signature>\n";
}
if (!it->second.attribution.empty())
out << indent(depth) << "<attribution>" << escaped(it->second.attribution) << "</attribution>\n";
diff --git a/pan/data-impl/server.cc b/pan/data-impl/server.cc
index ff6cb3f..898f606 100644
--- a/pan/data-impl/server.cc
+++ b/pan/data-impl/server.cc
@@ -130,10 +130,11 @@ DataImpl :: set_server_auth (const Quark & server,
#ifndef HAVE_GKR
s->password = password;
#else
- PasswordData pw ;
+ PasswordData pw;
pw.server = s->host;
pw.user = username;
pw.pw = password;
+ password_encrypt(&pw);
#endif
}
@@ -211,7 +212,31 @@ DataImpl :: get_server_auth (const Quark & server,
bool found (s);
if (found) {
setme_username = s->username;
+#ifndef HAVE_GKR
setme_password = s->password;
+#else
+ PasswordData pw;
+ pw.server = s->host;
+ pw.user = s->username;
+ GnomeKeyringResult res (password_decrypt(&pw));
+ switch (res)
+ {
+ case GNOME_KEYRING_RESULT_NO_MATCH:
+ Log::add_info_va(_("There seems to be no Password set for Server %s."), s->host.c_str());
+ break;
+
+ case GNOME_KEYRING_RESULT_NO_KEYRING_DAEMON:
+ Log::add_urgent_va (_("The Gnome keyring denied access to the Passwords."), s->host.c_str());
+ break;
+
+ case GNOME_KEYRING_RESULT_OK:
+ setme_password.assign(pw.pw.str, pw.pw.len);
+ break;
+
+ default:
+ break;
+ }
+#endif
}
return found;
@@ -393,29 +418,6 @@ DataImpl :: load_server_properties (const DataIO& source)
s.username = kv["username"];
#ifndef HAVE_GKR
s.password = kv["password"];
-#else
- PasswordData pw ;
- pw.server = s.host;
- pw.user = s.username;
- GnomeKeyringResult res (password_decrypt(pw));
- switch (res)
- {
- case GNOME_KEYRING_RESULT_NO_MATCH:
- Log::add_info_va(_("There seems to be no password set for server %s."), s.host.c_str());
- break;
-
- case GNOME_KEYRING_RESULT_NO_KEYRING_DAEMON:
- Log::add_urgent_va (_("The gnome keyring denied access to the passwords."), s.host.c_str());
- break;
-
- case GNOME_KEYRING_RESULT_OK:
- s.password.assign(pw.pw.str, pw.pw.len);
- break;
-
- default:
- Log::add_info_va ("%s %s",gnome_keyring_result_to_message (res),res);
- break;
- }
#endif
s.port = to_int (kv["port"], STD_NNTP_PORT);
s.max_connections = to_int (kv["connection-limit"], 2);
@@ -467,12 +469,13 @@ DataImpl :: save_server_properties (DataIO& data_io) const
*out << indent(depth++) << "<server-properties>\n";
foreach_const (alpha_quarks_t, servers, it) {
const Server* s (find_server (*it));
- debug("saving server, "<<s->cert);
+ std::string user, pass;
+ get_server_auth(*it, user, pass);
*out << indent(depth++) << "<server id=\"" << escaped(it->to_string()) << "\">\n";
*out << indent(depth) << "<host>" << escaped(s->host) << "</host>\n"
<< indent(depth) << "<port>" << s->port << "</port>\n"
- << indent(depth) << "<username>" << escaped(s->username) << "</username>\n"
- << indent(depth) << "<password>" << escaped(s->password) << "</password>\n"
+ << indent(depth) << "<username>" << escaped(user) << "</username>\n"
+ << indent(depth) << "<password>" << escaped(pass) << "</password>\n"
<< indent(depth) << "<expire-articles-n-days-old>" << s->article_expiration_age << "</expire-articles-n-days-old>\n"
<< indent(depth) << "<connection-limit>" << s->max_connections << "</connection-limit>\n"
<< indent(depth) << "<newsrc>" << s->newsrc_filename << "</newsrc>\n"
diff --git a/pan/data/data.h b/pan/data/data.h
index 79dd046..f9d94ea 100644
--- a/pan/data/data.h
+++ b/pan/data/data.h
@@ -94,8 +94,10 @@ namespace pan
std::string username;
std::string address;
bool use_sigfile;
- enum { TEXT, FILE, COMMAND };
+ bool use_gpgsig;
+ enum { TEXT, FILE, COMMAND, GPGSIG };
int sig_type;
+ std::string gpg_sig_uid;
std::string signature_file;
std::string attribution;
std::string fqdn;
@@ -113,10 +115,11 @@ namespace pan
return it==headers.end() ? nil : it->second;
}
- Profile(): use_sigfile(false), sig_type(TEXT) {}
+ Profile(): use_sigfile(false), use_gpgsig(false), sig_type(TEXT) {}
void clear() { username.clear(); address.clear();
use_sigfile = false;
+ use_gpgsig = false;
sig_type = TEXT;
signature_file.clear(); attribution.clear(); }
};
@@ -216,8 +219,8 @@ namespace pan
public:
#ifdef HAVE_GKR
- virtual GnomeKeyringResult password_encrypt (const PasswordData&) = 0;
- virtual GnomeKeyringResult password_decrypt (PasswordData&) const = 0;
+ virtual GnomeKeyringResult password_encrypt (const PasswordData*) = 0;
+ virtual GnomeKeyringResult password_decrypt (PasswordData*) const = 0;
#endif
/** Gets a quark to the provided hostname */
virtual bool find_server_by_hn (const Quark& server, Quark& setme) const = 0;
diff --git a/pan/gui/Makefile.am b/pan/gui/Makefile.am
index c5517f8..2e930cf 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@ -DPANLOCALEDIR=\""$(panlocaledir)"\"
+ @OPENSSL_CFLAGS@ @LIBNOTIFY_CFLAGS@ @LIBGNOME_KEYRING_1_CFLAGS@ @GPGME_CFLAGS@ -DPANLOCALEDIR=\""$(panlocaledir)"\"
noinst_LIBRARIES = libpangui.a
@@ -33,7 +33,8 @@ libpangui_a_SOURCES = \
server-ui.cc \
task-pane.cc \
xface.c \
- url.cc
+ url.cc \
+ gpg.cc
noinst_HEADERS = \
action-manager.h \
@@ -75,7 +76,8 @@ noinst_HEADERS = \
task-pane.h \
url.h \
wait.h \
- xface.h
+ xface.h \
+ gpg.h
EXTRA_DIST = \
panrc.rc
@@ -95,7 +97,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@
+ ../../uulib/libuu.a @GTKSPELL_LIBS@ @GTK_LIBS@ @GMIME_LIBS@ @GLIB_LIBS@ @OPENSSL_LIBS@ @LIBNOTIFY_LIBS@ @LIBGNOME_KEYRING_1_LIBS@ @GPGME_LIBS@
if HAVE_WIN32
pan_LDFLAGS = -mwindows
diff --git a/pan/gui/actions.cc b/pan/gui/actions.cc
index e553163..a2e0ea5 100644
--- a/pan/gui/actions.cc
+++ b/pan/gui/actions.cc
@@ -150,7 +150,6 @@ namespace
void do_flag_off (GtkAction*) { pan_ui->do_flag_off(); }
void do_next_flag (GtkAction*) { pan_ui->do_next_flag(); }
void do_last_flag (GtkAction*) { pan_ui->do_last_flag(); }
- void do_download_flagged (GtkAction*) { pan_ui->do_download_flagged(); }
void do_invert_selection (GtkAction*) { pan_ui->do_invert_selection(); }
void do_mark_all_flagged (GtkAction*) { pan_ui->do_mark_all_flagged(); }
void do_show_score_dialog (GtkAction*) { pan_ui->do_show_score_dialog(); }
@@ -577,11 +576,6 @@ namespace
N_("_Goto last flagged Thread"),
G_CALLBACK(do_last_flag) },
- { "get-all-flagged", NULL,
- N_("_Get all flagged Thread"), NULL, ///TODO invent shortcut
- N_("_Get all flagged Thread"),
- G_CALLBACK(do_download_flagged) },
-
{ "invert-selection", NULL,
N_("_Invert Selection"), "<control>I",
N_("_Invert Selection"),
diff --git a/pan/gui/body-pane.cc b/pan/gui/body-pane.cc
index 3819aee..bdd4aff 100644
--- a/pan/gui/body-pane.cc
+++ b/pan/gui/body-pane.cc
@@ -969,6 +969,11 @@ BodyPane :: append_part (GMimeObject * obj, GtkAllocation * widget_size)
is_done = true;
}
+ else if (g_mime_content_type_is_type (type, "text", "*"))
+ {
+
+ }
+
// otherwise, bitch and moan.
if (!is_done) {
const char * filename = g_mime_part_get_filename (part);
@@ -1049,7 +1054,7 @@ BodyPane :: set_text_from_message (GMimeMessage * message)
{
const char * fallback_charset (_charset.empty() ? 0 : _charset.c_str());
- // manditory headers...
+ // mandatory headers...
std::string s;
size_t w(0), l(0);
l = add_header_line (s, message, _("Subject"), "Subject", fallback_charset);
@@ -1098,6 +1103,7 @@ BodyPane :: set_text_from_message (GMimeMessage * message)
GdkPixbuf *pixbuf = NULL;
pixbuf = pan_gdk_pixbuf_create_from_x_face (pch);
gtk_image_set_from_pixbuf (GTK_IMAGE(_xface), pixbuf);
+ gtk_widget_show_all(_verbose);
g_object_unref (pixbuf);
}
// set the face
@@ -1416,7 +1422,7 @@ 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);
- w = _xface = gtk_image_new ();
+ 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);
w = _face = gtk_image_new ();
diff --git a/pan/gui/gui.cc b/pan/gui/gui.cc
index bb1d060..975fe90 100644
--- a/pan/gui/gui.cc
+++ b/pan/gui/gui.cc
@@ -69,6 +69,10 @@ extern "C" {
#include "profiles-dialog.h"
+#ifdef HAVE_GPGME
+ #include "gpg.h"
+#endif
+
namespace pan
{
void
@@ -170,20 +174,6 @@ namespace
}
}
-//namespace
-//{
-// enum {
-// TARGET_STRING,
-// TARGET_ROOTWIN
-// };
-//
-// static GtkTargetEntry target_list[] = {
-// { const_cast<char*>("STRING"), 0, TARGET_STRING },
-// { const_cast<char*>("text/plain"), 0, TARGET_STRING },
-// { const_cast<char*>("application/x-rootwindow-drop"), 0, TARGET_ROOTWIN }
-// };
-//}
-
GUI :: GUI (Data& data, Queue& queue, Prefs& prefs, GroupPrefs& group_prefs):
_data (data),
_queue (queue),
@@ -354,6 +344,9 @@ 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
@@ -372,7 +365,7 @@ GUI :: ~GUI ()
const std::string accel_filename (get_accel_filename());
gtk_accel_map_save (accel_filename.c_str());
- chmod (accel_filename.c_str(), 0600);
+ ::chmod (accel_filename.c_str(), 0600);
if (hpane)
_prefs.set_int ("main-window-hpane-position", gtk_paned_get_position(GTK_PANED(hpane)));
@@ -402,6 +395,10 @@ GUI :: ~GUI ()
foreach (std::set<GtkWidget*>, unref, it)
g_object_unref (*it);
g_object_unref (G_OBJECT(_ui_manager));
+
+#ifdef HAVE_GPGME
+ deinit_gpg();
+#endif
}
/***
@@ -1191,14 +1188,6 @@ GUI :: do_last_flag ()
}
void
-GUI :: do_download_flagged ()
-{
- do_mark_all_flagged();
- do_download_selected_article();
- do_unselect_all_articles();
-}
-
-void
GUI :: do_invert_selection ()
{
// std::cerr<<__LINE__<< " "<<__FILE__<<" : implement me.\n";
@@ -1646,7 +1635,6 @@ void GUI :: do_tabbed_layout (bool tabbed)
vpane = 0;
}
- //gtk_widget_hide_all (_workarea_bin);
gtk_widget_hide (_workarea_bin);
GtkWidget * group_w (_group_pane->root());
diff --git a/pan/gui/gui.h b/pan/gui/gui.h
index 1f38559..9bb36ad 100644
--- a/pan/gui/gui.h
+++ b/pan/gui/gui.h
@@ -140,7 +140,6 @@ namespace pan
virtual void do_next_flag ();
virtual void do_last_flag ();
virtual void do_mark_all_flagged ();
- virtual void do_download_flagged ();
virtual void do_invert_selection ();
virtual void do_show_score_dialog ();
virtual void do_show_new_score_dialog ();
diff --git a/pan/gui/pan-file-entry.cc b/pan/gui/pan-file-entry.cc
index ded3008..a732bbb 100644
--- a/pan/gui/pan-file-entry.cc
+++ b/pan/gui/pan-file-entry.cc
@@ -81,7 +81,7 @@ pan :: file_entry_new (const char * title, int chooser_action)
g_object_set_data (G_OBJECT(hbox), "chooser-action", GINT_TO_POINTER(chooser_action));
g_object_set_data (G_OBJECT(hbox), "entry", e);
file_entry_set (hbox, g_get_home_dir());
-
+
gtk_widget_show (e);
gtk_widget_show (b);
return hbox;
diff --git a/pan/gui/pan-ui.h b/pan/gui/pan-ui.h
index a32be83..1921c17 100644
--- a/pan/gui/pan-ui.h
+++ b/pan/gui/pan-ui.h
@@ -71,7 +71,6 @@ namespace pan
virtual void do_next_flag () = 0;
virtual void do_last_flag () = 0;
virtual void do_mark_all_flagged () = 0;
- virtual void do_download_flagged () = 0;
virtual void do_invert_selection () = 0;
virtual void do_cancel_article () = 0;
virtual void do_supersede_article () = 0;
diff --git a/pan/gui/pan.cc b/pan/gui/pan.cc
index 53a64ee..271131f 100644
--- a/pan/gui/pan.cc
+++ b/pan/gui/pan.cc
@@ -51,6 +51,12 @@ extern "C" {
#include <pan/tasks/socket-impl-openssl.h>
#endif
+#ifdef HAVE_GPGME
+ #include <gpgme.h>
+ #define GPG_DEF 1
+ #include <pan/gui/gpg.h>
+#endif
+
#include <pan/data/cert-store.h>
#include <pan/tasks/socket-impl-gio.h>
#include <pan/tasks/socket-impl-main.h>
@@ -82,8 +88,6 @@ namespace
namespace
{
-// bool keyring_active(gnome_keyring_is_available());
-
GMainLoop * nongui_gmainloop (0);
void mainloop ()
@@ -544,7 +548,7 @@ _("General Options\n"
}
/***
- ** DBUS STUFF
+ ** DBUS
***/
#define PAN_DBUS_SERVICE_NAME "news.pan.NZB"
diff --git a/pan/gui/pan.ui.h b/pan/gui/pan.ui.h
index 3be86ae..abecb3e 100644
--- a/pan/gui/pan.ui.h
+++ b/pan/gui/pan.ui.h
@@ -138,8 +138,6 @@ const char * fallback_ui_file =
" <menuitem action='last-flagged' />\n"
" <menuitem action='mark-all-flagged' />\n"
" <separator />\n"
-" <menuitem action='get-all-flagged' />\n"
-" <separator />\n"
" <menuitem action='plonk' />\n"
" <menuitem action='view-article-score' />\n"
" <separator />\n"
@@ -216,8 +214,6 @@ const char * fallback_ui_file =
" <menuitem action='last-flagged' />\n"
" <menuitem action='mark-all-flagged' />\n"
" <separator />\n"
-" <menuitem action='get-all-flagged' />\n"
-" <separator />\n"
" <menuitem action='plonk' />\n"
" <menuitem action='view-article-score' />\n"
" <separator />\n"
diff --git a/pan/gui/post-ui.cc b/pan/gui/post-ui.cc
index 7947e72..2231ad9 100644
--- a/pan/gui/post-ui.cc
+++ b/pan/gui/post-ui.cc
@@ -59,6 +59,11 @@ 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"
@@ -97,6 +102,7 @@ namespace
bool remember_charsets (true);
bool master_reply (true);
+ bool gpg_enc (false);
void on_remember_charset_toggled (GtkToggleAction * toggle, gpointer)
{
@@ -108,6 +114,11 @@ namespace
master_reply = gtk_toggle_action_get_active (toggle);
}
+ void on_enc_toggled (GtkToggleAction * toggle, gpointer)
+ {
+ gpg_enc = gtk_toggle_action_get_active (toggle);
+ }
+
void on_spellcheck_toggled (GtkToggleAction * toggle, gpointer post_g)
{
const bool enabled = gtk_toggle_action_get_active (toggle);
@@ -259,9 +270,12 @@ PostUI :: set_spellcheck_enabled (bool enabled)
{
#ifdef HAVE_GTKSPELL
GtkTextView * view = GTK_TEXT_VIEW(_body_view);
- GtkSpell * spell = gtkspell_get_from_text_view (view);
- if (spell)
- gtkspell_detach (spell);
+ if (view)
+ {
+ GtkSpell * spell = gtkspell_get_from_text_view (view);
+ if (spell)
+ gtkspell_detach (spell);
+ }
#endif
}
}
@@ -311,6 +325,68 @@ PostUI :: set_always_run_editor (bool run)
_prefs.set_flag ("always-run-editor", run);
}
+std::string
+PostUI :: gpg_sign_and_encrypt(const std::string& body, bool& fail)
+{
+ fail = true;
+
+ const Profile profile (get_current_profile ());
+ std::string uid = profile.gpg_sig_uid;
+ if (uid.empty()) return "";
+
+ gpgme_data_t gpg_buf, gpg_out_buf;
+ gpgme_error_t err;
+ gpgme_key_t mykey(0), key;
+
+ 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);
+
+ /* find key to uid */
+ err = gpgme_op_keylist_start (gpg_ctx, 0, 0);
+ while (!err)
+ {
+ err = gpgme_op_keylist_next (gpg_ctx, &key);
+ if (err) break;
+ if (strcmp(key->subkeys->keyid, uid.c_str()) == 0) { mykey = key; break; }
+ }
+ if (!mykey) return std::string("");
+
+ gpgme_key_t keys[] = { key, NULL} ;
+
+ if (gpg_enc)
+ {
+ gpgme_encrypt_result_t enc_res;
+ err = gpgme_op_encrypt (gpg_ctx, keys, GPGME_ENCRYPT_EXPECT_SIGN, gpg_buf, gpg_out_buf);
+ enc_res = gpgme_op_encrypt_result (gpg_ctx);
+ }
+ else if (profile.use_sigfile)
+ {
+ gpgme_sign_result_t sign_res;
+ gpgme_op_sign (gpg_ctx, gpg_buf, gpg_out_buf, GPGME_SIG_MODE_CLEAR);
+ sign_res = gpgme_op_sign_result (gpg_ctx);
+ }
+
+ gpgme_data_seek (gpg_out_buf,SEEK_SET, 0);
+ /* print buf */
+ 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;
+ ret = gpgme_data_read (gpg_out_buf, buffer, sizeof(buffer));
+ }
+
+ gpgme_data_release(gpg_buf);
+ gpgme_data_release(gpg_out_buf);
+
+ fail = false;
+ return ret_str.str();
+}
+
void
PostUI :: set_wrap_mode (bool wrap)
{
@@ -427,6 +503,7 @@ namespace
{ "always-run-editor", 0, N_("Always Run Editor"), 0, 0, G_CALLBACK(do_edit2), false },
{ "remember-charset", 0, N_("Remember Character Encoding for this Group"), 0, 0, G_CALLBACK(on_remember_charset_toggled), true },
{ "master-reply", 0, N_("Thread attached replies"), 0, 0, G_CALLBACK(on_mr_toggled), true },
+ { "gpg-encrypt", 0, N_("GPG-Encrypt the message"), 0, 0, G_CALLBACK(on_enc_toggled), true },
{ "spellcheck", 0, N_("Check _Spelling"), 0, 0, G_CALLBACK(on_spellcheck_toggled), true }
};
@@ -612,7 +689,7 @@ namespace
return true; // don't invoke the default handler that destroys the widget
}
- gboolean delete_parts_cb (GtkWidget* w, GdkEvent*, gpointer user_data)
+ gboolean delete_parts_cb (GtkWidget* w, GdkEvent*, gpointer user_data)
{
return false;
}
@@ -984,9 +1061,18 @@ PostUI :: maybe_post_message (GMimeMessage * message)
if(_file_queue_empty)
{
- _post_task = new TaskPost (server, message);
- _post_task->add_listener (this);
- _queue.add_task (_post_task, Queue::TOP);
+ bool fail;
+ std::string res = gpg_sign_and_encrypt(get_body(), fail);
+ if (!fail)
+ {
+ gtk_text_buffer_set_text (_body_buf, res.c_str(), res.size());
+ GMimeMessage* msg = new_message_from_ui(POSTING);
+ _post_task = new TaskPost (server, msg);
+ _post_task->add_listener (this);
+ _queue.add_task (_post_task, Queue::TOP);
+ } else
+ Log::add_urgent_va("Failed to sign the Message with your public key.");
+ return false;
} else {
// prepend header for xml file (if one was chosen)
@@ -1367,27 +1453,18 @@ GMimeMessage*
PostUI :: new_message_from_ui (Mode mode, bool copy_body)
{
GMimeMessage * msg(0);
- if (mode!=MULTI)
- msg = g_mime_message_new (false);
- else
- msg = (GMimeMessage*)g_mime_multipart_new_with_subtype("mixed");
+ msg = g_mime_message_new (false);
// headers from the ui: From
const Profile profile (get_current_profile ());
std::string s;
profile.get_from_header (s);
- if (mode!=MULTI)
- g_mime_message_set_sender (msg, s.c_str());
- else
- g_mime_object_set_header ((GMimeObject *) msg, "From", s.c_str());
+ g_mime_message_set_sender (msg, s.c_str());
// headers from the ui: Subject
const char * cpch (gtk_entry_get_text (GTK_ENTRY(_subject_entry)));
if (cpch) {
- if (mode!=MULTI)
- g_mime_message_set_subject (msg, cpch);
- else
- g_mime_object_set_header ((GMimeObject *) msg, "Subject", cpch);
+ g_mime_message_set_subject (msg, cpch);
}
// headers from the ui: To
@@ -1439,11 +1516,11 @@ PostUI :: new_message_from_ui (Mode mode, bool copy_body)
g_free (pch);
// User-Agent
- if ((mode==POSTING || mode == UPLOADING || mode == MULTI) && _prefs.get_flag (USER_AGENT_PREFS_KEY, true))
+ if ((mode==POSTING || mode == UPLOADING) && _prefs.get_flag (USER_AGENT_PREFS_KEY, true))
g_mime_object_set_header ((GMimeObject *) msg, "User-Agent", get_user_agent());
// Message-ID for single text-only posts
- if ((mode==POSTING || mode==UPLOADING || mode == MULTI) && _prefs.get_flag (MESSAGE_ID_PREFS_KEY, false)) {
+ if ((mode==POSTING || mode==UPLOADING) && _prefs.get_flag (MESSAGE_ID_PREFS_KEY, false)) {
const std::string message_id = !profile.fqdn.empty()
? GNKSA::generate_message_id (profile.fqdn)
: GNKSA::generate_message_id_from_email_address (profile.address);
@@ -1451,138 +1528,43 @@ PostUI :: new_message_from_ui (Mode mode, bool copy_body)
}
// body & charset
- if (mode != MULTI)
- {
- std::string body;
- if (copy_body) body = get_body();
- GMimeStream * stream = g_mime_stream_mem_new_with_buffer (body.c_str(), body.size());
- const std::string charset ((mode==POSTING && !_charset.empty()) ? _charset : "UTF-8");
- if (charset != "UTF-8") {
- // add a wrapper to convert from UTF-8 to $charset
- GMimeStream * tmp = g_mime_stream_filter_new (stream);
- g_object_unref (stream);
- GMimeFilter * filter = g_mime_filter_charset_new ("UTF-8", charset.c_str());
- g_mime_stream_filter_add (GMIME_STREAM_FILTER(tmp), filter);
- g_object_unref (filter);
- stream = tmp;
- }
- GMimeDataWrapper * content_object = g_mime_data_wrapper_new_with_stream (stream, GMIME_CONTENT_ENCODING_DEFAULT);
+ {
+ std::string body;
+ if (copy_body) body = get_body();
+ GMimeStream * stream = g_mime_stream_mem_new_with_buffer (body.c_str(), body.size());
+ const std::string charset ((mode==POSTING && !_charset.empty()) ? _charset : "UTF-8");
+ if (charset != "UTF-8") {
+ // add a wrapper to convert from UTF-8 to $charset
+ GMimeStream * tmp = g_mime_stream_filter_new (stream);
g_object_unref (stream);
- GMimePart * part = g_mime_part_new ();
- pch = g_strdup_printf ("text/plain; charset=%s", charset.c_str());
-
- 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_part_set_content_object (part, content_object);
- g_mime_part_set_content_encoding (part, GMIME_CONTENT_ENCODING_8BIT);
- g_object_unref (content_object);
- g_mime_message_set_mime_part (msg, GMIME_OBJECT(part));
- g_object_unref (part);
+ GMimeFilter * filter = g_mime_filter_charset_new ("UTF-8", charset.c_str());
+ g_mime_stream_filter_add (GMIME_STREAM_FILTER(tmp), filter);
+ g_object_unref (filter);
+ stream = tmp;
}
+ GMimeDataWrapper * content_object = g_mime_data_wrapper_new_with_stream (stream, GMIME_CONTENT_ENCODING_DEFAULT);
+ g_object_unref (stream);
+ GMimePart * part = g_mime_part_new ();
+ pch = g_strdup_printf ("text/plain; charset=%s", charset.c_str());
+// pch = g_strdup_printf ("multipart/encrypted;"
+// "protocol=\"application/pgp-encrypted\";"
+// "boundary=\"------------24i8m5cwm904t8v\"; charset=%s", charset.c_str());
- return msg;
-}
-
-GMimeMultipart*
-PostUI :: new_multipart_from_ui (bool copy_body)
-{
- GMimeMultipart * msg(g_mime_multipart_new_with_subtype("mixed"));
-
- // headers from the ui: From
- const Profile profile (get_current_profile ());
- std::string s;
- profile.get_from_header (s);
- g_mime_object_set_header ((GMimeObject *) msg, "From", s.c_str());
-
- // headers from the ui: Subject
- const char * cpch (gtk_entry_get_text (GTK_ENTRY(_subject_entry)));
- if (cpch)
- g_mime_object_set_header ((GMimeObject *) msg, "Subject", cpch);
-
- // headers from the ui: To
- const StringView to (gtk_entry_get_text (GTK_ENTRY(_to_entry)));
- if (!to.empty())
- pan_g_mime_message_add_recipients_from_string ((GMimeMessage*)msg, GMIME_RECIPIENT_TYPE_TO, to.str);
-
- // headers from the ui: Newsgroups
- const StringView groups (gtk_entry_get_text (GTK_ENTRY(_groups_entry)));
- if (!groups.empty())
- g_mime_object_set_header ((GMimeObject *) msg, "Newsgroups", groups.str);
-
- // headers from the ui: Followup-To
- const StringView followupto (gtk_entry_get_text (GTK_ENTRY(_followupto_entry)));
- if (!followupto.empty())
- g_mime_object_set_header ((GMimeObject *) msg, "Followup-To", followupto.str);
-
- // headers from the ui: Reply-To
- const StringView replyto (gtk_entry_get_text (GTK_ENTRY(_replyto_entry)));
- if (!replyto.empty())
- g_mime_object_set_header ((GMimeObject *) msg, "Reply-To", replyto.str);
+ g_mime_object_set_header ((GMimeObject *) msg, "Content-Transfer-Encoding", "Base64");
- // build headers from the 'more headers' entry field
- std::map<std::string,std::string> headers;
- GtkTextBuffer * buf (_headers_buf);
- GtkTextIter start, end;
- gtk_text_buffer_get_bounds (buf, &start, &end);
- char * pch = gtk_text_buffer_get_text (buf, &start, &end, false);
- StringView key, val, v(pch);
- v.trim ();
- while (v.pop_token (val, '\n') && val.pop_token(key,':')) {
- key.trim ();
- val.eat_chars (1);
- val.trim ();
- std::string key_str (key.to_string());
- if (extra_header_is_editable (key, val))
- g_mime_object_set_header ((GMimeObject *) msg, key.to_string().c_str(),
- val.to_string().c_str());
- }
- g_free (pch);
-
- // User-Agent
- if (_prefs.get_flag (USER_AGENT_PREFS_KEY, true))
- g_mime_object_set_header ((GMimeObject *) msg, "User-Agent", get_user_agent());
-
- // Message-ID for single text-only posts
- if (_prefs.get_flag (MESSAGE_ID_PREFS_KEY, false)) {
- const std::string message_id = !profile.fqdn.empty()
- ? GNKSA::generate_message_id (profile.fqdn)
- : GNKSA::generate_message_id_from_email_address (profile.address);
- pan_g_mime_message_set_message_id ((GMimeMessage*)msg, message_id.c_str());
+ 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_part_set_content_object (part, content_object);
+ g_mime_part_set_content_encoding (part, GMIME_CONTENT_ENCODING_8BIT);
+ g_object_unref (content_object);
+ g_mime_message_set_mime_part (msg, GMIME_OBJECT(part));
+ g_object_unref (part);
}
- // body & charset
- std::string body;
- if (copy_body) body = get_body();
- GMimeStream * stream = g_mime_stream_mem_new_with_buffer (body.c_str(), body.size());
- const std::string charset (_charset.empty() ? _charset : "UTF-8");
- if (charset != "UTF-8") {
- // add a wrapper to convert from UTF-8 to $charset
- GMimeStream * tmp = g_mime_stream_filter_new (stream);
- g_object_unref (stream);
- GMimeFilter * filter = g_mime_filter_charset_new ("UTF-8", charset.c_str());
- g_mime_stream_filter_add (GMIME_STREAM_FILTER(tmp), filter);
- g_object_unref (filter);
- stream = tmp;
- }
- GMimeDataWrapper * content_object = g_mime_data_wrapper_new_with_stream (stream, GMIME_CONTENT_ENCODING_DEFAULT);
- g_object_unref (stream);
- GMimePart * part = g_mime_part_new ();
- pch = g_strdup_printf ("text/plain; charset=%s", charset.c_str());
-
- 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_part_set_content_object (part, content_object);
- g_mime_part_set_content_encoding (part, GMIME_CONTENT_ENCODING_8BIT);
- g_object_unref (content_object);
- g_mime_message_set_mime_part ((GMimeMessage*)msg, GMIME_OBJECT(part));
- g_object_unref (part);
-
return msg;
}
-
void
PostUI :: save_draft ()
{
@@ -1767,7 +1749,7 @@ namespace
{
file :: get_text_file_contents (pch, sig);
}
- else // command
+ else if (type == Profile::COMMAND)
{
int argc = 0;
char ** argv = 0;
@@ -1807,6 +1789,10 @@ namespace
g_strfreev (argv);
}
+ else if (type == Profile::GPGSIG)
+ {
+
+ }
/* Convert signature to UTF-8. Since the signature is a local file,
* we assume the contents is in the user's locale's charset.
@@ -1926,11 +1912,11 @@ PostUI :: apply_profile_to_body ()
// get the new signature
std::string sig;
- if (profile.use_sigfile) {
- load_signature (profile.signature_file, profile.sig_type, sig);
- int ignored;
- if (GNKSA::find_signature_delimiter (sig, ignored) == GNKSA::SIG_NONE)
- sig = std::string("\n\n-- \n") + sig;
+ if (profile.use_sigfile && !profile.use_gpgsig) {
+ load_signature (profile.signature_file, profile.sig_type, sig);
+ int ignored;
+ if (GNKSA::find_signature_delimiter (sig, ignored) == GNKSA::SIG_NONE)
+ sig = std::string("\n\n-- \n") + sig;
}
_current_signature = sig;
@@ -2942,18 +2928,16 @@ PostUI :: PostUI (GtkWindow * parent,
_body_changed_id(0),
_body_changed_idle_tag(0),
_filequeue_eventbox (0),
- _filequeue_label (0),
- _multipart(g_mime_multipart_new_with_subtype("mixed"))
-{
+ _filequeue_label (0)
- g_mime_multipart_set_boundary(_multipart,"$pan_multipart_gmime_message$");
+{
rng.seed();
_upload_queue.add_listener (this);
/* init timer for autosave */
- set_draft_autosave_timeout( prefs.get_int("draft-autosave-timeout-min", 10 ));
+// set_draft_autosave_timeout( prefs.get_int("draft-autosave-timeout-min", 10 ));
// _draft_autosave_id = g_timeout_add_seconds( _draft_autosave_timeout * 60, draft_save_cb, this);
g_assert (profiles.has_profiles());
diff --git a/pan/gui/post-ui.h b/pan/gui/post-ui.h
index d6d6792..9d15665 100644
--- a/pan/gui/post-ui.h
+++ b/pan/gui/post-ui.h
@@ -84,6 +84,8 @@ namespace pan
void set_wrap_mode (bool wrap);
void set_always_run_editor (bool);
+ std::string gpg_sign_and_encrypt(const std::string& body, bool&);
+
void update_parts_tab();
//popup action entries
@@ -94,7 +96,6 @@ namespace pan
void move_down ();
void move_top ();
void move_bottom ();
-// void select_encode (GtkAction*); deactivated for now
static void do_popup_menu (GtkWidget*, GdkEventButton *event, gpointer pane_g);
static gboolean on_button_pressed (GtkWidget * treeview, GdkEventButton *event, gpointer userdata);
@@ -161,7 +162,6 @@ namespace pan
int _total_parts;
std::string _save_file;
MTRand rng;
- GMimeMultipart * _multipart;
private:
friend class UploadQueue;
@@ -173,9 +173,8 @@ namespace pan
void add_actions (GtkWidget* box);
void apply_profile_to_body ();
void apply_profile_to_headers ();
- enum Mode { DRAFTING, POSTING, UPLOADING, MULTI };
+ enum Mode { DRAFTING, POSTING, UPLOADING, MULTI};
GMimeMessage * new_message_from_ui (Mode mode, bool copy_body=true);
- GMimeMultipart* new_multipart_from_ui (bool copy_body=true);
Profile get_current_profile ();
bool check_message (const Quark& server, GMimeMessage*, bool binpost=false);
bool check_charset ();
diff --git a/pan/gui/post.ui.h b/pan/gui/post.ui.h
index d873cb1..7e91bcb 100644
--- a/pan/gui/post.ui.h
+++ b/pan/gui/post.ui.h
@@ -22,6 +22,8 @@ const char * fallback_post_ui =
" <separator />\n"
" <menuitem action='master-reply' />\n"
" <separator />\n"
+" <menuitem action='gpg-encrypt' />\n"
+" <separator />\n"
" <menuitem action='run-editor' />\n"
" <menuitem action='always-run-editor' />\n"
" <separator />\n"
diff --git a/pan/gui/prefs-ui.cc b/pan/gui/prefs-ui.cc
index 73f973a..5e113d3 100644
--- a/pan/gui/prefs-ui.cc
+++ b/pan/gui/prefs-ui.cc
@@ -558,9 +558,9 @@ PrefsDialog :: PrefsDialog (Prefs& prefs, GtkWindow* parent):
HIG :: workarea_add_section_title (t, &row, _("Articles"));
HIG :: workarea_add_section_spacer (t, row, 5);
w = new_check_button (_("Space selects next article rather than next unread"), "space-selects-next-article", true, prefs);
- HIG :: workarea_add_wide_control (t, &row, w);
+ HIG :: workarea_add_wide_control (t, &row, w);
w = new_check_button (_("Expand threads upon selection."), "expand-selected-articles", false, prefs);
- HIG :: workarea_add_wide_control (t, &row, w);
+ HIG :: workarea_add_wide_control (t, &row, w);
w = new_check_button (_("Always show article deletion confirmation dialog"), "show-deletion-confirm-dialog", true, prefs);
HIG :: workarea_add_wide_control (t, &row, w);
w = new_check_button (_("Smooth scrolling"), "smooth-scrolling", true, prefs);
diff --git a/pan/gui/profiles-dialog.cc b/pan/gui/profiles-dialog.cc
index d2496ce..db8e265 100644
--- a/pan/gui/profiles-dialog.cc
+++ b/pan/gui/profiles-dialog.cc
@@ -35,6 +35,11 @@ extern "C" {
#include "pan-file-entry.h"
#include "profiles-dialog.h"
+#ifdef HAVE_GPGME
+ #include <gpgme.h>
+ #include <pan/gui/gpg.h>
+#endif
+
using namespace pan;
/***
@@ -61,6 +66,24 @@ namespace
gtk_widget_set_sensitive (GTK_WIDGET(sensitize), gtk_toggle_button_get_active(tb));
}
+ void on_signature_type_changed (GtkComboBox* w, gpointer g)
+ {
+ ProfileDialog* d(static_cast<ProfileDialog*>(g));
+ g_return_if_fail(d);
+ gint row = gtk_combo_box_get_active (w);
+
+ if (row == 2) // GPG
+ {
+ gtk_widget_hide (d->_signature_file);
+ gtk_widget_show (d->_gpg_sig_entry);
+ }
+ else
+ {
+ gtk_widget_show (d->_signature_file);
+ gtk_widget_hide (d->_gpg_sig_entry);
+ }
+ }
+
GtkWidget* make_servers_combo (const Data& data, const Quark sel)
{
const quarks_t servers (data.get_servers ());
@@ -92,6 +115,8 @@ namespace
}
}
+/// TODO (perhaps) beautify this!
+
ProfileDialog :: ProfileDialog (const Data & data,
const StringView & profile_name,
const Profile & profile,
@@ -105,6 +130,8 @@ ProfileDialog :: ProfileDialog (const Data & data,
gtk_dialog_set_default_response (GTK_DIALOG(_root), GTK_RESPONSE_OK);
gtk_window_set_role (GTK_WINDOW(_root), "pan-edit-profile-dialog");
+ GtkWidget* hbox(0), * l(0);
+
int row (0);
GtkWidget *t = HIG :: workarea_create ();
HIG :: workarea_add_section_title (t, &row, _("Profile Information"));
@@ -136,33 +163,85 @@ ProfileDialog :: ProfileDialog (const Data & data,
w = _signature_file = pan:: file_entry_new (_("Signature File"), GTK_FILE_CHOOSER_ACTION_OPEN);
g_signal_connect (_signature_file_check, "toggled", G_CALLBACK(on_sig_file_toggled), w);
file_entry_set (w, profile.signature_file.c_str());
- HIG :: workarea_add_row (t, &row, _("_Signature:"), w);
- GtkListStore * store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
GtkTreeIter iter;
+
+ std::map<std::string, int> author_numbers;
+ GtkListStore * 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);
+
+
+ GtkCellRenderer * 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);
+
+ 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_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_set (store, &iter, 0, _("Text"), 1, Profile::TEXT, -1);
gtk_list_store_append (store, &iter);
- gtk_list_store_set (store, &iter, 0, _("Command"), 1, Profile::COMMAND, -1);
- w = _signature_file_combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL(store));
- g_signal_connect (_signature_file_check, "toggled", G_CALLBACK(on_sig_file_toggled), w);
- GtkCellRenderer * renderer (gtk_cell_renderer_text_new ());
- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (w), renderer, TRUE);
+ gtk_list_store_set (store, &iter, 0, _("GPG Signature"),1, Profile::GPGSIG, -1);
+ gtk_list_store_append (store, &iter);
+ 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);
+ gtk_box_pack_start(GTK_BOX(hbox), l, false, false, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), w, true, true, 0);
+ _signature_file_combo = hbox;
+ _signature_file_combo_box = w;
+
+ g_signal_connect (w, "changed", G_CALLBACK(on_signature_type_changed), this);
+
+ 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 = 0;
if (profile.sig_type == profile.TEXT) active = 1;
- if (profile.sig_type == profile.COMMAND) active = 2;
+ if (profile.sig_type == profile.GPGSIG) active = 2;
+ if (profile.sig_type == profile.COMMAND) active = 3;
+
gtk_combo_box_set_active (GTK_COMBO_BOX(w), active);
- HIG :: workarea_add_row (t, &row, _("Signature _Type:"), w);
+
+ 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);
+ gtk_box_pack_start(GTK_BOX(vbox), _gpg_sig_entry, false, false, 0);
+ HIG :: workarea_add_row (t, &row, "",vbox);
HIG :: workarea_add_section_divider (t, &row);
HIG :: workarea_add_section_title (t, &row, _("X-Face (Avatar)"));
w = _xface_entry = gtk_entry_new ();
set_entry (w, profile.xface);
- gtk_widget_set_tooltip_markup (w, _("You can add an avatar icon to your postings with a unique X-Face code. \n\
-Add the code without the trailing <b>\"X-Face:\"</b> \n if it was generated by a helper program (for example : http://www.dairiki.org/xface/xface.php)."));
+ gtk_widget_set_tooltip_markup (w, _("You can add an avatar icon to your postings with a unique X-Face code. \n"
+ "Add the code without the trailing <b>\"X-Face:\"</b> \n if it was generated "
+ "by a helper program (for example : http://www.dairiki.org/xface/xface.php)."));
HIG :: workarea_add_row (t, &row, _("_X-Face:"), w, NULL);
HIG :: workarea_add_section_divider (t, &row);
HIG :: workarea_add_section_title (t, &row, _("Optional Information"));
@@ -170,8 +249,9 @@ Add the code without the trailing <b>\"X-Face:\"</b> \n if it was generated by a
w = _msgid_fqdn_entry = gtk_entry_new ();
set_entry (w, profile.fqdn);
- gtk_widget_set_tooltip_text (w, _("When posting to Usenet, your article's Message-ID contains a domain name. \n\
-You can set a custom domain name here, or leave it blank to let Pan use the domain name from your email address."));
+ gtk_widget_set_tooltip_text (w, _("When posting to Usenet, your article's Message-ID contains a domain name. \n"
+ "You can set a custom domain name here, or leave it blank to let Pan use the "
+ "domain name from your email address."));
HIG :: workarea_add_row (t, &row, _("Message-ID _Domain Name:"), w, NULL);
w = _attribution_entry = gtk_entry_new ();
@@ -200,7 +280,8 @@ You can set a custom domain name here, or leave it blank to let Pan use the doma
s += it->first + ": " + it->second + "\n";
gtk_text_buffer_set_text (gtk_text_view_get_buffer (GTK_TEXT_VIEW(w)), s.c_str(), s.size());
GtkWidget * eventbox = gtk_event_box_new ();
- gtk_widget_set_tooltip_text (eventbox, _("Extra headers to be included in your posts, such as\nReply-To: \"Your Name\" <yourname somewhere com>\nOrganization: Your Organization"));
+ gtk_widget_set_tooltip_text (eventbox, _("Extra headers to be included in your posts, such as\nReply-To: \"Your Name\""
+ "<yourname somewhere com>\nOrganization: Your Organization\n"));
GtkWidget * scrolled_window = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(scrolled_window),
GTK_SHADOW_IN);
@@ -211,8 +292,11 @@ You can set a custom domain name here, or leave it blank to let Pan use the doma
gtk_container_add (GTK_CONTAINER(eventbox), scrolled_window);
HIG :: workarea_add_row (t, &row, _("E_xtra Headers:"), eventbox, w);
- 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);
+ /// 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);
+
gtk_box_pack_start (GTK_BOX( gtk_dialog_get_content_area( GTK_DIALOG(_root))), t, true, true, 0);
gtk_widget_show_all (t);
@@ -220,6 +304,8 @@ You can set a custom domain name here, or leave it blank to let Pan use the doma
gtk_window_set_transient_for (GTK_WINDOW(_root), parent);
gtk_window_set_position (GTK_WINDOW(_root), GTK_WIN_POS_CENTER_ON_PARENT);
}
+
+ on_signature_type_changed(GTK_COMBO_BOX(_signature_file_combo_box), this);
}
ProfileDialog :: ~ProfileDialog ()
@@ -271,16 +357,28 @@ ProfileDialog :: get_profile (std::string& profile_name, Profile& profile)
from_entry (_attribution_entry, profile.attribution);
profile.use_sigfile = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(_signature_file_check));
- from_entry (file_entry_gtk_entry(_signature_file), profile.signature_file);
int type;
GtkTreeIter iter;
- GtkComboBox * combo = GTK_COMBO_BOX (_signature_file_combo);
+ GtkComboBox * combo = GTK_COMBO_BOX (_signature_file_combo_box);
gtk_combo_box_get_active_iter (combo, &iter);
GtkTreeModel * model (gtk_combo_box_get_model (combo));
gtk_tree_model_get (model, &iter, 1, &type, -1);
profile.sig_type = type;
+ profile.use_gpgsig = (type == profile.GPGSIG);
+ if (!profile.use_gpgsig)
+ from_entry (file_entry_gtk_entry(_signature_file), profile.signature_file);
+
+ std::cerr<<"use gpgsig get profile "<<profile.use_gpgsig<<"\n";
+
+ 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;
+
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 44ce27c..6ec6779 100644
--- a/pan/gui/profiles-dialog.h
+++ b/pan/gui/profiles-dialog.h
@@ -46,12 +46,16 @@ namespace pan
GtkWidget * _xface_entry;
GtkWidget * _attribution_entry;
GtkWidget * _signature_file_check;
- GtkWidget * _signature_file;
- GtkWidget * _signature_file_combo;
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;
+ GtkWidget * _gpg_sig_entry;
+
static bool run_until_valid_or_cancel (ProfileDialog& p);
};
diff --git a/pan/gui/server-ui.cc b/pan/gui/server-ui.cc
index 35ea2c8..b6cabac 100644
--- a/pan/gui/server-ui.cc
+++ b/pan/gui/server-ui.cc
@@ -137,6 +137,7 @@ namespace
pan_spin_button_set (d->connection_limit_spin, max_conn);
pan_entry_set_text (d->auth_username_entry, user);
pan_entry_set_text (d->auth_password_entry, pass);
+ d->cert = cert;
// set the age combobox
GtkComboBox * combo (GTK_COMBO_BOX (d->expiration_age_combo));
@@ -183,7 +184,6 @@ namespace
server_edit_response_cb (GtkDialog * w, int response, gpointer user_data)
{
bool destroy (true);
- bool bf_set (false);
ServerEditDialog * d (static_cast<ServerEditDialog*>(user_data));
g_assert (d!=NULL);
@@ -208,7 +208,9 @@ namespace
if (gtk_combo_box_get_active_iter (combo, &iter))
gtk_tree_model_get (gtk_combo_box_get_model(combo), &iter, 1, &rank, -1);
int ssl(0);
+
StringView cert(d->cert);
+
#ifdef HAVE_OPENSSL
combo = GTK_COMBO_BOX (d->ssl_combo);
if (gtk_combo_box_get_active_iter (combo, &iter))
diff --git a/pan/tasks/nntp.cc b/pan/tasks/nntp.cc
index 15030c9..8142b84 100644
--- a/pan/tasks/nntp.cc
+++ b/pan/tasks/nntp.cc
@@ -302,10 +302,10 @@ NNTP :: help (Listener * l)
}
void
-NNTP :: get_group (Listener * l)
+NNTP :: get_group (Listener * l, const Quark& group)
{
_listener = l;
- _commands.push_back ("GROUP \r\n");
+ _commands.push_back (build_command ("GROUP %s\r\n",group.c_str()));
write_next_command();
}
@@ -318,7 +318,7 @@ NNTP :: xover (const Quark & group,
{
_listener = l;
- get_group(l);
+ get_group(l,group);
_commands.push_back (build_command ("XOVER %"G_GUINT64_FORMAT"-%"G_GUINT64_FORMAT"\r\n", low, high));
@@ -331,7 +331,7 @@ NNTP :: xover_count_only (const Quark & group,
{
_listener = l;
- get_group(l);
+ get_group(l,group);
_commands.push_back (build_command ("XOVER"));
@@ -361,7 +361,7 @@ NNTP :: article (const Quark & group,
{
_listener = l;
- get_group(l);
+ get_group(l,group);
_commands.push_back (build_command ("ARTICLE %"G_GUINT64_FORMAT"\r\n", article_number));
@@ -375,7 +375,7 @@ NNTP :: article (const Quark & group,
{
_listener = l;
- get_group(l);
+ get_group(l,group);
_commands.push_back (build_command ("ARTICLE %s\r\n", message_id));
@@ -389,7 +389,7 @@ NNTP :: get_headers (const Quark & group,
{
_listener = l;
- get_group(l);
+ get_group(l,group);
_commands.push_back (build_command ("HEAD %s\r\n", message_id));
@@ -403,7 +403,7 @@ NNTP :: get_headers (const Quark & group,
{
_listener = l;
- get_group(l);
+ get_group(l,group);
_commands.push_back (build_command ("HEAD %"G_GUINT64_FORMAT"\r\n", article_number));
@@ -417,7 +417,7 @@ NNTP :: get_body (const Quark & group,
{
_listener = l;
- get_group(l);
+ get_group(l,group);
_commands.push_back (build_command ("BODY %s\r\n", message_id));
@@ -431,7 +431,7 @@ NNTP :: get_body (const Quark & group,
{
_listener = l;
- if (group != _group) get_group(l);
+ if (group != _group) get_group(l,group);
_commands.push_back (build_command ("BODY %"G_GUINT64_FORMAT"\r\n", article_number));
diff --git a/pan/tasks/nntp.h b/pan/tasks/nntp.h
index a6bdcdc..60e6d51 100644
--- a/pan/tasks/nntp.h
+++ b/pan/tasks/nntp.h
@@ -162,7 +162,7 @@ namespace pan
public:
/* Internal only */
- void get_group (Listener * l);
+ void get_group (Listener * l, const Quark& group);
void get_headers (const Quark & group, const char * message_id, Listener * l);
void get_headers (const Quark & group, uint64_t article_number, Listener * l);
void get_body (const Quark & group, const char * message_id, Listener * l);
diff --git a/pan/tasks/task-upload.h b/pan/tasks/task-upload.h
index 9048c71..8e425f2 100644
--- a/pan/tasks/task-upload.h
+++ b/pan/tasks/task-upload.h
@@ -101,22 +101,6 @@ namespace pan
unsigned long get_bytes_remaining () const;
void stop ();
const std::string& get_basename() { return _basename; }
-// std::string enc_mode_to_str(EncodeMode& e)
-// {
-// std::string res;
-// switch (e)
-// {
-// case YENC:
-// res += "yEnc";
-// break;
-// case PLAIN:
-// break;
-// default:
-// res += "yEnc";
-// break;
-// }
-// return res;
-// }
/** only call this for tasks in the NEED_ENCODE state
* attempts to acquire the encoder thread and start encoding
diff --git a/pan/usenet-utils/Makefile.am b/pan/usenet-utils/Makefile.am
index 7ee5aed..1ebac86 100644
--- a/pan/usenet-utils/Makefile.am
+++ b/pan/usenet-utils/Makefile.am
@@ -1,4 +1,6 @@
-AM_CPPFLAGS = -I top_srcdir@ @GMIME_CFLAGS@ @GLIB_CFLAGS@
+AM_CPPFLAGS = -I top_srcdir@ @GMIME_CFLAGS@ @GLIB_CFLAGS@ @GPGME_CFLAGS@
+
+AM_LDFLAGS = @GPGME_LIBS@
noinst_LIBRARIES = libusenetutils.a
diff --git a/pan/usenet-utils/mime-utils.cc b/pan/usenet-utils/mime-utils.cc
index 4b24ff6..182c894 100644
--- a/pan/usenet-utils/mime-utils.cc
+++ b/pan/usenet-utils/mime-utils.cc
@@ -22,6 +22,7 @@
#include <cstring>
#include <cstdlib>
#include <iostream>
+#include <sstream>
extern "C"
{
#include <unistd.h>
@@ -36,6 +37,11 @@ extern "C"
#define is_nonempty_string(a) ((a) && (*a))
+#ifdef HAVE_GPGME
+ #include <gpgme.h>
+ #include <pan/gui/gpg.h>
+#endif
+
using namespace pan;
namespace
@@ -329,6 +335,37 @@ namespace
}
}
+/***
+**** GPG
+***/
+
+namespace
+{
+
+ bool
+ gpg_is_beginning_line (const StringView& line)
+ {
+ if (line.len <= 1) return false;//g_return_val_if_fail(line.len > 1, false);
+ StringView l(line);
+// l.ltrim(); l.ltrim();
+ return !strncmp (l.str, GPG_MARKER_BEGIN, GPG_MARKER_BEGIN_LEN);
+ }
+
+ bool
+ gpg_is_ending_line (const StringView& line)
+ {
+ if (line.len <= 1) return false;//g_return_val_if_fail(line.len > 1, false);
+ StringView l(line);
+// l.ltrim(); l.ltrim();
+ return !strncmp (l.str, GPG_MARKER_END, GPG_MARKER_END_LEN);
+ }
+
+}
+
+/***
+****
+***/
+
namespace
{
guint
@@ -359,9 +396,11 @@ namespace
enum EncType
{
- ENC_PLAIN,
- ENC_YENC,
- ENC_UU
+ ENC_PLAIN = 1 ,
+ ENC_YENC = 1 << 1,
+ ENC_UU = 1 << 2,
+ ENC_GPG = 1 << 3,
+ ENC_BASE64 = 1<< 4
};
namespace
@@ -423,22 +462,81 @@ namespace
return true;
}
+ GMimeStream* gpg_decrypt (gpgme_ctx_t gpg_ctx, GMimeStream* s, TempPart* part)
+ {
+
+ 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);
+
+ gpgme_data_t gpg_buf, gpg_out_buf;
+ gpgme_key_t key;
+ gpgme_error_t err;
+ bool found(false);
+
+ StringView v(streambuf);
+ gpgme_data_new_from_mem (&gpg_buf, v.str, v.len, 0);
+
+ gpgme_strerror(gpgme_data_new (&gpg_out_buf));
+
+ gpgme_signers_clear(gpg_ctx);
+
+ gpgme_set_armor (gpg_ctx, 1);
+ gpgme_data_set_encoding (gpg_out_buf, GPGME_DATA_ENCODING_NONE);
+
+ err = gpgme_op_decrypt (gpg_ctx, gpg_buf, gpg_out_buf);
+// gpgme_op_decrypt_result
+
+ 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);
+
+ gpgme_data_release(gpg_buf);
+ gpgme_data_release(gpg_out_buf);
+
+ g_mime_stream_reset(decrypted);
+
+ return decrypted;
+ }
+
void apply_source_and_maybe_filter (TempPart * part, GMimeStream * s)
{
+
if (!part->stream) {
part->stream = g_mime_stream_mem_new ();
- if (part->type != ENC_PLAIN) {
- part->filter_stream =
- g_mime_stream_filter_new (part->stream);
- part->filter = part->type == ENC_UU
- ? g_mime_filter_basic_new (GMIME_CONTENT_ENCODING_UUENCODE, FALSE)
- : g_mime_filter_yenc_new (FALSE);
+ if (part->type != ENC_PLAIN && part->type != ENC_GPG) {
+ part->filter_stream = g_mime_stream_filter_new (part->stream);
+ switch (part->type)
+ {
+ case ENC_UU:
+ part->filter = g_mime_filter_basic_new (GMIME_CONTENT_ENCODING_UUENCODE, FALSE);
+ break;
+
+ case ENC_YENC:
+ part->filter = g_mime_filter_yenc_new (FALSE);
+ break;
+ }
+
g_mime_stream_filter_add (GMIME_STREAM_FILTER(part->filter_stream),
part->filter);
}
}
- g_mime_stream_write_to_stream (s, part->type == ENC_PLAIN ?
+ g_mime_stream_write_to_stream (s, (part->type == ENC_PLAIN || part->type == ENC_GPG) ?
part->stream : part->filter_stream);
g_object_unref (s);
}
@@ -452,212 +550,245 @@ namespace
sep_state():uu_temp(NULL) {};
};
-bool
-separate_encoded_parts (GMimeStream * istream, sep_state &state)
-{
- temp_parts_t& master(state.master_list);
- temp_parts_t& appendme(state.current_list);
- TempPart * cur = NULL;
- EncType type = ENC_PLAIN;
- GByteArray * line;
- gboolean yenc_looking_for_part_line = FALSE;
- gint64 linestart_pos = 0;
- gint64 sub_begin = 0;
- guint line_len;
- bool found = false;
-
- /* sanity clause */
- pan_return_val_if_fail (istream!=NULL,false);
-
- sub_begin = 0;
- line = g_byte_array_sized_new (4096);
-
- while ((line_len = stream_readln (istream, line, &linestart_pos)))
+ bool
+ separate_encoded_parts (GMimeStream * istream, sep_state &state)
{
- char * line_str = (char*) line->data;
- char * pch = strchr (line_str, '\n');
- if (pch != NULL) {
- pch[1] = '\0';
- line_len = pch - line_str;
- }
+ temp_parts_t& master(state.master_list);
+ temp_parts_t& appendme(state.current_list);
+ TempPart * cur = NULL;
+ EncType type = ENC_PLAIN;
+ GByteArray * line;
+ gboolean yenc_looking_for_part_line = FALSE;
+ gboolean gpg_looking_for_line = FALSE;
+ gint64 linestart_pos = 0;
+ gint64 sub_begin = 0;
+ guint line_len;
+ bool found = false;
- switch (type)
+ /* sanity clause */
+ pan_return_val_if_fail (istream!=NULL,false);
+
+ sub_begin = 0;
+ line = g_byte_array_sized_new (4096);
+
+ while ((line_len = stream_readln (istream, line, &linestart_pos)))
{
- case ENC_PLAIN:
- {
- const StringView line_pstr (line_str, line_len);
+ char * line_str = (char*) line->data;
+ char * pch = strchr (line_str, '\n');
+ if (pch != NULL) {
+ pch[1] = '\0';
+ line_len = pch - line_str;
+ }
- if (uu_is_beginning_line (line_pstr))
+ switch (type)
+ {
+ case ENC_PLAIN:
{
- gulong mode = 0ul;
- char * filename = NULL;
+ const StringView line_pstr (line_str, line_len);
- found=true;
- // flush the current entry
- if (cur != NULL) {
- GMimeStream * s = g_mime_stream_substream (istream, sub_begin, linestart_pos);
+ if (uu_is_beginning_line (line_pstr))
+ {
+ gulong mode = 0ul;
+ char * filename = NULL;
+
+ found=true;
+ // flush the current entry
+ if (cur != NULL) {
+ GMimeStream * s = g_mime_stream_substream (istream, sub_begin, linestart_pos);
apply_source_and_maybe_filter (cur, s);
- if ( append_if_not_present (master, cur) )
- append_if_not_present (appendme, cur);
- cur = NULL;
- }
- // start a new section (or, if filename matches, continue an existing one)
- sub_begin = linestart_pos;
- uu_parse_begin_line (line_pstr, &filename, &mode);
- cur = find_filename_part (master, filename);
- if (cur)
- g_free (filename);
- else
- cur = new TempPart (type=ENC_UU, filename);
- state.uu_temp = cur;
- }
- else if (yenc_is_beginning_line (line_str))
- {
- found = true;
- // flush the current entry
- if (cur != NULL) {
- GMimeStream * s = g_mime_stream_substream (istream, sub_begin, linestart_pos);
+ if ( append_if_not_present (master, cur) )
+ append_if_not_present (appendme, cur);
+ cur = NULL;
+ }
+
+ // start a new section (or, if filename matches, continue an existing one)
+ sub_begin = linestart_pos;
+ uu_parse_begin_line (line_pstr, &filename, &mode);
+ cur = find_filename_part (master, filename);
+ if (cur)
+ g_free (filename);
+ else
+ cur = new TempPart (type=ENC_UU, filename);
+ state.uu_temp = cur;
+ }
+ else if (yenc_is_beginning_line (line_str))
+ {
+ found = true;
+ // flush the current entry
+ if (cur != NULL) {
+ GMimeStream * s = g_mime_stream_substream (istream, sub_begin, linestart_pos);
apply_source_and_maybe_filter (cur, s);
- if ( append_if_not_present (master, cur) )
- append_if_not_present (appendme, cur);
- cur = NULL;
+
+ if ( append_if_not_present (master, cur) )
+ append_if_not_present (appendme, cur);
+ cur = NULL;
+ }
+ sub_begin = linestart_pos;
+
+ // start a new section (or, if filename matches, continue an existing one)
+ char * fname;
+ int line_len, attach_size, part;
+ yenc_parse_begin_line (line_str, &fname, &line_len, &attach_size, &part);
+ cur = find_filename_part (master, fname);
+ if (cur) {
+ g_free (fname);
+ g_mime_filter_yenc_set_state (GMIME_FILTER_YENC (cur->filter),
+ GMIME_YDECODE_STATE_INIT);
+ }
+ else
+ {
+ cur = new TempPart (type=ENC_YENC, fname);
+ cur->y_line_len = line_len;
+ cur->y_attach_size = attach_size;
+ cur->y_part = part;
+ 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;
}
- sub_begin = linestart_pos;
-
- // start a new section (or, if filename matches, continue an existing one)
- char * fname;
- int line_len, attach_size, part;
- yenc_parse_begin_line (line_str, &fname, &line_len, &attach_size, &part);
- cur = find_filename_part (master, fname);
- if (cur) {
- g_free (fname);
- g_mime_filter_yenc_set_state (GMIME_FILTER_YENC (cur->filter),
- GMIME_YDECODE_STATE_INIT);
+ else if (state.uu_temp != NULL && is_uu_line(line_str, line_len) )
+ {
+ // continue an incomplete uu decode
+ found = true;
+ // flush the current entry
+ if (cur != NULL) {
+ GMimeStream * s = g_mime_stream_substream (istream, sub_begin, linestart_pos);
+ apply_source_and_maybe_filter (cur, s);
+
+ if ( append_if_not_present (master, cur) )
+ append_if_not_present (appendme, cur);
+ cur = NULL;
+ }
+ sub_begin = linestart_pos;
+ cur = state.uu_temp;
+ ++cur->valid_lines;
+ type = ENC_UU;
}
- else
+ else if (cur == NULL)
{
- cur = new TempPart (type=ENC_YENC, fname);
- cur->y_line_len = line_len;
- cur->y_attach_size = attach_size;
- cur->y_part = part;
- yenc_looking_for_part_line = cur->y_part!=0;
+ sub_begin = linestart_pos;
+
+ cur = new TempPart (type = ENC_PLAIN);
}
+ break;
}
- else if (state.uu_temp != NULL && is_uu_line(line_str, line_len) )
+ case ENC_UU:
{
- // continue an incomplete uu decode
- found = true;
- // flush the current entry
- if (cur != NULL) {
- GMimeStream * s = g_mime_stream_substream (istream, sub_begin, linestart_pos);
- apply_source_and_maybe_filter (cur, s);
- if ( append_if_not_present (master, cur) )
+ if (uu_is_ending_line(line_str))
+ {
+ GMimeStream * stream;
+ if (sub_begin < 0)
+ sub_begin = linestart_pos;
+ stream = g_mime_stream_substream (istream, sub_begin, linestart_pos+line_len);
+ apply_source_and_maybe_filter (cur, stream);
+ if( append_if_not_present (master, cur) )
append_if_not_present (appendme, cur);
+
cur = NULL;
+ type = ENC_PLAIN;
+ state.uu_temp = NULL;
}
- sub_begin = linestart_pos;
- cur = state.uu_temp;
- ++cur->valid_lines;
- type = ENC_UU;
- }
- else if (cur == NULL)
- {
- sub_begin = linestart_pos;
+ else if (!is_uu_line(line_str, line_len))
+ {
+ /* hm, this isn't a uenc line, so ending the cat and setting sub_begin to -1 */
+ if (sub_begin >= 0)
+ {
+ GMimeStream * stream = g_mime_stream_substream (istream, sub_begin, linestart_pos);
+ apply_source_and_maybe_filter (cur, stream);
+ }
- cur = new TempPart (type = ENC_PLAIN);
- }
- break;
- }
- case ENC_UU:
- {
- if (uu_is_ending_line(line_str))
- {
- GMimeStream * stream;
- if (sub_begin < 0)
+ sub_begin = -1;
+ }
+ else if (sub_begin == -1)
+ {
+ /* looks like they decided to start using uu lines again. */
+ ++cur->valid_lines;
sub_begin = linestart_pos;
- stream = g_mime_stream_substream (istream, sub_begin, linestart_pos+line_len);
- apply_source_and_maybe_filter (cur, stream);
- if( append_if_not_present (master, cur) )
- append_if_not_present (appendme, cur);
-
- cur = NULL;
- type = ENC_PLAIN;
- state.uu_temp = NULL;
- }
- else if (!is_uu_line(line_str, line_len))
- {
- /* hm, this isn't a uenc line, so ending the cat and setting sub_begin to -1 */
- if (sub_begin >= 0)
+ }
+ else
{
- GMimeStream * stream = g_mime_stream_substream (istream, sub_begin, linestart_pos);
- apply_source_and_maybe_filter (cur, stream);
+ ++cur->valid_lines;
}
-
- sub_begin = -1;
- }
- else if (sub_begin == -1)
- {
- /* looks like they decided to start using uu lines again. */
- ++cur->valid_lines;
- sub_begin = linestart_pos;
+ break;
}
- else
+ case ENC_YENC:
{
- ++cur->valid_lines;
- }
- break;
- }
- case ENC_YENC:
- {
- if (yenc_is_ending_line (line_str))
- {
- GMimeStream * stream = g_mime_stream_substream (istream, sub_begin, linestart_pos+line_len);
+ if (yenc_is_ending_line (line_str))
+ {
+ GMimeStream * stream = g_mime_stream_substream (istream, sub_begin, linestart_pos+line_len);
apply_source_and_maybe_filter (cur, stream);
- yenc_parse_end_line (line_str, &cur->y_size, NULL, &cur->y_pcrc, &cur->y_crc);
- if( append_if_not_present (master, cur) )
- append_if_not_present (appendme, cur);
+ yenc_parse_end_line (line_str, &cur->y_size, NULL, &cur->y_pcrc, &cur->y_crc);
+ if( append_if_not_present (master, cur) )
+ append_if_not_present (appendme, cur);
- cur = NULL;
- type = ENC_PLAIN;
- }
- else if (yenc_looking_for_part_line && yenc_is_part_line(line_str))
- {
- yenc_parse_part_line (line_str, &cur->y_offset_begin, &cur->y_offset_end);
- yenc_looking_for_part_line = FALSE;
- ++cur->valid_lines;
+ cur = NULL;
+ type = ENC_PLAIN;
+ }
+ else if (yenc_looking_for_part_line && yenc_is_part_line(line_str))
+ {
+ yenc_parse_part_line (line_str, &cur->y_offset_begin, &cur->y_offset_end);
+ yenc_looking_for_part_line = FALSE;
+ ++cur->valid_lines;
+ }
+ else
+ {
+ ++cur->valid_lines;
+ }
+ break;
}
- else
+ case ENC_GPG:
{
- ++cur->valid_lines;
+ if (gpg_is_ending_line(line_str))
+ {
+ GMimeStream * stream = g_mime_stream_substream (istream, sub_begin, linestart_pos+line_len);
+ GMimeStream * dec = gpg_decrypt(gpg_ctx, stream, cur);
+ apply_source_and_maybe_filter (cur, dec);
+ gpg_looking_for_line = false;
+ 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;
}
- break;
}
}
- }
- /* close last entry */
- if (cur != NULL)
- {
- if (sub_begin >= 0)
+ /* close last entry */
+ if (cur != NULL)
{
- GMimeStream * stream = g_mime_stream_substream (istream, sub_begin, linestart_pos);
+ if (sub_begin >= 0)
+ {
+ GMimeStream * stream = g_mime_stream_substream (istream, sub_begin, linestart_pos);
apply_source_and_maybe_filter (cur, stream);
- }
+ }
- /* just in case someone started with "yenc" or "begin 644 asf" in a text message to fuck with unwary newsreaders */
- if (cur->valid_lines < 10u)
- cur->type = ENC_PLAIN;
+ /* just in case someone started with "yenc" or "begin 644 asf" in a text message to fuck with unwary newsreaders */
+ if (cur->valid_lines < 10u)
+ cur->type = ENC_PLAIN;
- if( append_if_not_present (master, cur) )
- append_if_not_present (appendme, cur);
- cur = NULL;
- type = ENC_PLAIN;
- }
+ if( append_if_not_present (master, cur) )
+ append_if_not_present (appendme, cur);
+ cur = NULL;
+ type = ENC_PLAIN;
+ }
- g_byte_array_free (line, TRUE);
- return found;
-}
+ g_byte_array_free (line, TRUE);
+ return found;
+ }
}
@@ -782,7 +913,7 @@ namespace
// break it into separate parts for text, uu, and yenc pieces.
sep_state &state(*(sep_state*)data);
temp_parts_t &parts(state.current_list);
- bool split=separate_encoded_parts (istream, state);
+ bool split = separate_encoded_parts (istream, state);
g_mime_stream_reset (istream);
// split?
@@ -883,6 +1014,21 @@ namespace{
return;
v->push_back(temp_p(parent,part) );
}
+
+ void find_gpg_parts_cb(GMimeObject *parent, GMimeObject *part, gpointer data)
+ {
+ if(!GMIME_IS_PART(part))
+ return;
+
+ temp_p_t *v( (temp_p_t *) 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")))
+ return;
+ v->push_back(temp_p(parent,part) );
+ }
+
}
/***
@@ -940,6 +1086,15 @@ mime :: construct_message (GMimeStream ** istreams,
handle_uu_and_yenc_in_text_plain_cb(data.parent, data.part, &state);
}
+// partslist.clear();
+// if (retval != NULL)
+// g_mime_message_foreach(retval, find_text_cb, &partslist);
+// foreach(temp_p_t, partslist, it)
+// {
+// temp_p &data(*it);
+// handle_gpg_encrypted_parts_cb(data.parent, data.part, &state);
+// }
+
// cleanup
foreach (temp_parts_t, state.master_list, it)
{
@@ -1186,7 +1341,7 @@ namespace
g_return_val_if_fail (GMIME_IS_PART (mime_part), NULL);
if (!mime_part->content || !mime_part->content->stream) {
- g_warning ("no content set on this mime part");
+// g_warning ("no content set on this mime part"); // dbg
return NULL;
}
diff --git a/pan/usenet-utils/mime-utils.h b/pan/usenet-utils/mime-utils.h
index 403503b..93a838e 100644
--- a/pan/usenet-utils/mime-utils.h
+++ b/pan/usenet-utils/mime-utils.h
@@ -55,6 +55,17 @@
#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_LEN
+
namespace pan
{
/**
diff --git a/uulib/uulib.c b/uulib/uulib.c
index de8add7..1b7060b 100644
--- a/uulib/uulib.c
+++ b/uulib/uulib.c
@@ -84,7 +84,7 @@
char * uulib_id = "$Id$";
#ifdef SYSTEM_WINDLL
-BOOL _export WINAPI
+BOOL _export WINAPI
DllEntryPoint (HINSTANCE hInstance, DWORD seginfo,
LPVOID lpCmdLine)
{
@@ -574,7 +574,7 @@ UUstrerror (int code)
*/
int UUEXPORT
-UUSetMsgCallback (void *opaque,
+UUSetMsgCallback (void *opaque,
void (*func) _ANSI_ARGS_((void *, char *, int)))
{
uu_MsgCallback = func;
@@ -719,7 +719,7 @@ UULoadFileWithPartNo (char *filename, char *fileid, int delflag, int partno)
fileid = filename;
while (!feof (datei) && !ferror (datei)) {
- /*
+ /*
* Peek file, or some systems won't detect EOF
*/
res = fgetc (datei);
@@ -727,7 +727,7 @@ UULoadFileWithPartNo (char *filename, char *fileid, int delflag, int partno)
break;
else
ungetc (res, datei);
-
+
if ((loaded = ScanPart (datei, fileid, &sr)) == NULL) {
if (sr != UURET_NODATA && sr != UURET_OK && sr != UURET_CONT) {
UUkillfread (loaded);
@@ -778,7 +778,7 @@ UULoadFileWithPartNo (char *filename, char *fileid, int delflag, int partno)
if (uu_fast_scanning && sr != UURET_CONT) break;
continue;
}
-
+
if ((fload = UUPreProcessPart (loaded, &res)) == NULL) {
/*
* no useful data found
@@ -808,7 +808,7 @@ UULoadFileWithPartNo (char *filename, char *fileid, int delflag, int partno)
(loaded->end) ? "end" : "",
codenames[loaded->uudet]);
}
-
+
if ((res = UUInsertPartToList (fload))) {
/*
* couldn't use the data
@@ -915,7 +915,7 @@ UUDecodeFile (uulist *thefile, char *destname)
/*
* Determine the name of the target file according to the rules:
- *
+ *
* IF (destname!=NULL) THEN filename=destname;
* ELSE
* filename = thefile->filename
@@ -1068,7 +1068,7 @@ UUInfoFile (uulist *thefile, void *opaque,
*/
if (uu_FileCallback) {
- if ((res = (*uu_FileCallback) (uu_FileCBArg,
+ if ((res = (*uu_FileCallback) (uu_FileCBArg,
thefile->thisfile->data->sfname,
uugen_fnbuffer,
1)) != UURET_OK)
@@ -1085,7 +1085,7 @@ UUInfoFile (uulist *thefile, void *opaque,
else {
if ((inpfile = fopen (thefile->thisfile->data->sfname, "rb")) == NULL) {
UUMessage (uulib_id, __LINE__, UUMSG_ERROR,
- uustring (S_NOT_OPEN_FILE),
+ uustring (S_NOT_OPEN_FILE),
thefile->thisfile->data->sfname,
strerror (uu_errno=errno));
return UURET_IOERR;
@@ -1100,7 +1100,7 @@ UUInfoFile (uulist *thefile, void *opaque,
fseek (inpfile, thefile->thisfile->data->startpos, SEEK_SET);
maxpos = thefile->thisfile->data->startpos + thefile->thisfile->data->length;
- while (!feof (inpfile) &&
+ while (!feof (inpfile) &&
(uu_fast_scanning || ftell(inpfile) < maxpos)) {
if (_FP_fgets (uugen_inbuffer, 511, inpfile) == NULL)
break;
@@ -1136,7 +1136,7 @@ UUInfoFile (uulist *thefile, void *opaque,
fclose (inpfile);
if (uu_FileCallback)
- (*uu_FileCallback) (uu_FileCBArg,
+ (*uu_FileCallback) (uu_FileCBArg,
thefile->thisfile->data->sfname,
uugen_fnbuffer, 0);
@@ -1145,7 +1145,7 @@ UUInfoFile (uulist *thefile, void *opaque,
return UURET_OK;
}
-
+
int UUEXPORT
UURenameFile (uulist *thefile, char *newname)
{
@@ -1262,10 +1262,10 @@ UUCleanUp (void)
* clean up the malloc'ed stuff
*/
- for (aiter=toallocate; aiter->ptr; aiter++) {
- _FP_free (*(aiter->ptr));
- *(aiter->ptr) = NULL;
- }
+// for (aiter=toallocate; aiter->ptr; aiter++) {
+// _FP_free (*(aiter->ptr));
+// *(aiter->ptr) = NULL;
+// }
return UURET_OK;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]