in separate msgview Enter key opens currently selected msg master
authorpaul <paul@claws-mail.org>
Fri, 3 Dec 2021 15:01:01 +0000 (15:01 +0000)
committerPaul <paul@claws-mail.org>
Fri, 3 Dec 2021 15:03:40 +0000 (15:03 +0000)
also modify when to automatically show the next msg or not when moving/deleting current msg

146 files changed:
configure.ac
src/Makefile.am
src/addrcache.c
src/addrclip.c
src/addrduplicates.c
src/addressbook.c
src/addritem.c
src/addrquery.c
src/addrselect.c
src/common/file-utils.h
src/common/mgutils.c
src/common/passcrypt.c
src/common/pkcs5_pbkdf2.c
src/common/progressindicator.c
src/common/proxy.h
src/common/quoted-printable.c
src/common/socket.c
src/common/socket.h
src/common/stringtable.c
src/common/template.c
src/common/tests/codeconv_test.c
src/common/tests/md5_test.c
src/common/tests/pkcs5_pbkdf2_test.c
src/common/tests/unmime_test.c
src/common/tests/utils_get_serverportfp_from_filename_test.c
src/common/tests/utils_get_uri_part_test.c
src/common/tests/xml_test.c
src/common/utils.c
src/common/utils.h
src/common/uuencode.c
src/common/w32_reg.c
src/compose.c
src/compose.h
src/etpan/etpan-ssl.h
src/etpan/imap-thread.c
src/filtering.c
src/foldersel.c
src/folderutils.c
src/folderview.c
src/gtk/colorlabel.c
src/gtk/foldersort.c
src/gtk/gtksctree.c
src/gtk/inputdialog.c
src/gtk/manage_window.c
src/ldif.c
src/localfolder.c
src/main.c
src/mainwindow.c
src/messageview.c
src/mimeview.c
src/mimeview.h
src/mutt.c
src/password.h
src/password_gtk.h
src/pine.c
src/plugins/demo/demo.c
src/plugins/libravatar/libravatar_cache.c
src/plugins/libravatar/libravatar_federation.c
src/plugins/libravatar/libravatar_missing.c
src/plugins/litehtml_viewer/lh_viewer.c
src/plugins/litehtml_viewer/lh_widget_text.cpp
src/plugins/mailmbox/carray.c
src/plugins/mailmbox/chash.c
src/plugins/mailmbox/clist.c
src/plugins/mailmbox/mailimf_types.c
src/plugins/mailmbox/mailimf_types_helper.c
src/plugins/mailmbox/maillock.c
src/plugins/mailmbox/mailmbox_parse.c
src/plugins/mailmbox/mailmbox_types.c
src/plugins/mailmbox/mmapstring.c
src/plugins/managesieve/managesieve.c
src/plugins/managesieve/sieve_plugin.c
src/plugins/newmail/newmail.c
src/plugins/notification/gtkhotkey/gtk-hotkey-error.c
src/plugins/notification/gtkhotkey/gtk-hotkey-info.c
src/plugins/notification/gtkhotkey/gtk-hotkey-key-file-registry.c
src/plugins/notification/gtkhotkey/gtk-hotkey-listener.c
src/plugins/notification/gtkhotkey/gtk-hotkey-marshal.c
src/plugins/notification/gtkhotkey/gtk-hotkey-registry.c
src/plugins/notification/gtkhotkey/gtk-hotkey-utils.c
src/plugins/notification/gtkhotkey/gtk-hotkey-x11-listener.c
src/plugins/notification/gtkhotkey/x11/eggaccelerators.c
src/plugins/notification/gtkhotkey/x11/tomboykeybinder.c
src/plugins/notification/notification_banner.h
src/plugins/notification/notification_command.h
src/plugins/notification/notification_foldercheck.h
src/plugins/notification/notification_hotkeys.h
src/plugins/notification/notification_indicator.h
src/plugins/notification/notification_lcdproc.h
src/plugins/notification/notification_pixbuf.c
src/plugins/notification/notification_plugin.c
src/plugins/notification/notification_plugin.h
src/plugins/notification/notification_popup.h
src/plugins/notification/notification_prefs.h
src/plugins/notification/notification_trayicon.h
src/plugins/pdf_viewer/poppler_viewer.h
src/plugins/pgpcore/claws.def
src/plugins/pgpcore/pgp_viewer.c
src/plugins/pgpcore/plugin.def
src/plugins/pgpcore/sgpgme.c
src/plugins/pgpcore/sgpgme.h
src/plugins/pgpcore/tests/pgp_utils_test.c
src/plugins/pgpinline/claws.def
src/plugins/pgpinline/pgpinline.c
src/plugins/pgpinline/plugin.c
src/plugins/pgpmime/claws.def
src/plugins/pgpmime/mypgpcore.def
src/plugins/pgpmime/pgpmime.c
src/plugins/pgpmime/plugin.c
src/plugins/python/clawsmailmodule.c
src/plugins/python/python-shell.c
src/plugins/rssyl/libfeed/date.c
src/plugins/rssyl/libfeed/feed.c
src/plugins/rssyl/libfeed/feeditem.c
src/plugins/rssyl/libfeed/feeditemenclosure.c
src/plugins/rssyl/libfeed/parser_atom10.c
src/plugins/rssyl/libfeed/parser_opml.c
src/plugins/rssyl/libfeed/parser_rdf.c
src/plugins/rssyl/libfeed/parser_rss20.c
src/plugins/rssyl/libfeed/tests/date_test.c
src/plugins/rssyl/libfeed/tests/feed_test.c
src/plugins/rssyl/old_feeds.c
src/plugins/rssyl/tests/strutils_test.c
src/plugins/smime/claws.def
src/plugins/smime/mypgpcore.def
src/plugins/smime/plugin.c
src/plugins/smime/smime.c
src/plugins/spamassassin/utils.c
src/plugins/vcalendar/claws.def
src/plugins/vcalendar/vcal_folder.c
src/prefs_account.c
src/prefs_common.h
src/prefs_matcher.c
src/prefs_proxy.c
src/prefs_template.c
src/privacy.c
src/privacy.h
src/procmime.c
src/procmime.h
src/procmsg.c
src/remotefolder.c
src/sourcewindow.c
src/summaryview.c
src/summaryview.h
src/tests/entity_test.c
src/textview.c

index facf5d70002a55c0df7c8a8a421b0c4b195b5597..5127dfefd333ddf55c9bb8e4da53f3a766d4e77e 100644 (file)
@@ -90,6 +90,7 @@ AC_CONFIG_HEADERS(config.h)
 AC_CONFIG_HEADERS(claws-features.h)
 
 AM_MAINTAINER_MODE
+AC_GNU_SOURCE
 
 dnl Checks for programs.
 dnl AC_ARG_PROGRAM
@@ -175,22 +176,29 @@ AC_MSG_RESULT([$env_cygwin])
 AM_CONDITIONAL(CYGWIN, test x"$env_cygwin" = x"yes")
 
 AC_MSG_CHECKING([for time_t format specifier])
-case "$host" in
-  x86_64-w64-mingw32)
-    time_t_fmt=lld
-    ;;
-  *)
-    time_t_fmt=ld
-    ;;
-esac
+_gcc_cflags_save=$CFLAGS
+CFLAGS="-Wall -Werror"
+AC_COMPILE_IFELSE([
+       AC_LANG_PROGRAM([[
+               #include <stdio.h>
+               #include <time.h>
+               ]],[[printf("%lld", time(NULL));]])],
+       [time_t_long_long=yes],
+       [time_t_long_long=no])
+CFLAGS=$_gcc_cflags_save
+
+if test x"$time_t_long_long" = xyes; then
+       time_t_fmt=lld
+else
+       time_t_fmt=ld
+fi
 AC_MSG_RESULT([$time_t_fmt])
 AC_DEFINE_UNQUOTED([CM_TIME_FORMAT], ["$time_t_fmt"],
        [Define printf format specifier for time_t])
 
-if test "$GCC" = "yes"
-then
-       CFLAGS="$CFLAGS -Wno-unused-function"
-       #CFLAGS="-g -Wall -Wno-unused-function"
+AM_CFLAGS="-Wall"
+if test $USE_MAINTAINER_MODE = yes; then
+       AM_CFLAGS="$AM_CFLAGS -g"
 fi
 
 AC_MSG_CHECKING([if gcc supports -Wno-pointer-sign])
@@ -200,34 +208,30 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],_gcc_psign=yes,_gcc_psign=no)
 AC_MSG_RESULT($_gcc_psign)
 CFLAGS=$_gcc_cflags_save;
 if test x"$_gcc_psign" = xyes ; then
-       CFLAGS="$CFLAGS -Wno-pointer-sign"
-fi
-
-CFLAGS="$CFLAGS -Wall -D_GNU_SOURCE"
-
-if test $USE_MAINTAINER_MODE = yes; then
-       CFLAGS="$CFLAGS -g -Wno-pointer-sign -DUSE_MAINTAINER_MODE"
+       AM_CFLAGS="$AM_CFLAGS -Wno-pointer-sign"
 fi
 
 pthread_name=
 case "$target" in
 *-darwin*)
-       CFLAGS="$CFLAGS -no-cpp-precomp -fno-common"
+       AM_CFLAGS="$AM_CFLAGS -no-cpp-precomp -fno-common"
        ;;
 *-*-mingw*)
-        # Note that we need to link to pthread in all cases. This
-        # is because some locking is used even when pthread support is
-        # disabled.
-        pthread_name=pthread
-       CFLAGS="$CFLAGS -mms-bitfields"
+       # Note that we need to link to pthread in all cases. This
+       # is because some locking is used even when pthread support is
+       # disabled.
+       pthread_name=pthread
+       AM_CFLAGS="$AM_CFLAGS -mms-bitfields"
        LIBS="$LIBS -l${pthread_name} -lws2_32 -lregex"
        ;;
 *-*-solaris*)
-       CPPFLAGS="$CPPFLAGS -D_POSIX_PTHREAD_SEMANTICS"
-       CFLAGS="$CFLAGS -std=gnu99 -DSOLARIS"
+       AM_CFLAGS="$AM_CFLAGS -std=gnu99"
+       AC_DEFINE([SOLARIS], [], [Target is Solaris])
        ;;
 esac
 
+AC_SUBST(AM_CFLAGS)
+
 dnl Checks for iconv
 AM_ICONV
 
@@ -466,7 +470,7 @@ dnl ** common code **
 dnl *****************
 
 dnl check for glib
-PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.28 gmodule-2.0 >= 2.28 gobject-2.0 >= 2.28 gthread-2.0 >= 2.28])
+PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.36 gmodule-2.0 >= 2.36 gobject-2.0 >= 2.36 gthread-2.0 >= 2.36])
 
 GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0`
 AC_SUBST(GLIB_GENMARSHAL)
@@ -958,7 +962,7 @@ if test x"$enable_libetpan" = xyes; then
         # before 1.9.4, libetpan uses its own libetpan-config script
         AC_PATH_PROG(libetpanconfig, [libetpan-config])
         if test "x$libetpanconfig" != "x"; then
-            LIBETPAN_CPPFLAGS="`$libetpanconfig --cflags`"
+            LIBETPAN_CFLAGS="`$libetpanconfig --cflags`"
             LIBETPAN_LIBS="`$libetpanconfig --libs`"
             # support libetpan version like x.x and x.x.x
             libetpan_versiontype=`$libetpanconfig --version | tr -dc . | wc -c`
@@ -971,7 +975,6 @@ if test x"$enable_libetpan" = xyes; then
         fi
     ])
     if test "x$libetpan_config" = "xyes"; then
-        CPPFLAGS="$CPPFLAGS $LIBETPAN_FLAGS"
         AC_CHECK_HEADER(libetpan/libetpan.h, [libetpan_result=yes])
         if test "x$libetpan_result" = "xyes"; then
             AC_MSG_CHECKING([whether libetpan-config hints compiles and links fine])
@@ -988,7 +991,7 @@ if test x"$enable_libetpan" = xyes; then
                 AC_MSG_ERROR([libetpan 0.57 not found])
             fi
         fi
-        AC_SUBST(LIBETPAN_FLAGS)
+        AC_SUBST(LIBETPAN_CFLAGS)
         AC_SUBST(LIBETPAN_LIBS)
         AC_DEFINE(HAVE_LIBETPAN, 1, Define if you want IMAP and/or NNTP support.)
     else
index c479bf1222ba79fc3c53389a0a53e6bd958c52fb..3b100ec6464c78f562374bcfff81969fb01521e3 100644 (file)
@@ -630,6 +630,9 @@ AM_CPPFLAGS = \
        $(VALGRIND_CFLAGS) \
        $(CONTACTS_CFLAGS)
 
+matcher_parser_lex.$(OBJEXT) : AM_CFLAGS += -Wno-unused-function
+quote_fmt_lex.$(OBJEXT) : AM_CFLAGS += -Wno-unused-function
+
 #no-unused-function is there because of bison stuff
 #no-deprecated-declarations because of gpgme_data_rewind, which we have
 #to call inside gpgme due to our lack of LARGEFILE support
index 2765b41bb0ae8b081bcd17703c18339c2c256a02..918e226b8074e62d2df571f7115bdd5252d11d08 100644 (file)
@@ -21,6 +21,8 @@
  * Functions to maintain address cache.
  */
 
+#include "config.h"
+
 #include <stdio.h>
 #include <string.h>
 #include <sys/stat.h>
index 58d59477644e8dc3fd98163f6098f2c4dc367cc8..b4160394268c2ff257263f59803e04459cc8e649 100644 (file)
@@ -45,6 +45,8 @@
  * 
  */
 
+#include "config.h"
+
 #include <stdio.h>
 #include <glib.h>
 #include <glib/gi18n.h>
index 06def3d6a2e58e85cbd6d6d6ffab7fb68cbe76b7..02236304fd23ffb1a94f45b5b10b8136f54d1e43 100644 (file)
@@ -272,7 +272,7 @@ static gint collect_emails(ItemPerson *itemperson, AddressDataSource *ds)
                addr = g_utf8_strdown(email->address, -1);
                old_val = g_hash_table_lookup(addr_hash, addr);
                if(old_val)
-                       new_val = slist_copy_deep(old_val, (GCopyFunc)copy_hash_val);
+                       new_val = g_slist_copy_deep(old_val, (GCopyFunc)copy_hash_val, NULL);
                else
                        new_val = NULL;
 
index ede2e4fe3ff8708abd668d730c1439d602e682b4..240cbb21f5e4b2aa0f37702a25fa1130d8479367 100644 (file)
@@ -393,11 +393,6 @@ static GtkTargetEntry addressbook_drag_types[] =
 
 static GtkTargetList *addressbook_target_list = NULL;
 
-static void about_show_cb(GtkAction *action, gpointer data)
-{
-       about_show();
-}
-
 static GtkActionEntry addressbook_entries[] =
 {
        {"Menu",                                NULL, "Menu", NULL, NULL, NULL },
@@ -5798,7 +5793,6 @@ static gboolean addressbook_drag_motion_cb(GtkWidget      *widget,
                                AdapterDSource *ads = NULL;
                                AddressDataSource *ds = NULL;
                                ads = ADAPTER_DSOURCE(obj);
-                               if (ads == NULL ){ return FALSE;}
                                ds = ads->dataSource;
                                if (ds == NULL ) { return FALSE;}
 
index f0c26176acda1d641e427707ebfd9a43f67af538..cfde577966a7b572929466c64f335e886776e419 100644 (file)
@@ -20,6 +20,8 @@
  * General primitive address item objects.
  */
 
+#include "config.h"
+
 #include <glib.h>
 #include <stdio.h>
 #include <string.h>
index 67d1718b0a371d48dedf09d15ba204414ba00751..730e491dc75699d4c4af7e7918a05ca697d96b51 100644 (file)
@@ -21,6 +21,8 @@
  * Functions to define an address query (a request).
  */
 
+#include "config.h"
+
 #include <stdio.h>
 #include <string.h>
 #include <glib.h>
index 8d967cf61f958a57a57f48fe11596f9f2281e287..d4d516f9ca1babaa3352275b3a1ee747df602512 100644 (file)
@@ -21,6 +21,8 @@
  * Address list item selection objects.
  */
 
+#include "config.h"
+
 #include <stdio.h>
 #include <glib.h>
 
index d89b06971e83018bda5fa45a6be82329681d37b5..14bd42360e73378fbb743a2bf08c7692c3dff2b4 100644 (file)
@@ -20,7 +20,6 @@
 #define __CLAWS_IO_H__
 
 #ifdef HAVE_CONFIG_H
-#  include "config.h"
 #include "claws-features.h"
 #endif
 
index 9bdb2b12a356ab7ab5ca319127751c574c9f4b51..e6fdf4d2de277c57382a37e016f09f9feee9411b 100644 (file)
@@ -20,6 +20,8 @@
  * Definitions for generic functions.
  */
 
+#include "config.h"
+
 #include <glib.h>
 #include <stdio.h>
 #include <string.h>
index 5fceb734d93b7c61588cdc57e2d7129412bbd63c..5b3a1dbe86228e6873585ef91ded4a75d4a5c288 100644 (file)
  * 
  */
 
-#if !defined (__FreeBSD__)
-#define _XOPEN_SOURCE 600
-#else
-#define _XOPEN_SOURCE
-#endif
+#include "config.h"
 
 #include <sys/types.h>
 #include <stdio.h>
index 6f83fe50f3bc287a203e5d46d31b0e16d36bb323..4a6fa714db7b7be31b5498589643fc1c15154023 100644 (file)
@@ -17,6 +17,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include "config.h"
+
 #include <glib.h>
 #include <sys/types.h>
 
index e6898e1ec8ccd6af6f403fe28657a847a3865283..1a848384e7182b2bed889a3cc9cd7d9c091dee5e 100644 (file)
@@ -17,6 +17,8 @@
  * 
  */
 
+#include "config.h"
+
 #include <glib.h>
 
 #include "hooks.h"
index 8f527accb30ec3f221bba587ec351254998b1782..7551a5e669d4ea0ec1a04261f38fff673bb5427c 100644 (file)
 #ifndef __PROXY_H__
 #define __PROXY_H__
 
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
 #include <glib.h>
 
 #include "socket.h"
index dd0a6bb594e61b58548e9b5f083b457f02b9fe58..0d265a119775438088d9a7bd37d224813a442bbd 100644 (file)
@@ -17,6 +17,8 @@
  * 
  */
 
+#include "config.h"
+
 #include <glib.h>
 #include <ctype.h>
 
index a26b583406f23781103c350b08e2b89a68b4352c..33dd65cd64c30f8676416e156259a0ea98fe94e6 100644 (file)
 #include "claws-features.h"
 #endif
 
-#if (defined (_XOPEN_SOURCE) && !defined (_BSD_SOURCE))
-#define _BSD_SOURCE
-#endif
-
 /* This can probably be handled better, e.g. define it in config.h. */
 #define _WIN32_WINNT _WIN32_WINNT_WIN6
 #include <glib.h>
@@ -1428,6 +1424,7 @@ gint sock_write_all(SockInfo *sock, const gchar *buf, gint len)
        return ret;
 }
 
+#ifndef G_OS_WIN32
 static gint fd_recv(gint fd, gchar *buf, gint len, gint flags)
 {
        if (fd_check_io(fd, G_IO_IN) < 0)
@@ -1435,6 +1432,7 @@ static gint fd_recv(gint fd, gchar *buf, gint len, gint flags)
 
        return recv(fd, buf, len, flags);
 }
+#endif
 
 gint fd_gets(gint fd, gchar *buf, gint len)
 {
index a1b17e5391cfbfe087e105ad117b0d814651999e..da547d9bc3275021c14477698893b5bef5641f95 100644 (file)
 #include "claws-features.h"
 #endif
 
-#if (defined (_XOPEN_SOURCE) && !defined (_BSD_SOURCE))
-#define _BSD_SOURCE
-#endif
-
 #include <glib.h>
 #if HAVE_NETDB_H
 #  include <netdb.h>
index b0f747ed48f6197f3fae34649578805f9ba345ca..349daf5b394c452c8ba1ad539a2c0ac52c934d36 100644 (file)
@@ -17,6 +17,8 @@
  * 
  */
 
+#include "config.h"
+
 #include <glib.h>
 #include <string.h>
 
index c9180121b69f51245e4f607890987ba920913029..e10132a6cb6e8f360b9e0bf803dd713c006900a9 100644 (file)
@@ -18,6 +18,7 @@
  * 
  */
 
+#include "config.h"
 #include "defs.h"
 
 #include <glib.h>
index 3cf74370c3a9e8fbc61bc9c2da9587cc35eff8c4..2775f69772b2f938484043a3fc6c4fb4fd82553c 100644 (file)
@@ -1,3 +1,5 @@
+#include "config.h"
+
 #include <glib.h>
 
 #include "codeconv.h"
index e78d118f4dcb47b53c5eb9c4294dc92e04d9c8c1..679c14e2f5d89e1442ee035fd11d696f023cf5b1 100644 (file)
@@ -1,3 +1,5 @@
+#include "config.h"
+
 #include <glib.h>
 
 #include <common/md5.h>
index 3f7a451c369f380aa745ca5731f9d2c730695b3d..e4c1b2d06af3964a22f3fdffdaf43543d4e6ce8d 100644 (file)
@@ -1,3 +1,5 @@
+#include "config.h"
+
 #include <glib.h>
 
 #include <common/pkcs5_pbkdf2.h>
index 1f4066035c94286ccb7c04bfb910d5b63b55fc88..05e628780046e3094b1c37e47de17668427fc6e3 100644 (file)
@@ -1,3 +1,5 @@
+#include "config.h"
+
 #include <stdio.h>
 #include <glib.h>
 
index 746aa9fe4b8e6e3933f22bbfc365cf59de455e88..a23bc228bf95416e3e927dab7dd6672864ddcd2c 100644 (file)
@@ -1,3 +1,5 @@
+#include "config.h"
+
 #include <stdio.h>
 #include <glib.h>
 
index 18ab31c2430307093d434e64d754e60f17bb7bf7..ddd9b0f394331890892fe4cb18110e3d7041f557 100644 (file)
@@ -1,3 +1,5 @@
+#include "config.h"
+
 #include <stdio.h>
 #include <glib.h>
 
index 015971202372f5bea0974fe8f27c61ee924a243c..288031fff383b3229bcdcda60d3ea13f1fb34257 100644 (file)
@@ -1,3 +1,5 @@
+#include "config.h"
+
 #include <glib.h>
 
 #include "xml.h"
index 0631f2afe3e843fd876435e1cbd5e08f3e9ea96f..5b6f1b98d29cf3eb98fbe41644d9f477ea5d1d0a 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2020 The Claws Mail Team and Hiroyuki Yamamoto
+ * Copyright (C) 1999-2021 The Claws Mail Team and Hiroyuki Yamamoto
  *
  * 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
 
 static gboolean debug_mode = FALSE;
 
-GSList *slist_copy_deep(GSList *list, GCopyFunc func)
-{
-#if GLIB_CHECK_VERSION(2, 34, 0)
-       return g_slist_copy_deep(list, func, NULL);
-#else
-       GSList *res = g_slist_copy(list);
-       GSList *walk = res;
-       while (walk) {
-               walk->data = func(walk->data, NULL);
-               walk = walk->next;
-       }
-       return res;
-#endif
-}
-
 void list_free_strings_full(GList *list)
 {
        g_list_free_full(list, (GDestroyNotify)g_free);
@@ -299,6 +284,21 @@ gchar *strcrchomp(gchar *str)
        return str;
 }
 
+/* truncates string at first CR (carriage return) or LF (line feed) */
+gchar *strcrlftrunc(gchar *str)
+{
+       gchar *p = NULL;
+
+       if ((str == NULL) || (!*str)) return str;
+
+       if ((p = strstr(str, "\r")) != NULL)
+               *p = '\0';
+       if ((p = strstr(str, "\n")) != NULL)
+               *p = '\0';
+
+       return str;
+}
+
 #ifndef HAVE_STRCASESTR
 /* Similar to `strstr' but this function ignores the case of both strings.  */
 gchar *strcasestr(const gchar *haystack, const gchar *needle)
@@ -2695,6 +2695,7 @@ FILE *get_command_output_stream(const char* cmdline)
        return fdopen(fd, "r");
 }
 
+#ifndef G_OS_WIN32
 static gint is_unchanged_uri_char(char c)
 {
        switch (c) {
@@ -2730,6 +2731,7 @@ static void encode_uri(gchar *encoded_uri, gint bufsize, const gchar *uri)
        }
        encoded_uri[k] = 0;
 }
+#endif
 
 gint open_uri(const gchar *uri, const gchar *cmdline)
 {
@@ -3492,19 +3494,6 @@ void g_auto_pointer_free(GAuto *auto_ptr)
        g_free(ptr);
 }
 
-void replace_returns(gchar *str)
-{
-       if (!str)
-               return;
-
-       while (strstr(str, "\n")) {
-               *strstr(str, "\n") = ' ';
-       }
-       while (strstr(str, "\r")) {
-               *strstr(str, "\r") = ' ';
-       }
-}
-
 /* get_uri_part() - retrieves a URI starting from scanpos.
                    Returns TRUE if successful */
 gboolean get_uri_part(const gchar *start, const gchar *scanpos,
@@ -4456,25 +4445,6 @@ size_t fast_strftime(gchar *buf, gint buflen, const gchar *format, struct tm *lt
 #define WEXITSTATUS(x) (x)
 #endif
 
-GMutex *cm_mutex_new(void) {
-#if GLIB_CHECK_VERSION(2,32,0)
-       GMutex *m = g_new0(GMutex, 1);
-       g_mutex_init(m);
-       return m;
-#else
-       return g_mutex_new();
-#endif
-}
-
-void cm_mutex_free(GMutex *mutex) {
-#if GLIB_CHECK_VERSION(2,32,0)
-       g_mutex_clear(mutex);
-       g_free(mutex);
-#else
-       g_mutex_free(mutex);
-#endif
-}
-
 static gchar *canonical_list_to_file(GSList *list)
 {
        GString *result = g_string_new(NULL);
@@ -4664,40 +4634,6 @@ guchar *g_base64_decode_zero(const gchar *text, gsize *out_len)
        return out;
 }
 
-#if !GLIB_CHECK_VERSION(2, 30, 0)
-/**
- * g_utf8_substring:
- * @str: a UTF-8 encoded string
- * @start_pos: a character offset within @str
- * @end_pos: another character offset within @str
- *
- * Copies a substring out of a UTF-8 encoded string.
- * The substring will contain @end_pos - @start_pos
- * characters.
- *
- * Returns: a newly allocated copy of the requested
- *     substring. Free with g_free() when no longer needed.
- *
- * Since: GLIB 2.30
- */
-gchar *
-g_utf8_substring (const gchar *str,
-                                 glong            start_pos,
-                                 glong            end_pos)
-{
-  gchar *start, *end, *out;
-
-  start = g_utf8_offset_to_pointer (str, start_pos);
-  end = g_utf8_offset_to_pointer (start, end_pos - start_pos);
-
-  out = g_malloc (end - start + 1);
-  memcpy (out, start, end - start);
-  out[end - start] = 0;
-
-  return out;
-}
-#endif
-
 /* Attempts to read count bytes from a PRNG into memory area starting at buf.
  * It is up to the caller to make sure there is at least count bytes
  * available at buf. */
index 4b1b422193a1c9fc546b4c03ad4de7a57f2b0d6a..1010aa87cef4e062166fe9994a09d48dd5dd3301 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2020 The Claws Mail Team and Hiroyuki Yamamoto
+ * Copyright (C) 1999-2021 The Claws Mail Team and Hiroyuki Yamamoto
  *
  * 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
@@ -25,7 +25,6 @@
 
 #ifdef HAVE_CONFIG_H
 #include "claws-features.h"
-#include "config.h"
 #endif
 
 #ifdef HAVE_BACKTRACE
@@ -248,11 +247,6 @@ gboolean debug_get_mode            (void);
 #define Str(x) #x
 #define Xstr(x)        Str(x)
 
-/* List utilities. */
-
-GSList *slist_copy_deep                (GSList         *list,
-                                GCopyFunc       func);
-
 /* String utilities.  */
 
 void list_free_strings_full            (GList          *list);
@@ -278,6 +272,7 @@ gchar *strretchomp  (gchar          *str);
 gchar *strtailchomp    (gchar          *str,
                         gchar           tail_char);
 gchar *strcrchomp      (gchar          *str);
+gchar *strcrlftrunc    (gchar *str);
 #ifndef HAVE_STRCASESTR
 gchar *strcasestr      (const gchar    *haystack,
                         const gchar    *needle);
@@ -502,7 +497,6 @@ GAuto *g_auto_pointer_new_with_free (gpointer p,
 gpointer g_auto_pointer_get_ptr                (GAuto *auto_ptr);
 GAuto *g_auto_pointer_copy             (GAuto *auto_ptr);
 void g_auto_pointer_free               (GAuto *auto_ptr);
-void replace_returns                   (gchar *str);
 gboolean get_uri_part  (const gchar *start,
                         const gchar *scanpos,
                         const gchar **bp,
@@ -529,19 +523,10 @@ gboolean file_is_email(const gchar *filename);
 gboolean sc_g_list_bigger(GList *list, gint max);
 gboolean sc_g_slist_bigger(GSList *list, gint max);
 
-GMutex *cm_mutex_new(void);
-void cm_mutex_free(GMutex *mutex);
-
 int cm_canonicalize_filename(const gchar *filename, gchar **canonical_name);
 
 guchar *g_base64_decode_zero(const gchar *text, gsize *out_len);
 
-#if !GLIB_CHECK_VERSION(2, 30, 0)
-gchar   *g_utf8_substring         (const gchar *p,
-                                   glong        start_pos,
-                                   glong        end_pos) G_GNUC_MALLOC;
-#endif
-
 gboolean get_random_bytes(void *buf, size_t count);
 
 #ifdef __cplusplus
index 0e5c82cc0d0545900daf09cea6539cfebd0a74c1..99af96148f32b78b1e44118e950c0123ddb77178 100644 (file)
@@ -17,6 +17,8 @@
  * 
  */
 
+#include "config.h"
+
 #include <ctype.h>
 
 #define UUDECODE(c) (c=='`' ? 0 : c - ' ')
index 05568ff7f7b69af3ce62c8158c36013d3143039a..0cf3bbfc9aca2a13f782953c4f8a6ef1ec4840ff 100644 (file)
@@ -16,6 +16,8 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "config.h"
+
 #include "w32_reg.h"
 #include "utils.h"
 
index 94ef486961dbe3eddd84fe70bbd9fdd9d1bb9766..2c90fb85b053adbc60ccda2471170137f69daf80 100644 (file)
@@ -7818,7 +7818,7 @@ static Compose *compose_create(PrefsAccount *account,
        compose->account = account;
        compose->folder = folder;
        
-       compose->mutex = cm_mutex_new();
+       g_mutex_init(&compose->mutex);
        compose->set_cursor_pos = -1;
 
        window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "compose");
@@ -9242,7 +9242,7 @@ static void compose_destroy(Compose *compose)
        gtk_widget_destroy(compose->window);
        toolbar_destroy(compose->toolbar);
        g_free(compose->toolbar);
-       cm_mutex_free(compose->mutex);
+       g_mutex_clear(&compose->mutex);
        g_free(compose);
 }
 
@@ -10320,7 +10320,7 @@ gboolean compose_draft (gpointer data, guint action)
        draft = account_get_special_folder(compose->account, F_DRAFT);
        cm_return_val_if_fail(draft != NULL, FALSE);
        
-       if (!g_mutex_trylock(compose->mutex)) {
+       if (!g_mutex_trylock(&compose->mutex)) {
                /* we don't want to lock the mutex once it's available,
                 * because as the only other part of compose.c locking
                 * it is compose_close - which means once unlocked,
@@ -10461,12 +10461,12 @@ warn_err:
                                          FALSE, NULL, ALERT_QUESTION);
                                if (val == G_ALERTALTERNATE) {
                                        lock = FALSE;
-                                       g_mutex_unlock(compose->mutex); /* must be done before closing */
+                                       g_mutex_unlock(&compose->mutex); /* must be done before closing */
                                        compose_close(compose);
                                        return TRUE;
                                } else {
                                        lock = FALSE;
-                                       g_mutex_unlock(compose->mutex); /* must be done before closing */
+                                       g_mutex_unlock(&compose->mutex); /* must be done before closing */
                                        return FALSE;
                                }
                        }
@@ -10501,7 +10501,7 @@ warn_err:
        
        if (action == COMPOSE_QUIT_EDITING || action == COMPOSE_DRAFT_FOR_EXIT) {
                lock = FALSE;
-               g_mutex_unlock(compose->mutex); /* must be done before closing */
+               g_mutex_unlock(&compose->mutex); /* must be done before closing */
                compose_close(compose);
                return TRUE;
        } else {
@@ -10567,7 +10567,7 @@ warn_err:
        }
 unlock:
        lock = FALSE;
-       g_mutex_unlock(compose->mutex);
+       g_mutex_unlock(&compose->mutex);
        return TRUE;
 }
 
@@ -10744,7 +10744,7 @@ static void compose_close_cb(GtkAction *action, gpointer data)
 
        if (compose->modified) {
                gboolean reedit = (compose->rmode == COMPOSE_REEDIT);
-               if (!g_mutex_trylock(compose->mutex)) {
+               if (!g_mutex_trylock(&compose->mutex)) {
                        /* we don't want to lock the mutex once it's available,
                         * because as the only other part of compose.c locking
                         * it is compose_close - which means once unlocked,
@@ -10763,7 +10763,7 @@ static void compose_close_cb(GtkAction *action, gpointer data)
                                 _("_Don't save"), _("_Save to Drafts"), GTK_STOCK_CANCEL,
                                 ALERTFOCUS_SECOND);
                }
-               g_mutex_unlock(compose->mutex);
+               g_mutex_unlock(&compose->mutex);
                switch (val) {
                case G_ALERTDEFAULT:
                        if (compose_can_autosave(compose) && !reedit)
@@ -12128,7 +12128,7 @@ gboolean compose_close(Compose *compose)
 
        cm_return_val_if_fail(compose, FALSE);
 
-       if (!g_mutex_trylock(compose->mutex)) {
+       if (!g_mutex_trylock(&compose->mutex)) {
                /* we have to wait for the (possibly deferred by auto-save)
                 * drafting to be done, before destroying the compose under
                 * it. */
@@ -12152,7 +12152,7 @@ gboolean compose_close(Compose *compose)
                prefs_common.compose_x = x;
                prefs_common.compose_y = y;
        }
-       g_mutex_unlock(compose->mutex);
+       g_mutex_unlock(&compose->mutex);
        compose_destroy(compose);
        return FALSE;
 }
index 3c155be556c514a5ea72661498af64e15cff9ebb..7b7fb0154a5a833f2291b0ba7dc6aff6bd4f7fe5 100644 (file)
@@ -244,7 +244,7 @@ struct _Compose
        GtkTextTag *uri_tag;
 
        gboolean automatic_break;
-       GMutex *mutex;
+       GMutex mutex;
        gint close_timeout_tag;
        gchar *orig_charset;
        gint set_cursor_pos;
index adb8f9d92b8a846aa0d846d8f07f3fe7b46b9f0a..81da3d55969e540f014fa58981c5ecc2bf947d22 100644 (file)
@@ -22,7 +22,6 @@
 #define __ETPAN_SSL_H__
 
 #ifdef HAVE_CONFIG_H
-#  include "config.h"
 #include "claws-features.h"
 #endif
 
index 252863ab3ab685a99ae8383e26e9cc5229312966..0c4ad1dc2d726a5c5998faf9df82ca0826036788 100644 (file)
@@ -3377,15 +3377,11 @@ int imap_threaded_store(Folder * folder, struct mailimap_set * set,
 }
 
 
-#define ENV_BUFFER_SIZE 512
 #ifndef G_OS_WIN32
 static void do_exec_command(int fd, const char * command,
                            const char * servername, uint16_t port)
 {
        int i, maxopen;
-#ifdef SOLARIS
-       char env_buffer[ENV_BUFFER_SIZE];
-#endif
        
        if (fork() > 0) {
                /* Fork again to become a child of init rather than
index 46cfd238b894add05f92781e7d983cc18a1c445c..8006915e647bc43dea58824cfb8ac7a125c34f5c 100644 (file)
@@ -16,6 +16,7 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "config.h"
 #include "defs.h"
 #include <glib.h>
 #include <glib/gi18n.h>
index 42d33ef91b9e135a343e4c860b74f75aba6db1d2..1973bc3a698b8488fd0a829bc555ab5e61e249a5 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2020 the Claws Mail team and Hiroyuki Yamamoto
+ * Copyright (C) 1999-2021 the Claws Mail team and Hiroyuki Yamamoto
  *
  * 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
@@ -16,6 +16,7 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "config.h"
 #include "defs.h"
 
 #include <glib.h>
@@ -108,9 +109,6 @@ static void foldersel_cancel                (GtkButton      *button,
 static void foldersel_new_folder       (GtkButton      *button,
                                         gpointer        data);
 
-static void foldersel_entry_activated  (GtkEntry       *entry,
-                                        gpointer        data);
-
 static void foldersel_tree_activated   (GtkTreeView            *treeview,
                                         GtkTreePath            *path,
                                         GtkTreeViewColumn      *column,
@@ -345,8 +343,6 @@ static void foldersel_create(const gchar *title)
        statusbar_cid = gtk_statusbar_get_context_id(
                        GTK_STATUSBAR(statusbar), "Select Folder Dialog" );
        gtk_box_pack_start(GTK_BOX(vbox), statusbar, FALSE, FALSE, 0);
-       g_signal_connect(G_OBJECT(statusbar), "activate",
-                        G_CALLBACK(foldersel_entry_activated), NULL);
 
        gtkut_stock_button_set_create(&confirm_area,
                                      &new_button,    GTK_STOCK_NEW,
@@ -633,11 +629,6 @@ static void foldersel_new_folder(GtkButton *button, gpointer data)
        folder_write_list();
 }
 
-static void foldersel_entry_activated(GtkEntry *entry, gpointer data)
-{
-       gtk_button_clicked(GTK_BUTTON(ok_button));
-}
-
 static void foldersel_tree_activated(GtkTreeView *treeview, GtkTreePath *path,
                                     GtkTreeViewColumn *column, gpointer data)
 {
index 650e2a1c652ff6d8ef5932bb7bf5e708516965a7..4ff6133be6c3ce6bc140ac55fd6e2899ea981ef5 100644 (file)
@@ -17,6 +17,8 @@
  * 
  */
 
+#include "config.h"
+
 #include <glib.h>
 
 #include "utils.h"
index 3f4058e10fd3e0a0a51e8afee7c90592273f1ec5..c080c3e485e265c190f300cc1be17a4eeada5405 100644 (file)
@@ -16,6 +16,7 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "config.h"
 #include "defs.h"
 
 #include <glib.h>
index 2703096e7d702998ae63ddcbd50389a1daa0e441..fb49bfc7c535add89deab996424158935b2ec896 100644 (file)
@@ -22,6 +22,7 @@
  * file is just that it make it easier to allow "user changeable" label colors.
  */
 
+#include "config.h"
 #include "defs.h"
 
 #include <glib.h>
index 45b2c07db2447d87bc7de07eab4ab06ea7040dbd..7238684b9ae32a14a36036b96792edcd64c5ac89 100644 (file)
@@ -17,6 +17,7 @@
  * 
  */
 
+#include "config.h"
 #include "defs.h"
 
 #include <glib.h>
index 101d0916da41dae7b8ef6cb02c43a81d80db27de..5bd835d4e1501a51522afafb9286b15ffc5e7e6f 100644 (file)
@@ -26,6 +26,8 @@
  * 
  */
 
+#include "config.h"
+
 #include <stdlib.h>
 
 #include "gtksctree.h"
index 6953e60b6e202a13f7c0e2291df7bbb5425e10b5..2bad05b37a99cef8768fc932a5e16282a773aef3 100644 (file)
@@ -321,7 +321,7 @@ static void input_dialog_create(gboolean is_password)
        gtk_box_pack_start (GTK_BOX (hbox), icon_p, FALSE, FALSE, 0);
        
        vbox = gtk_vbox_new (FALSE, 12);
-       gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
+       gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 16);
        gtk_widget_show (vbox);
        
        msg_title = gtk_label_new("");
index 47f786ae6dab40218f154dd83f692f3f2f7228c6..68aede5a2924d087c5148faf83a51fc3038497e6 100644 (file)
@@ -17,6 +17,8 @@
  * 
  */
 
+#include "config.h"
+
 #include <glib.h>
 #include <gtk/gtk.h>
 
index 6f686590f7017b79269ccf38513aef1ab7ad4137..d2147d95e7181a05f127eb17b4560370b1d78e24 100644 (file)
@@ -21,6 +21,8 @@
  * files).
  */
 
+#include "config.h"
+
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <string.h>
index 0d2ffb769e47113eb4c5c4f78d739c9bf341e8b9..7cce203bfc2af4c98a31241304299460b5634a61 100644 (file)
@@ -17,6 +17,8 @@
  * 
  */
 
+#include "config.h"
+
 #include <glib.h>
 
 #include "folder.h"
index fab75e8df3ec0c1f40f2743b6e79c9ac9c3ade0e..b074ba145250ac9c8762b27b59f2eeee0d078b38 100644 (file)
@@ -230,7 +230,9 @@ static void open_compose_new                (const gchar    *address,
 
 static void send_queue                 (void);
 static void initial_processing         (FolderItem *item, gpointer data);
+#ifndef G_OS_WIN32
 static void quit_signal_handler         (int sig);
+#endif
 static void install_basic_sighandlers   (void);
 #if (defined linux && defined SIGIO)
 static void install_memory_sighandler   (void);
@@ -724,13 +726,6 @@ static void win32_print_stdout(const gchar *string)
        }
 }
 
-static void win32_print_stderr(const gchar *string)
-{
-       if (win32_debug_log) {
-               win32_log_WriteFile(string);
-       }
-}
-
 GLogWriterOutput win32_log_writer(GLogLevelFlags log_level, const GLogField *fields, gsize n_fields, gpointer user_data)
 {
        gchar *formatted;
@@ -1136,10 +1131,6 @@ int main(int argc, char *argv[])
        
        if (cmd.exit)
                return 0;
-#if !GLIB_CHECK_VERSION(2,32,0)
-       if (!g_thread_supported())
-               g_thread_init(NULL);
-#endif
 
        reset_statistics();
        
@@ -1199,12 +1190,6 @@ int main(int argc, char *argv[])
        /* Create container for all the menus we will be adding */
        MENUITEM_ADDUI("/", "Menus", NULL, GTK_UI_MANAGER_MENUBAR);
 
-#if !GLIB_CHECK_VERSION(2,32,0)
-       if (!g_thread_supported()) {
-               g_error("g_thread is not supported by glib");
-       }
-#endif
-
 #ifdef G_OS_WIN32
        CHDIR_EXEC_CODE_RETURN_VAL_IF_FAIL(get_home_dir(), 1, win32_close_log(););
 #else
@@ -2946,12 +2931,14 @@ static void send_queue(void)
        }
 }
 
+#ifndef G_OS_WIN32
 static void quit_signal_handler(int sig)
 {
        debug_print("Quitting on signal %d\n", sig);
 
        g_timeout_add(0, clean_quit, NULL);
 }
+#endif
 
 static void install_basic_sighandlers()
 {
index 2b3511f00f0e8d89c16cf171c7d7084cdfb3c9f5..695826b09290b621fc9b735598ba353af1bcf3db 100644 (file)
@@ -16,6 +16,7 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "config.h"
 #include "defs.h"
 
 #ifdef G_OS_WIN32
@@ -5480,7 +5481,6 @@ void mainwindow_learn (MainWindow *mainwin, gboolean is_spam)
 void mainwindow_jump_to(const gchar *target, gboolean popup)
 {
        gchar *tmp = NULL;
-       gchar *p = NULL;
        FolderItem *item = NULL;
        gchar *msg = NULL;
        MainWindow *mainwin = mainwindow_get_mainwindow();
@@ -5497,11 +5497,8 @@ void mainwindow_jump_to(const gchar *target, gboolean popup)
                tmp = from_uri;
        else
                tmp = g_strdup(target);
-       
-       if ((p = strstr(tmp, "\r")) != NULL)
-               *p = '\0';
-       if ((p = strstr(tmp, "\n")) != NULL)
-               *p = '\0';
+
+       strcrlftrunc(tmp);
 
        if ((item = folder_find_item_from_identifier(tmp))) {
                g_print("selecting folder '%s'\n", tmp);
index a8a45573387a4d6173ce69a1c2f68f86e54bfbec..44253b706360d76d23dfa6bd8de4aa05b8097f73 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2016 Hiroyuki Yamamoto and the Claws Mail team
+ * Copyright (C) 1999-2021 the Claws Mail team and Hiroyuki Yamamoto
  *
  * 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
@@ -16,6 +16,7 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "config.h"
 #include "defs.h"
 
 #include <glib.h>
@@ -1854,6 +1855,13 @@ static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event,
        if (event && (event->state & GDK_SHIFT_MASK) && event->keyval != GDK_KEY_space) 
                return FALSE;
 
+       if (event && (event->keyval == GDK_KEY_KP_Enter || event->keyval ==  GDK_KEY_Return) &&
+           messageview->window) {
+               MsgInfo *new_msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
+               messageview_show(messageview, new_msginfo, messageview->all_headers);
+               return FALSE;
+       }
+
        return mimeview_pass_key_press_event(messageview->mimeview, event);
 }
 
@@ -2943,8 +2951,7 @@ static gboolean messageview_update_msg(gpointer source, gpointer data)
                return FALSE;
 
        if ((msginfo_update->flags & MSGINFO_UPDATE_DELETED) ||
-           MSG_IS_DELETED(old_msginfo->flags))
-       {
+           MSG_IS_DELETED(old_msginfo->flags)) {
                if (messageview->new_window) {
                        if (old_msginfo->folder && old_msginfo->folder->total_msgs == 0) {
                                messageview_clear(messageview);
@@ -2953,20 +2960,19 @@ static gboolean messageview_update_msg(gpointer source, gpointer data)
                                return FALSE;
                        }
                        
-                       if (!prefs_common.always_show_msg) {
-                               messageview_clear(messageview);
-                               textview_show_info(messageview->mimeview->textview,
-                                       MSG_IS_DELETED(old_msginfo->flags) ?
-                                       _("\n  Message has been deleted") :
-                                       _("\n  Message has been deleted or moved to another folder"));
+                       if (!OPEN_SELECTED_ON_DELETEMOVE && !OPEN_SELECTED_ON_PREVNEXT) {
+                               messageview_clear(messageview);
+                               textview_show_info(messageview->mimeview->textview,
+                                       MSG_IS_DELETED(old_msginfo->flags) ?
+                                       _("\n  Message has been deleted") :
+                                       _("\n  Message has been deleted or moved to another folder"));
                        } else
                                messageview->update_needed = TRUE;
-
                } else {
                        messageview_clear(messageview);
                        messageview_update(messageview, old_msginfo);
                }
-       } 
+       }
 
        return FALSE;
 }
index 24b89495f80a800d593d51a7a6a195f65416bb59..451e8c1696a9859764e73d4fd9eacab99f4497eb 100644 (file)
@@ -549,26 +549,11 @@ void mimeview_show_message(MimeView *mimeview, MimeInfo *mimeinfo,
                                          mimeview_selected, mimeview);
 }
 
-#ifdef USE_PTHREAD
-static void mimeview_check_sig_cancel_now(MimeView *mimeview);
-#endif
-
 static void mimeview_free_mimeinfo(MimeView *mimeview)
 {
-       gboolean defer = FALSE;
-#ifdef USE_PTHREAD
-       defer = (mimeview->check_data != NULL);
-       if (defer)
-               mimeview->check_data->free_after_use = TRUE;
-#endif
-       if (mimeview->mimeinfo != NULL && !defer) {
+       if (mimeview->mimeinfo != NULL) {
                procmime_mimeinfo_free_all(&mimeview->mimeinfo);
                mimeview->mimeinfo = NULL;
-       } else if (defer) {
-#ifdef USE_PTHREAD
-               debug_print("deferring free(mimeinfo) and cancelling check\n");
-               mimeview_check_sig_cancel_now(mimeview);
-#endif
        }
 }
 
@@ -583,20 +568,19 @@ void mimeview_destroy(MimeView *mimeview)
        g_slist_free(mimeview->viewers);
        gtk_target_list_unref(mimeview->target_list);
 
-#ifdef USE_PTHREAD
-       if (mimeview->check_data) {
-               mimeview->check_data->destroy_mimeview = TRUE;
-               debug_print("deferring destroy\n");
-       } else 
-#endif
-       {
-               mimeview_free_mimeinfo(mimeview);
-               gtk_tree_path_free(mimeview->opened);
-               g_free(mimeview->file);
-               g_free(mimeview);
-               mimeviews = g_slist_remove(mimeviews, mimeview);
+       if (mimeview->sig_check_timeout_tag != 0)
+               g_source_remove(mimeview->sig_check_timeout_tag);
+       if (mimeview->sig_check_cancellable != NULL) {
+               /* Set last_sig_check_task to NULL to discard results in async_cb */
+               mimeview->siginfo->last_sig_check_task = NULL;
+               g_cancellable_cancel(mimeview->sig_check_cancellable);
+               g_object_unref(mimeview->sig_check_cancellable);
        }
-       
+       mimeview_free_mimeinfo(mimeview);
+       gtk_tree_path_free(mimeview->opened);
+       g_free(mimeview->file);
+       g_free(mimeview);
+       mimeviews = g_slist_remove(mimeviews, mimeview);
 }
 
 MimeInfo *mimeview_get_selected_part(MimeView *mimeview)
@@ -990,6 +974,19 @@ void mimeview_clear(MimeView *mimeview)
        if (g_slist_find(mimeviews, mimeview) == NULL)
                return;
        
+       if (mimeview->sig_check_timeout_tag != 0) {
+               g_source_remove(mimeview->sig_check_timeout_tag);
+               mimeview->sig_check_timeout_tag = 0;
+       }
+
+       if (mimeview->sig_check_cancellable != NULL) {
+               /* Set last_sig_check_task to NULL to discard results in async_cb */
+               mimeview->siginfo->last_sig_check_task = NULL;
+               g_cancellable_cancel(mimeview->sig_check_cancellable);
+               g_object_unref(mimeview->sig_check_cancellable);
+               mimeview->sig_check_cancellable = NULL;
+       }
+
        noticeview_hide(mimeview->siginfoview);
 
        model = gtk_tree_view_get_model(GTK_TREE_VIEW(mimeview->ctree));
@@ -1027,21 +1024,20 @@ gchar * get_message_check_signature_shortcut(MessageView *messageview) {
 static void check_signature_cb(GtkWidget *widget, gpointer user_data);
 static void display_full_info_cb(GtkWidget *widget, gpointer user_data);
 
-static void update_signature_noticeview(MimeView *mimeview, MimeInfo *mimeinfo, 
-                                       gboolean special, SignatureStatus code)
+static void update_signature_noticeview(MimeView *mimeview, gboolean special, SignatureStatus code)
 {
        gchar *text = NULL, *button_text = NULL;
        void  *func = NULL;
        StockPixmap icon = STOCK_PIXMAP_PRIVACY_SIGNED;
        SignatureStatus mycode = SIGNATURE_UNCHECKED;
        
-       cm_return_if_fail(mimeview != NULL);
-       cm_return_if_fail(mimeinfo != NULL);
-       
+       if (mimeview == NULL || mimeview->siginfo == NULL)
+               g_error("bad call to update noticeview");
+
        if (special)
                mycode = code;
-       else 
-               mycode = privacy_mimeinfo_get_sig_status(mimeinfo);
+       else
+               mycode = privacy_mimeinfo_get_sig_status(mimeview->siginfo);
 
        switch (mycode) {
        case SIGNATURE_UNCHECKED:
@@ -1069,6 +1065,7 @@ static void update_signature_noticeview(MimeView *mimeview, MimeInfo *mimeinfo,
                func = display_full_info_cb;
                icon = STOCK_PIXMAP_PRIVACY_FAILED;
                break;
+       case SIGNATURE_CHECK_ERROR:
        case SIGNATURE_CHECK_FAILED:
        case SIGNATURE_CHECK_TIMEOUT:
                button_text = _("Check again");
@@ -1078,19 +1075,17 @@ static void update_signature_noticeview(MimeView *mimeview, MimeInfo *mimeinfo,
        default:
                break;
        }
+
        if (mycode == SIGNATURE_UNCHECKED) {
-               gchar *tmp = privacy_mimeinfo_sig_info_short(mimeinfo);
+               gchar *tmp = privacy_mimeinfo_get_sig_info(mimeview->siginfo, FALSE);
                gchar *shortcut = get_message_check_signature_shortcut(mimeview->messageview);
 
                if (*shortcut == '\0')
                        text = g_strdup_printf(_("%s Click the icon to check it."), tmp);
                else
-                       text = g_strdup_printf(_("%s Click the icon or hit '%s' to check it."),
-                               tmp, shortcut);
-               g_free(tmp);
+                       text = g_strdup_printf(_("%s Click the icon or hit '%s' to check it."), tmp, shortcut);
+
                g_free(shortcut);
-       } else if (mycode != SIGNATURE_CHECK_TIMEOUT) {
-               text = privacy_mimeinfo_sig_info_short(mimeinfo);
        } else if (mycode == SIGNATURE_CHECK_TIMEOUT) {
                gchar *shortcut = get_message_check_signature_shortcut(mimeview->messageview);
 
@@ -1098,13 +1093,25 @@ static void update_signature_noticeview(MimeView *mimeview, MimeInfo *mimeinfo,
                        text = g_strdup(_("Timeout checking the signature. Click the icon to try again."));
                else
                        text = g_strdup_printf(_("Timeout checking the signature. Click the icon or hit '%s' to try again."), shortcut);
+
+               g_free(shortcut);
+       } else if (mycode == SIGNATURE_CHECK_ERROR) {
+               gchar *shortcut = get_message_check_signature_shortcut(mimeview->messageview);
+
+               if (*shortcut == '\0')
+                       text = g_strdup(_("Error checking the signature. Click the icon to try again."));
+               else
+                       text = g_strdup_printf(_("Error checking the signature. Click the icon or hit '%s' to try again."), shortcut);
+
                g_free(shortcut);
+       } else {
+               text = g_strdup(privacy_mimeinfo_get_sig_info(mimeview->siginfo, FALSE));
        }
 
        noticeview_set_text(mimeview->siginfoview, text);
        gtk_label_set_selectable(GTK_LABEL(mimeview->siginfoview->text), TRUE);
-
        g_free(text);
+
        noticeview_set_button_text(mimeview->siginfoview, NULL);
        noticeview_set_button_press_callback(
                mimeview->siginfoview,
@@ -1117,242 +1124,130 @@ static void update_signature_noticeview(MimeView *mimeview, MimeInfo *mimeinfo,
        icon_list_create(mimeview, mimeview->mimeinfo);
 }
 
-#ifdef USE_PTHREAD
-
-/* reset all thread stuff, and do the cleanups we've been left to do */
-static void mimeview_check_data_reset(MimeView *mimeview)
+static void check_signature_async_cb(GObject *source_object,
+       GAsyncResult *async_result,
+       gpointer user_data)
 {
-       gboolean must_free;
-       gboolean must_destroy;
+       GTask *task = G_TASK(async_result);
+       GCancellable *cancellable;
+       MimeView *mimeview = (MimeView *)user_data;
+       gboolean cancelled;
+       SigCheckTaskResult *result;
+       GError *error = NULL;
 
-       if (!mimeview->check_data)
+       if (mimeview->siginfo == NULL) {
+               debug_print("discarding stale sig check task result task:%p\n", task);
                return;
-
-       must_free = mimeview->check_data->free_after_use;
-       must_destroy = mimeview->check_data->destroy_mimeview;
-       
-       if (mimeview->check_data->cancel_th_init) {
-               debug_print("killing canceller thread\n");
-               mimeview->check_data->cancel_th_init = FALSE;
-               pthread_cancel(mimeview->check_data->cancel_th);
-       }
-
-       if (must_free) {
-               debug_print("freeing deferred mimeinfo\n");
-               procmime_mimeinfo_free_all(&mimeview->check_data->siginfo);
+       } else if (task != mimeview->siginfo->last_sig_check_task) {
+               debug_print("discarding stale sig check task result last_task:%p task:%p\n",
+                       mimeview->siginfo->last_sig_check_task, task);
+               return;
+       } else {
+               debug_print("using sig check task result task:%p\n", task);
+               mimeview->siginfo->last_sig_check_task = NULL;
        }
 
-       g_free(mimeview->check_data);
-       mimeview->check_data = NULL;
+       cancellable = g_task_get_cancellable(task);
+       cancelled = g_cancellable_set_error_if_cancelled(cancellable, &error);
+       if (cancelled) {
+               debug_print("sig check task was cancelled: task:%p GError: domain:%s code:%d message:\"%s\"\n",
+                       task, g_quark_to_string(error->domain), error->code, error->message);
+               g_error_free(error);
+               update_signature_noticeview(mimeview, TRUE, SIGNATURE_CHECK_TIMEOUT);
+               return;
+       } else {
+               if (mimeview->sig_check_cancellable == NULL)
+                       g_error("bad cancellable");
+               if (mimeview->sig_check_timeout_tag == 0)
+                       g_error("bad cancel source tag");
 
-       if (must_destroy) {
-               debug_print("freeing deferred mimeview\n");
-               mimeview_free_mimeinfo(mimeview);
-               gtk_tree_path_free(mimeview->opened);
-               g_free(mimeview->file);
-               g_free(mimeview);
-               mimeviews = g_slist_remove(mimeviews, mimeview);
+               g_source_remove(mimeview->sig_check_timeout_tag);
+               mimeview->sig_check_timeout_tag = 0;
+               g_object_unref(mimeview->sig_check_cancellable);
+               mimeview->sig_check_cancellable = NULL;
        }
-}
 
-/* GUI update once the checker thread is done or killed */
-static gboolean mimeview_check_sig_thread_cb(void *data)
-{
-       MimeView *mimeview = (MimeView *) data;
-       MimeInfo *mimeinfo = mimeview->siginfo;
+       result = g_task_propagate_pointer(task, &error);
 
-       debug_print("mimeview_check_sig_thread_cb\n");
-       
-       if (mimeinfo == NULL) {
-               /* message changed !? */
-               g_warning("no more siginfo!");
-               goto end;
-       }
-       
-       if (!mimeview->check_data) {
-               g_warning("nothing to check");
-               return FALSE;
+       if (mimeview->siginfo->sig_data) {
+               privacy_free_signature_data(mimeview->siginfo->sig_data);
+               mimeview->siginfo->sig_data = NULL;
        }
 
-       if (mimeview->check_data->siginfo != mimeinfo) {
-               /* message changed !? */
-               g_warning("different siginfo!");
-               goto end;
-       }
-
-       if (mimeview->check_data->destroy_mimeview ||
-           mimeview->check_data->free_after_use) {
-               debug_print("not bothering, we're changing message\n"); 
-               goto end;
+       if (result == NULL) {
+               debug_print("sig check task propagated NULL task:%p GError: domain:%s code:%d message:\"%s\"\n",
+                       task, g_quark_to_string(error->domain), error->code, error->message);
+               g_error_free(error);
+               update_signature_noticeview(mimeview, TRUE, SIGNATURE_CHECK_ERROR);
+               return;
        }
-       
-       /* update status */
-       if (mimeview->check_data->timeout) 
-               update_signature_noticeview(mimeview, mimeview->siginfo, 
-                       TRUE, SIGNATURE_CHECK_TIMEOUT);
-       else
-               update_signature_noticeview(mimeview, mimeview->siginfo, 
-                       FALSE, 0);
 
-end:
-       mimeview_check_data_reset(mimeview);
-       return FALSE;
-}
+       mimeview->siginfo->sig_data = result->sig_data;
+       update_signature_noticeview(mimeview, FALSE, 0);
 
-/* sig checker thread */
-static void *mimeview_check_sig_worker_thread(void *data)
-{
-       MimeView *mimeview = (MimeView *)data;
-       MimeInfo *mimeinfo = mimeview->siginfo;
-       
-       debug_print("checking...\n");
-
-       if (!mimeview->check_data)
-               return NULL;
-
-       if (mimeinfo && mimeinfo == mimeview->check_data->siginfo) {
-               privacy_mimeinfo_check_signature(mimeinfo);
-               if (mimeview->check_data && mimeview->check_data->cancel_th_init) {
-                       mimeview->check_data->cancel_th_init = FALSE;
-                       pthread_cancel(mimeview->check_data->cancel_th);
-               }
-       } else {
-               /* that's strange! we changed message without 
-                * getting killed. */
-               g_warning("different siginfo!");
-               mimeview_check_data_reset(mimeview);
-               return NULL;
+       if (result->newinfo) {
+               g_warning("Check sig task returned an unexpected new MimeInfo");
+               procmime_mimeinfo_free_all(&result->newinfo);
        }
 
-       /* use g_timeout so that GUI updates is done from the
-        * correct thread */
-       g_timeout_add(0,mimeview_check_sig_thread_cb,mimeview);
-       
-       return NULL;
+       g_free(result);
 }
 
-/* killer thread - acts when the checker didn't work fast
- * enough. */
-static void *mimeview_check_sig_cancel_thread(void *data)
+gboolean mimeview_check_sig_timeout(gpointer user_data)
 {
-       MimeView *mimeview = (MimeView *)data;
-       
-       if (!mimeview->check_data)
-               return NULL; /* nothing to kill ! */
+       MimeView *mimeview = (MimeView *)user_data;
+       GCancellable *cancellable = mimeview->sig_check_cancellable;
 
-       /* wait for a few seconds... */
-       debug_print("waiting a while\n");
+       mimeview->sig_check_timeout_tag = 0;
 
-       g_usleep(5 * 1000 * 1000);
-       
-       if (!mimeview->check_data)
-               return NULL; /* nothing to kill, it's done in time :) */
-       
-       /* too late, go away checker thread */
-       debug_print("killing checker thread\n");
-       if (mimeview->check_data->th_init) {
-               mimeview->check_data->th_init = FALSE;
-               pthread_cancel(mimeview->check_data->th);
+       if (cancellable == NULL) {
+               return G_SOURCE_REMOVE;
        }
 
-       /* tell upstream it was a timeout */
-       mimeview->check_data->timeout = TRUE;
-       /* use g_timeout so that GUI updates is done from the
-        * correct thread */
-       g_timeout_add(0,mimeview_check_sig_thread_cb,mimeview);
+       mimeview->sig_check_cancellable = NULL;
+       g_cancellable_cancel(cancellable);
+       g_object_unref(cancellable);
 
-       return NULL;
+       return G_SOURCE_REMOVE;
 }
 
-/* get rid of the checker thread right now - used when changing the
- * displayed message for example. */
-static void mimeview_check_sig_cancel_now(MimeView *mimeview)
-{
-       if (!mimeview->check_data)
-               return;
-       debug_print("killing checker thread NOW\n");
-       if (mimeview->check_data->th_init) {
-               mimeview->check_data->th_init = FALSE;
-               pthread_cancel(mimeview->check_data->th);
-       }
-
-       /* tell upstream it was a timeout */
-       mimeview->check_data->timeout = TRUE;
-       mimeview_check_sig_thread_cb(mimeview);
-       return;
-}
-
-/* creates a thread to check the signature, and a second one
- * to kill the first one after a timeout */
-static void mimeview_check_sig_in_thread(MimeView *mimeview)
-{
-       pthread_t th, th2;
-       pthread_attr_t detach, detach2;
-       
-       if (mimeview->check_data) {
-               g_warning("already checking it");
-               return;
-       }
-       
-       mimeview->check_data = g_new0(SigCheckData, 1);
-       mimeview->check_data->siginfo = mimeview->siginfo;
-       debug_print("creating thread\n");
-
-       /* init thread attributes and create the checker thread */
-       if (pthread_attr_init(&detach) != 0 ||
-           pthread_attr_setdetachstate(&detach, PTHREAD_CREATE_DETACHED) != 0 ||
-           pthread_attr_init(&detach2) != 0 ||
-           pthread_attr_setdetachstate(&detach2, PTHREAD_CREATE_DETACHED) != 0 ||
-           pthread_create(&th, &detach, 
-                       mimeview_check_sig_worker_thread, 
-                       mimeview) != 0) {
-               /* arh. We'll do it synchronously. */
-               g_warning("can't create checked thread");
-               g_free(mimeview->check_data);
-               mimeview->check_data = NULL;
-               return;
-       } else {
-               mimeview->check_data->th = th;
-               mimeview->check_data->th_init = TRUE;
-       }
-
-       /* create the killer thread */
-       if (pthread_create(&th2, &detach2, 
-                       mimeview_check_sig_cancel_thread, 
-                       mimeview) != 0) {
-               g_warning("can't create killer thread");
-               g_free(mimeview->check_data);
-               mimeview->check_data = NULL;
-               return;
-       } else {
-               mimeview->check_data->cancel_th = th2;
-               mimeview->check_data->cancel_th_init = TRUE;
-       }
-}
-#endif
-
 static void check_signature_cb(GtkWidget *widget, gpointer user_data)
 {
        MimeView *mimeview = (MimeView *) user_data;
        MimeInfo *mimeinfo = mimeview->siginfo;
+       gint ret;
        
        if (mimeinfo == NULL || !noticeview_is_visible(mimeview->siginfoview))
                return;
-#ifdef USE_PTHREAD
-       if (mimeview->check_data)
-               return;
-#endif
+
        noticeview_set_text(mimeview->siginfoview, _("Checking signature..."));
        GTK_EVENTS_FLUSH();
-#ifdef USE_PTHREAD
-       /* let's do it non-blocking */
-       mimeview_check_sig_in_thread(mimeview);
-       if (!mimeview->check_data) /* let's check syncronously */
-#endif
-       {
-               debug_print("checking without thread\n");
-               privacy_mimeinfo_check_signature(mimeinfo);
-               update_signature_noticeview(mimeview, mimeview->siginfo, FALSE, 0);
+
+       if (mimeview->sig_check_cancellable != NULL) {
+               if (mimeview->sig_check_timeout_tag == 0)
+                       g_error("bad cancel source tag");
+               g_source_remove(mimeview->sig_check_timeout_tag);
+               g_cancellable_cancel(mimeview->sig_check_cancellable);
+               g_object_unref(mimeview->sig_check_cancellable);
+       }
+
+       mimeview->sig_check_cancellable = g_cancellable_new();
+
+       ret = privacy_mimeinfo_check_signature(mimeview->siginfo,
+               mimeview->sig_check_cancellable,
+               check_signature_async_cb,
+               mimeview);
+       if (ret == 0) {
+               mimeview->sig_check_timeout_tag = g_timeout_add_seconds(prefs_common.io_timeout_secs,
+                       mimeview_check_sig_timeout, mimeview);
+       } else if (ret < 0) {
+               g_object_unref(mimeview->sig_check_cancellable);
+               mimeview->sig_check_cancellable = NULL;
+               update_signature_noticeview(mimeview, TRUE, SIGNATURE_CHECK_ERROR);
+       } else {
+               g_object_unref(mimeview->sig_check_cancellable);
+               mimeview->sig_check_cancellable = NULL;
+               update_signature_noticeview(mimeview, FALSE, 0);
        }
 }
 
@@ -1373,11 +1268,8 @@ static void redisplay_email(GtkWidget *widget, gpointer user_data)
 static void display_full_info_cb(GtkWidget *widget, gpointer user_data)
 {
        MimeView *mimeview = (MimeView *) user_data;
-       gchar *siginfo;
 
-       siginfo = privacy_mimeinfo_sig_info_full(mimeview->siginfo);
-       textview_set_text(mimeview->textview, siginfo);
-       g_free(siginfo);
+       textview_set_text(mimeview->textview, privacy_mimeinfo_get_sig_info(mimeview->siginfo, TRUE));
        noticeview_set_button_text(mimeview->siginfoview, NULL);
        noticeview_set_button_press_callback(
                mimeview->siginfoview,
@@ -1426,7 +1318,7 @@ static void update_signature_info(MimeView *mimeview, MimeInfo *selected)
                return;
        }
        
-       update_signature_noticeview(mimeview, siginfo, FALSE, 0);
+       update_signature_noticeview(mimeview, FALSE, 0);
        noticeview_show(mimeview->siginfoview);
 }
 
@@ -2615,6 +2507,7 @@ static void icon_list_append_icon (MimeView *mimeview, MimeInfo *mimeinfo)
        if (siginfo != NULL) {
                switch (privacy_mimeinfo_get_sig_status(siginfo)) {
                case SIGNATURE_UNCHECKED:
+               case SIGNATURE_CHECK_ERROR:
                case SIGNATURE_CHECK_FAILED:
                case SIGNATURE_CHECK_TIMEOUT:
                        pixmap = stock_pixmap_widget_with_overlay(stockp,
@@ -2634,7 +2527,7 @@ static void icon_list_append_icon (MimeView *mimeview, MimeInfo *mimeinfo)
                            STOCK_PIXMAP_PRIVACY_EMBLEM_FAILED, OVERLAY_BOTTOM_RIGHT, 6, 3);
                        break;
                }
-               sigshort = privacy_mimeinfo_sig_info_short(siginfo);
+               sigshort = privacy_mimeinfo_get_sig_info(siginfo, FALSE);
        } else if (encrypted != NULL) {
                        pixmap = stock_pixmap_widget_with_overlay(stockp,
                            STOCK_PIXMAP_PRIVACY_EMBLEM_ENCRYPTED, OVERLAY_BOTTOM_RIGHT, 6, 3);         
@@ -2684,7 +2577,6 @@ static void icon_list_append_icon (MimeView *mimeview, MimeInfo *mimeinfo)
                g_free(sigshort_escaped);
                tip = tiptmp;
        }
-       g_free(sigshort);
 
        gtk_widget_set_tooltip_markup(button, tip);
        g_free(tip);
index 2f87b8c3acb521f23043969ea10c335afce3f797..a804cedd386bf0ac27756cd177034ec2a605dbb4 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2012 Hiroyuki Yamamoto and the Claws Mail team
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2021 the Claws Mail team and Hiroyuki Yamamoto
  *
  * 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
@@ -26,9 +26,6 @@ typedef struct _MimeViewer            MimeViewer;
 #include <glib.h>
 #include <gdk/gdk.h>
 #include <gtk/gtk.h>
-#ifdef USE_PTHREAD
-#include <pthread.h>
-#endif
 
 #include "textview.h"
 #include "messageview.h"
@@ -41,22 +38,6 @@ typedef enum
        MIMEVIEW_VIEWER
 } MimeViewType;
 
-#ifdef USE_PTHREAD
-typedef struct _SigCheckData SigCheckData;
-struct _SigCheckData
-{
-       pthread_t th;
-       pthread_t cancel_th;
-       gboolean th_init;
-       gboolean cancel_th_init;
-
-       MimeInfo *siginfo;
-       gboolean free_after_use;
-       gboolean destroy_mimeview;
-       gboolean timeout;
-};
-#endif
-
 struct _MimeView
 {
        GtkWidget *hbox;
@@ -100,9 +81,8 @@ struct _MimeView
        GtkActionGroup *action_group;
        gboolean signed_part;
 
-#ifdef USE_PTHREAD
-       SigCheckData *check_data;
-#endif
+       GCancellable *sig_check_cancellable;
+       guint sig_check_timeout_tag;
 };
 
 struct _MimeViewerFactory
index 0747cf512d62ce79b3cdc8f909878d3e8ac8f8d5..73a0ff3ef41d6dc5516cbdd9cc0c0e831b78954c 100644 (file)
@@ -21,6 +21,8 @@
  * Functions necessary to access MUTT address book file.
  */
 
+#include "config.h"
+
 #include <sys/stat.h>
 #include <ctype.h>
 #include <string.h>
index 4480a5eb6ff3647f59e653bd2e6f3ccb36877f36..19d05b96a5d8363b2e924e56ff3bd977f3f0c439 100644 (file)
 #ifndef __PASSWORD_H
 #define __PASSWORD_H
 
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
 #include <glib.h>
 
 #ifndef PASSWORD_CRYPTO_OLD
index b8a19fbbecbd836e0a7b90f9454ad53f8e8dc6c4..af0fdcf4f8cfa2f14dcd3e73d0a873d5d5c282a0 100644 (file)
 #ifndef __PASSWORD_GTK_H
 #define __PASSWORD_GTK_H
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #ifndef PASSWORD_CRYPTO_OLD
 void master_passphrase_change_dialog();
 #endif
index 1e5df3d6b48f297eee4db789d8d7e81deabada05..ae00b7ad1630b68fc364d020558013cdc5f22bc4 100644 (file)
@@ -21,6 +21,8 @@
  * Functions necessary to access Pine address book file.
  */
 
+#include "config.h"
+
 #include <sys/stat.h>
 #include <glib.h>
 #include <string.h>
index d08807732eedf601065918beb3f8c1d4d1988e54..817c46ef85b6a1c53ed4b2ecd3c55a768f0717f4 100644 (file)
@@ -17,6 +17,8 @@
  * 
  */
 
+#include "config.h"
+
 #include <glib.h>
 #include <glib/gi18n.h>
 
index 22fa9cd735582461881c8109f3d17cf57fbcf6c8..9160e5d83a91df294587101ae82b1afe9b12ee62 100644 (file)
@@ -16,6 +16,8 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "config.h"
+
 #include <sys/stat.h>
 
 #include "libravatar_cache.h"
index 9f8266e108f0ae28b1f53079798c7e6581225941..01734605f4a615e3e5ade43e404665d84551743d 100644 (file)
@@ -16,6 +16,8 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "config.h"
+
 #include <stdio.h>
 
 #include "libravatar_federation.h"
index cc4ae30a663669603518ec60b3b87d14c59a5d30..cc024de9a7927b0f50665ac12272b10f50a8cfe2 100644 (file)
@@ -16,6 +16,8 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "config.h"
+
 #include <stdio.h>
 
 #include "libravatar_missing.h"
index cd9cd693c8dee2917e139c9e166bc2c582f74fef..5951fc0d4257d546332589136164f4e0d5c9a98c 100644 (file)
@@ -43,44 +43,6 @@ static GtkWidget *lh_get_widget(MimeViewer *_viewer)
        return viewer->vbox;
 }
 
-static gchar *get_utf8_string(const gchar *string) {
-        gchar *utf8 = NULL;
-        gsize length;
-        GError *error = NULL;
-        gchar *locale = NULL;
-
-       if (!g_utf8_validate(string, -1, NULL)) {
-               const gchar *cur_locale = conv_get_current_locale();
-               gchar* split = g_strstr_len(cur_locale, -1, ".");
-               if (split) {
-                   locale = ++split;
-               } else {
-                   locale = (gchar *) cur_locale;
-               }
-               debug_print("Try converting to UTF-8 from %s\n", locale);
-               if (g_ascii_strcasecmp("utf-8", locale) != 0) {
-                   utf8 = g_convert(string, -1, "utf-8", locale, NULL, &length, &error);
-                   if (error) {
-                           debug_print("Failed convertion to current locale: %s\n", error->message);
-                           g_clear_error(&error);
-                       }
-           }
-           if (!utf8) {
-               debug_print("Use iso-8859-1 as last resort\n");
-                       utf8 = g_convert(string, -1, "utf-8", "iso-8859-1", NULL, &length, &error);
-                       if (error) {
-                               debug_print("Charset detection failed. Use text as is\n");
-                               utf8 = g_strdup(string);
-                               g_clear_error(&error);
-                       }
-               }
-       } else {
-               utf8 = g_strdup(string);
-       }
-
-       return utf8;
-}
-
 static void lh_show_mimepart(MimeViewer *_viewer, const gchar *infile,
                MimeInfo *partinfo)
 {
@@ -132,6 +94,7 @@ static void lh_destroy_viewer(MimeViewer *_viewer)
        g_free(viewer);
 }
 
+/*
 static void lh_print_viewer (MimeViewer *_viewer)
 {
     debug_print("LH: print_viewer\n");
@@ -139,7 +102,7 @@ static void lh_print_viewer (MimeViewer *_viewer)
     LHViewer* viewer = (LHViewer *) _viewer;
     lh_widget_print(viewer->widget);    
 }
-
+*/
 
 static gboolean lh_scroll_page(MimeViewer *_viewer, gboolean up)
 {
index a832700fca774f1a018efdad092a3a0d409e0982..f6161a05e229cd2e67fe76285e2cbfde4a4e6aeb 100644 (file)
@@ -17,6 +17,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
+#include "config.h"
+
 #include <glib.h>
 
 #include "litehtml/litehtml.h"
index a8e78c9812324a0f2214c39966635207fb72c837..eb6963f1e557076a9df1b665b1c5f2fc5ba19b3d 100644 (file)
@@ -37,6 +37,8 @@
  * $Id$
  */
 
+#include "config.h"
+
 #include <stdlib.h>
 #include <string.h>
 #include "carray.h"
index 20552211bc60b92ab05c99b03cd124d1810269cc..89cff8906b49175b152d9ae93a8a425ff5ec9c28 100644 (file)
@@ -37,6 +37,8 @@
  * $Id$
  */
 
+#include "config.h"
+
 #include <stdlib.h>
 #include <string.h>
 
index e5c680dfb7a93982945b0e3720254b5cb426477e..5c8151abafb914adbeec23866c26dca297630189 100644 (file)
@@ -37,6 +37,8 @@
  * $Id$
  */
 
+#include "config.h"
+
 #include <stdlib.h>
 #include "clist.h"
 
index fbef8f03c0484949af5b558a538b6e017d85d802..31969c084ca96d15b27b5f4bcbd9bd0221e39d99 100644 (file)
@@ -33,6 +33,8 @@
  * $Id$
  */
 
+#include "config.h"
+
 #include "mailimf_types.h"
 #include "mmapstring.h"
 #include <stdlib.h>
index eadb043bd38535be12f0c8fee6dc529cca090554..202dbe22aa3c1ae98dc05e868457be046527c42d 100644 (file)
@@ -29,6 +29,8 @@
  * SUCH DAMAGE.
  */
 
+#include "config.h"
+
 #include "mailimf_types_helper.h"
 
 #include <stdlib.h>
index 5c6e704d1785f810bfe83dd5b4d27fb835501067..300bebd76d3317bc26ba41d3ec7b7a35e5b425a2 100644 (file)
@@ -33,6 +33,8 @@
  * $Id $
  */
 
+#include "config.h"
+
 #include "maillock.h"
 
 #include <sys/types.h>
index ea1dd5862bb738da6a75b496d733755c3b92cbeb..afd964c7df576816f0c27082044003b506af77a5 100644 (file)
@@ -33,6 +33,8 @@
  * $Id$
  */
 
+#include "config.h"
+
 #include "mailmbox_parse.h"
 
 #include "mailmbox.h"
index 8495d8caefe4b75d21c7dec2c9300ba3ead36af9..8da9685012798be8e00071c8d3cde9b687bf57d7 100644 (file)
@@ -29,6 +29,8 @@
  * SUCH DAMAGE.
  */
 
+#include "config.h"
+
 #include "mailmbox_types.h"
 #include "utils.h"
 
index 535e04bcea2166b0b9c63753a1df8d3579852bd1..b4f04ad3ce19114f2f6a133633b68a5945eb9926 100644 (file)
@@ -33,6 +33,8 @@
  * $Id$
  */
 
+#include "config.h"
+
 #include "mmapstring.h"
 
 #include "chash.h"
index a2fb3342986cd43a6d995232753ef3977883d04a..ab0685098ab35f095766d16b49b8471164029dbf 100644 (file)
@@ -18,6 +18,8 @@
  * 
  */
 
+#include "config.h"
+
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <ctype.h>
index 09264fc2c56c2d11f12715dcf0d7768216e8ae1f..aed95615196ac4f03755153d3b3984b30f010aea 100644 (file)
@@ -18,6 +18,8 @@
  * 
  */
 
+#include "config.h"
+
 #include <glib.h>
 #include <glib/gi18n.h>
 
index 87c118000da0ee47833bcd312e4c10763c9cdc95..6616722d10cfbe296770c26f713f3939cace36f0 100644 (file)
@@ -16,6 +16,8 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "config.h"
+
 #include <errno.h>
 
 #include <glib.h>
index 5050c284f5281761b0f6153ba8c9b09cbb2c7b09..0062667c31d53d0859cf48c6d6e58ba304b829cb 100644 (file)
@@ -16,6 +16,8 @@
  *   along with GtkHotkey.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "config.h"
+
 #include "gtk-hotkey-error.h"
 
 GQuark
index 88805f38ee06a56d32f5822f37d30236fa93f14e..80974901ed223c5cd500e5f4993f643562d117e1 100644 (file)
@@ -16,6 +16,8 @@
  *   along with GtkHotkey.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "config.h"
+
 #include "gtk-hotkey-info.h"
 #include "gtk-hotkey-error.h"
 #include "gtk-hotkey-listener.h"
index b9651b2f3ba3e396ed2ad0a1253d20a0c892b558..be1aa9fb382d28ecc48c5bcd0f6df1dd71a61398 100644 (file)
@@ -16,6 +16,8 @@
  *   along with GtkHotkey.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "config.h"
+
 #include "utils.h"
 
 #include "gtk-hotkey-key-file-registry.h"
index 2a08692824b0487ef5b5903a037b671c6541ab48..d145ba3181a857333b5120b8911d5ece169885f3 100644 (file)
@@ -16,6 +16,8 @@
  *   along with GtkHotkey.  If not, see <http://www.gnu.org/licenses/>.
  */
  
+#include "config.h"
+
 #include "gtk-hotkey-listener.h"
 #include "gtk-hotkey-x11-listener.h"
 #include "gtk-hotkey-marshal.h"
index 11bca5c4cf07a09b8ccdd2130276a0e61f241f5e..1327008971f1fb267831a665d005fc55ba5b9314 100644 (file)
@@ -16,6 +16,8 @@
  *   along with GtkHotkey.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "config.h"
+
 #include       <glib-object.h>
 
 
index 150fcb97832c641087b414b300a535381b6f0ca5..badbfe81380d8e42bab7d6afe0082a47a77bf5fa 100644 (file)
@@ -16,6 +16,8 @@
  *   along with GtkHotkey.  If not, see <http://www.gnu.org/licenses/>.
  */
  
+#include "config.h"
+
 #include "gtk-hotkey-registry.h"
 #include "gtk-hotkey-key-file-registry.h"
 
index a1385422329281084e8e7efeb781095edc9ba179..61e79b5c2fc8832706b6580440c9e50af103f2ed 100644 (file)
@@ -16,6 +16,8 @@
  *   along with GtkHotkey.  If not, see <http://www.gnu.org/licenses/>.
  */
  
+#include "config.h"
+
 #include <gio/gio.h>
 
 GFileType
index 16f77d3da9e876f4c93f8769182e732a3b7f75bd..67228a1e1028791f2845658a0c5ae10c6b0169e8 100644 (file)
@@ -16,6 +16,8 @@
  *   along with GtkHotkey.  If not, see <http://www.gnu.org/licenses/>.
  */
  
+#include "config.h"
+
 #include "gtk-hotkey-error.h"
 #include "gtk-hotkey-x11-listener.h"
 #include "gtk-hotkey-listener.h"
index 10e8e52e4e8a6ccdc73991f658326b05837c6df4..4c39353b9a52777e4489e938dc47a9b8db00de9e 100644 (file)
@@ -18,6 +18,8 @@
  * Boston, MA 02111-1307, USA.
  */
 
+#include "config.h"
+
 #include "eggaccelerators.h"
 
 #include <string.h>
index 8dc619fa6b000217733038b40b0918f3ab42a25f..18019bf0b45bbbebf63caaacef9c2f8a23aff9f1 100644 (file)
@@ -1,4 +1,6 @@
 
+#include "config.h"
+
 #include <string.h>
 #include <stdio.h>
 #include <unistd.h>
index 55ab7f622e0416aefdc2ae2bfc087f724cb7957b..659c6ebcd566b53223e22f54e547c54b7a6a59f3 100644 (file)
@@ -19,7 +19,6 @@
 #define NOTIFICATION_BANNER_H NOTIFICATION_BANNER_H
 
 #ifdef HAVE_CONFIG_H
-#  include "config.h"
 #  include "claws-features.h"
 #endif
 
index 8b62566dd68438ac90025b05b686adabe85196b7..fcf8065aaf5edb368568aa7b15955c59d7cb963b 100644 (file)
@@ -19,7 +19,6 @@
 #define NOTIFICATION_COMMAND_H NOTIFICATION_COMMAND_H 
 
 #ifdef HAVE_CONFIG_H
-#  include "config.h"
 #  include "claws-features.h"
 #endif
 
index 361663e641c0692f7bb12c26648a4421efe56174..5d8391b69e108e3e7b75d8676bfb42431ab59240 100644 (file)
@@ -21,7 +21,6 @@
 #include <gtk/gtk.h>
 
 #ifdef HAVE_CONFIG_H
-#  include "config.h"
 #  include "claws-features.h"
 #endif
 
index 5a75e5b923e0d79b43ac0c91b9af1e8fad2ab0c8..e48a9be892c37e5d1e3a8adf73d53df265a3901d 100644 (file)
@@ -19,7 +19,6 @@
 #define NOTIFICATION_HOTKEYS_H NOTIFICATION_HOTKEYS_H
 
 #ifdef HAVE_CONFIG_H
-#  include "config.h"
 #  include "claws-features.h"
 #endif
 
index 95360c02674ba9104b8a604155014a535ff2a6ee..27e733427ed49ef42db0b228a49b82f576a63b5b 100644 (file)
@@ -19,7 +19,6 @@
 #define NOTIFICATION_INDICATOR_H NOTIFICATION_INDICATOR_H
 
 #ifdef HAVE_CONFIG_H
-#  include "config.h"
 #  include "claws-features.h"
 #endif
 
index 71f753ab6fbf33a4c06c6523573817e5e6b27239..7008f8601507d1bdfd14459d4f36a65f46b8f7d7 100644 (file)
@@ -19,7 +19,6 @@
 #define NOTIFICATION_LCDPROC_H NOTIFICATION_LCDPROC_H
 
 #ifdef HAVE_CONFIG_H
-#  include "config.h"
 #  include "claws-features.h"
 #endif
 
index f50d3d159ac7b81ed8bd24657ca3f824438dc04b..1534048176f95ea3805df6288fe2c14660acd7f0 100644 (file)
@@ -15,6 +15,8 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "config.h"
+
 #include "notification_pixbuf.h"
 #include "common/utils.h"
 #include "stock_pixmap.h"
index ef27d39ee734017659afb56b16dcf931db1d4a16..fcd9b85e60bfc33683fb66910065a5784ada6896 100644 (file)
@@ -220,14 +220,6 @@ gint plugin_init(gchar **error)
                           VERSION_NUMERIC, _("Notification"), error))
     return -1;
 
-#if !GLIB_CHECK_VERSION(2,32,0)
-  /* Check if threading is enabled */
-  if(!g_thread_supported()) {
-    *error = g_strdup(_("The Notification plugin needs threading support."));
-    return -1;
-  }
-#endif
-
   hook_f_item = hooks_register_hook(FOLDER_ITEM_UPDATE_HOOKLIST,
                                    my_folder_item_update_hook, NULL);
   if(hook_f_item == 0) {
index 9b42e2c624fb605d91dd87dde0c8efb17b0c9582..4e111d2646ea6d15e79656e5c06ff8015dc36aa5 100644 (file)
@@ -19,7 +19,6 @@
 #define NOTIFICATION_PLUGIN_H NOTIFICATION_PLUGIN_H
 
 #ifdef HAVE_CONFIG_H
-#  include "config.h"
 #  include "claws-features.h"
 #endif
 
index 449e98cb4b8cdbc933190729ce9ed59ac8f69daa..342ebc43910c7f4016b3b1c2143c0b3ac2e2bdf9 100644 (file)
@@ -19,7 +19,6 @@
 #define NOTIFICATION_POPUP_H NOTIFICATION_POPUP_H
 
 #ifdef HAVE_CONFIG_H
-#  include "config.h"
 #  include "claws-features.h"
 #endif
 
index 2234de0a20cb15aa950592bed31e32604e061085..6de3f13153ba2b68f6ccdbeea86e9565a6b079a0 100644 (file)
@@ -19,7 +19,6 @@
 #define NOTIFICATION_PREFS_H NOTIFICATION_PREFS_H
 
 #ifdef HAVE_CONFIG_H
-#  include "config.h"
 #  include "claws-features.h"
 #endif
 
index 65c27310a044767a9393739da3b56a7079d1762a..8e5bb6e59ef9a3b43a2d1a4c2dacef0ac8ae6398 100644 (file)
@@ -19,7 +19,6 @@
 #define NOTIFICATION_TRAYICON_H NOTIFICATION_TRAYICON_H
 
 #ifdef HAVE_CONFIG_H
-#  include "config.h"
 #  include "claws-features.h"
 #endif
 
index af1d97a270d8ed59ff213974526fb0dac55ac7bd..04b0c0f8a6e1e7ea7128cf630e2e8619d1e2a7f0 100644 (file)
 #ifndef POPPLER_VIEWER_H
 #define POPPLER_VIEWER_H
 
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
 //#include <unistd.h>
 #include <stdio.h>
 #include <gtk/gtk.h>
index 87a931d4cdc40d711f99b4f33c998a2ef4a82735..2ded33e41c69f5965bae487733931aeea62298ea 100644 (file)
@@ -60,9 +60,12 @@ prefs_set_block_label
 prefs_set_default
 prefs_write_open
 prefs_write_param
+privacy_free_sig_check_task_result
+privacy_free_signature_data
 privacy_get_error
 privacy_set_error
 procmime_mimeinfo_get_parameter
+procmime_mimeinfo_parent
 procmime_decode_content
 procmime_get_tmp_file_name
 procmime_get_part
index b020b75a5eb62e8221d17fed01e737e8d117e7fc..d39b96a09b0baba6de6a2bbecc132ffb8968554c 100644 (file)
@@ -304,6 +304,7 @@ static void pgpview_show_mime_part(TextView *textview, MimeInfo *partinfo)
 
                TEXTVIEW_INSERT(":\n\n");
                TEXTVIEW_INSERT(_("   This key is in your keyring.\n"));
+               gpgme_key_unref(key);
        }
        gpgme_data_release(sigdata);
        gpgme_release(ctx);
index 1f156d953ac28399540ceba16311ce728d6b5c88..c9803ee18c8eff2047827231800005e6c718ed63 100644 (file)
@@ -1,29 +1,29 @@
 EXPORTS
-        plugin_desc
-        plugin_done
-        plugin_init
-        plugin_licence
-        plugin_name
+       plugin_desc
+       plugin_done
+       plugin_init
+       plugin_licence
+       plugin_name
        plugin_provides
-        plugin_type
-        plugin_version
+       plugin_type
+       plugin_version
 
-        sgpgme_data_from_mimeinfo
+       sgpgme_data_from_mimeinfo
        sgpgme_data_release_and_get_mem
-        sgpgme_decrypt_verify
-        sgpgme_get_encrypt_data
-        sgpgme_setup_signers
-        sgpgme_sigstat_gpgme_to_privacy
-        sgpgme_sigstat_info_full
-        sgpgme_sigstat_info_short
-        sgpgme_verify_signature
+       sgpgme_decrypt_verify
+       sgpgme_get_encrypt_data
+       sgpgme_setup_signers
+       sgpgme_sigstat_gpgme_to_privacy
+       sgpgme_sigstat_info_full
+       sgpgme_sigstat_info_short
+       sgpgme_verify_signature
 
-        gpgmegtk_passphrase_cb
-        prefs_gpg_add_skip_encryption_warning
-        prefs_gpg_enable_agent
-        prefs_gpg_remove_skip_encryption_warning
-        prefs_gpg_should_skip_encryption_warning
-        prefs_gpg_get_config
+       gpgmegtk_passphrase_cb
+       prefs_gpg_add_skip_encryption_warning
+       prefs_gpg_enable_agent
+       prefs_gpg_remove_skip_encryption_warning
+       prefs_gpg_should_skip_encryption_warning
+       prefs_gpg_get_config
 
        cm_gpgme_data_rewind
 
index 150fd9f476673edef50d0c75592a45dbddfc6f9d..3d804210d80de53a1ffcf72e32cfb63a8cb89f16 100644 (file)
@@ -67,6 +67,192 @@ static void sgpgme_disable_all(void)
      * gpgme messages */
 }
 
+void cm_free_detached_sig_task_data(gpointer data)
+{
+       DetachedSigTaskData *task_data = (DetachedSigTaskData *)data;
+
+       g_free(task_data->boundary);
+       g_free(task_data->text_filename);
+       g_free(task_data->sig_filename);
+       g_free(task_data);
+}
+
+void cm_check_detached_sig(GTask *task,
+       gpointer source_object,
+       gpointer _task_data,
+       GCancellable *cancellable)
+{
+       DetachedSigTaskData *task_data = (DetachedSigTaskData *)_task_data;
+       GQuark domain;
+       FILE *fp;
+       gpgme_ctx_t ctx;
+       gpgme_error_t err;
+       gpgme_data_t textdata = NULL;
+       gpgme_data_t sigdata = NULL;
+       gpgme_verify_result_t gpgme_res;
+       gchar *textstr;
+       gboolean return_err = TRUE;
+       gboolean cancelled = FALSE;
+       SigCheckTaskResult *task_result = NULL;
+       char err_str[GPGERR_BUFSIZE] = "";
+
+       domain = g_quark_from_static_string("claws_pgpcore");
+
+       err = gpgme_new(&ctx);
+       if (err != GPG_ERR_NO_ERROR) {
+               gpgme_strerror_r(err, err_str, GPGERR_BUFSIZE);
+               g_warning("couldn't initialize GPG context: %s", err_str);
+               goto out;
+       }
+
+       err = gpgme_set_protocol(ctx, task_data->protocol);
+       if (err != GPG_ERR_NO_ERROR) {
+               gpgme_strerror_r(err, err_str, GPGERR_BUFSIZE);
+               g_warning("couldn't set GPG protocol: %s", err_str);
+               goto out_ctx;
+       }
+
+       fp = claws_fopen(task_data->text_filename, "rb");
+       if (fp == NULL) {
+               err = GPG_ERR_GENERAL;
+               g_snprintf(err_str, GPGERR_BUFSIZE, "claws_fopen failed");
+               goto out_ctx;
+       }
+
+       textstr = task_data->get_canonical_content(fp, task_data->boundary);
+       claws_fclose(fp);
+
+       err = gpgme_data_new_from_mem(&textdata, textstr, textstr?strlen(textstr):0, 0);
+       if (err != GPG_ERR_NO_ERROR) {
+               gpgme_strerror_r(err, err_str, GPGERR_BUFSIZE);
+               g_warning("gpgme_data_new_from_mem failed: %s", err_str);
+               goto out_textstr;
+       }
+
+       fp = claws_fopen(task_data->sig_filename, "rb");
+       if (fp == NULL) {
+               err = GPG_ERR_GENERAL;
+               g_snprintf(err_str, GPGERR_BUFSIZE, "claws_fopen failed");
+               goto out_textdata;
+       }
+
+       err = gpgme_data_new_from_filepart(&sigdata, NULL, fp, task_data->sig_offset, task_data->sig_length);
+       claws_fclose(fp);
+       if (err != GPG_ERR_NO_ERROR) {
+               gpgme_strerror_r(err, err_str, GPGERR_BUFSIZE);
+               g_warning("gpgme_data_new_from_filepart failed: %s", err_str);
+               goto out_textdata;
+       }
+
+       if (task_data->sig_encoding == ENC_BASE64) {
+               err = gpgme_data_set_encoding(sigdata, GPGME_DATA_ENCODING_BASE64);
+               if (err != GPG_ERR_NO_ERROR) {
+                       gpgme_strerror_r(err, err_str, GPGERR_BUFSIZE);
+                       g_warning("gpgme_data_set_encoding failed: %s\n", err_str);
+                       goto out_sigdata;
+               }
+       }
+
+       if (g_task_return_error_if_cancelled(task)) {
+               debug_print("task was cancelled, aborting task:%p\n", task);
+               cancelled = TRUE;
+               goto out_sigdata;
+       }
+
+       err = gpgme_op_verify(ctx, sigdata, textdata, NULL);
+       if (err != GPG_ERR_NO_ERROR) {
+               gpgme_strerror_r(err, err_str, GPGERR_BUFSIZE);
+               g_warning("gpgme_op_verify failed: %s\n", err_str);
+               goto out_sigdata;
+       }
+
+       if (g_task_return_error_if_cancelled(task)) {
+               debug_print("task was cancelled, aborting task:%p\n", task);
+               cancelled = TRUE;
+               goto out_sigdata;
+       }
+
+       gpgme_res = gpgme_op_verify_result(ctx);
+       if (gpgme_res && gpgme_res->signatures == NULL) {
+               err = GPG_ERR_SYSTEM_ERROR;
+               g_warning("no signature found");
+               g_snprintf(err_str, GPGERR_BUFSIZE, "No signature found");
+               goto out_sigdata;
+       }
+
+       task_result = g_new0(SigCheckTaskResult, 1);
+       task_result->sig_data = g_new0(SignatureData, 1);
+
+       task_result->sig_data->status = sgpgme_sigstat_gpgme_to_privacy(ctx, gpgme_res);
+       task_result->sig_data->info_short = sgpgme_sigstat_info_short(ctx, gpgme_res);
+       task_result->sig_data->info_full = sgpgme_sigstat_info_full(ctx, gpgme_res);
+
+       return_err = FALSE;
+
+out_sigdata:
+       gpgme_data_release(sigdata);
+out_textdata:
+       gpgme_data_release(textdata);
+out_textstr:
+       g_free(textstr);
+out_ctx:
+       gpgme_release(ctx);
+out:
+       if (cancelled)
+               return;
+
+       if (return_err)
+               g_task_return_new_error(task, domain, err, "%s", err_str);
+       else
+               g_task_return_pointer(task, task_result, privacy_free_sig_check_task_result);
+}
+
+gint cm_check_detached_sig_async(MimeInfo *mimeinfo,
+       GCancellable *cancellable,
+       GAsyncReadyCallback callback,
+       gpointer user_data,
+       gpgme_protocol_t protocol,
+       gchar *(*get_canonical_content)(FILE *, const gchar *))
+{
+       GTask *task;
+       DetachedSigTaskData *task_data;
+       MimeInfo *parent;
+       MimeInfo *signature;
+       gchar *boundary;
+
+       parent = procmime_mimeinfo_parent(mimeinfo);
+
+       boundary = g_hash_table_lookup(parent->typeparameters, "boundary");
+       if (boundary == NULL) {
+               debug_print("failed to lookup boundary string\n");
+               return -1;
+       }
+
+       signature = (MimeInfo *) mimeinfo->node->next->data;
+
+       task_data = g_new0(DetachedSigTaskData, 1);
+
+       task_data->protocol = protocol;
+       task_data->boundary = g_strdup(boundary);
+       task_data->text_filename = g_strdup(parent->data.filename);
+       task_data->sig_filename = g_strdup(signature->data.filename);
+       task_data->sig_offset = signature->offset;
+       task_data->sig_length = signature->length;
+       task_data->sig_encoding = signature->encoding_type;
+       task_data->get_canonical_content = get_canonical_content;
+
+       task = g_task_new(NULL, cancellable, callback, user_data);
+       mimeinfo->last_sig_check_task = task;
+
+       g_task_set_task_data(task, task_data, cm_free_detached_sig_task_data);
+       debug_print("creating check sig async task:%p task_data:%p\n", task, task_data);
+       g_task_set_return_on_cancel(task, TRUE);
+       g_task_run_in_thread(task, cm_check_detached_sig);
+       g_object_unref(task);
+
+       return 0;
+}
+
 gpgme_verify_result_t sgpgme_verify_signature(gpgme_ctx_t ctx, gpgme_data_t sig, 
                                        gpgme_data_t plain, gpgme_data_t dummy)
 {
@@ -312,7 +498,7 @@ gchar *sgpgme_sigstat_info_short(gpgme_ctx_t ctx, gpgme_verify_result_t status)
        g_free(uname);
 
        if (key)
-               gpgme_key_release(key);
+               gpgme_key_unref(key);
 
        return result;
 }
@@ -338,6 +524,7 @@ gchar *sgpgme_sigstat_info_full(gpgme_ctx_t ctx, gpgme_verify_result_t status)
                struct tm lt;
                gpgme_key_t key;
                gpgme_error_t err;
+               gpgme_user_id_t tmp;
                const gchar *keytype, *keyid, *uid;
                
                err = gpgme_get_key(ctx, sig->fpr, &key, 0);
@@ -398,14 +585,14 @@ gchar *sgpgme_sigstat_info_full(gpgme_ctx_t ctx, gpgme_verify_result_t status)
                if (sig->status != GPG_ERR_BAD_SIGNATURE) {
                        gint j = 1;
                        if (key) {
-                               key->uids = key->uids ? key->uids->next : NULL;
-                               while (key->uids != NULL) {
+                               tmp = key->uids ? key->uids->next : NULL;
+                               while (tmp != NULL) {
                                        g_string_append_printf(siginfo,
                                                _("                    uid \"%s\" (Validity: %s)\n"),
-                                               key->uids->uid,
-                                               key->uids->revoked==TRUE?_("Revoked"):get_validity_str(key->uids->validity));
+                                               tmp->uid,
+                                               tmp->revoked==TRUE?_("Revoked"):get_validity_str(tmp->validity));
                                        j++;
-                                       key->uids = key->uids->next;
+                                       tmp = tmp->next;
                                }
                        }
                        g_string_append_printf(siginfo,_("Owner Trust: %s\n"),
@@ -446,6 +633,7 @@ gchar *sgpgme_sigstat_info_full(gpgme_ctx_t ctx, gpgme_verify_result_t status)
                g_string_append(siginfo, "\n");
                i++;
                sig = sig->next;
+               gpgme_key_unref(key);
        }
 bail:
        ret = siginfo->str;
index 78127f463a2b26afbbce5d4b866037a9f184ef7d..8e494af60d91d9658e2ac12489fdb678f898d6e7 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2012 the Claws Mail team
+ * Copyright (C) 1999-2021 the Claws Mail team
  *
  * 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
 
 #include "privacy.h"
 
+#define GPGERR_BUFSIZE 128
+
+typedef struct _DetachedSigTaskData
+{
+       gpgme_protocol_t protocol;
+       gchar *boundary;
+       gchar *text_filename;
+       gchar *sig_filename;
+       guint sig_offset;
+       guint sig_length;
+       EncodingType sig_encoding;
+       gchar *(*get_canonical_content)(FILE *, const gchar *);
+} DetachedSigTaskData;
+
 void sgpgme_init(void);
 void sgpgme_done(void);
 
+void cm_free_detached_sig_task_data(gpointer data);
+
+void cm_check_detached_sig(GTask *task,
+       gpointer source_object,
+       gpointer _task_data,
+       GCancellable *cancellable);
+
+gint cm_check_detached_sig_async(MimeInfo *mimeinfo,
+       GCancellable *cancellable,
+       GAsyncReadyCallback callback,
+       gpointer user_data,
+       gpgme_protocol_t protocol,
+       gchar *(*get_canonical_content)(FILE *, const gchar *));
+
 gpgme_verify_result_t sgpgme_verify_signature  (gpgme_ctx_t ctx,
                                         gpgme_data_t sig,
                                         gpgme_data_t plain,
index d4a407ae676f21bcdce6e2ef042f0b427a210a1c..dbdd03b1ab6229356fb389fcfed16f7651b87007 100644 (file)
@@ -1,3 +1,5 @@
+#include "config.h"
+
 #include "pgp_utils.h"
 
 #define HEADER "HEADER"
index 8670366b440ac4bfcf036935ad94a18d6047688d..f09bbfa58d6b22ee780719331608a5483c55f1aa 100644 (file)
@@ -15,6 +15,8 @@ file_read_stream_to_str_no_recode
 get_mime_tmp_dir
 file_read_stream_to_str_no_recode
 my_tmpfile
+privacy_free_sig_check_task_result
+privacy_free_signature_data
 privacy_register_system
 privacy_reset_error
 privacy_set_error
index 9b81fdcc9fe2bf67909f1de93664b86b26b2ac46..4dbd2befbaee3c1b109c7f1dba2e5133c49a6d64 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2016 Colin Leroy and the Claws Mail team
+ * Copyright (C) 1999-2021 Colin Leroy and the Claws Mail team
  *
  * 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
@@ -52,37 +52,28 @@ struct _PrivacyDataPGP
        
        gboolean        done_sigtest;
        gboolean        is_signed;
-       gpgme_verify_result_t   sigstatus;
-       gpgme_ctx_t     ctx;
 };
 
-static PrivacySystem pgpinline_system;
+typedef struct _PGPInlineTaskData
+{
+       gchar *rawtext;
+       gchar *charset;
+} PGPInlineTaskData;
 
-static gint pgpinline_check_signature(MimeInfo *mimeinfo);
+static PrivacySystem pgpinline_system;
 
 static PrivacyDataPGP *pgpinline_new_privacydata()
 {
        PrivacyDataPGP *data;
-       gpgme_error_t err;
 
        data = g_new0(PrivacyDataPGP, 1);
        data->data.system = &pgpinline_system;
-       data->done_sigtest = FALSE;
-       data->is_signed = FALSE;
-       data->sigstatus = NULL;
-       if ((err = gpgme_new(&data->ctx)) != GPG_ERR_NO_ERROR) {
-               debug_print(("Couldn't initialize GPG context, %s\n"), gpgme_strerror(err));
-        g_free(data);
-               return NULL;
-       }
        
        return data;
 }
 
-static void pgpinline_free_privacydata(PrivacyData *_data)
+static void pgpinline_free_privacydata(PrivacyData *data)
 {
-       PrivacyDataPGP *data = (PrivacyDataPGP *) _data;
-       gpgme_release(data->ctx);
        g_free(data);
 }
 
@@ -144,102 +135,178 @@ static gboolean pgpinline_is_signed(MimeInfo *mimeinfo)
        return TRUE;
 }
 
-static gint pgpinline_check_signature(MimeInfo *mimeinfo)
+static void pgpinline_free_task_data(gpointer data)
 {
-       PrivacyDataPGP *data = NULL;
-       gchar *textdata = NULL, *tmp = NULL;
-       gpgme_data_t plain = NULL, cipher = NULL;
-       gpgme_error_t err;
+       PGPInlineTaskData *task_data = (PGPInlineTaskData *)data;
+
+       g_free(task_data->rawtext);
+       g_free(task_data->charset);
+       g_free(task_data);
+}
 
-       cm_return_val_if_fail(mimeinfo != NULL, 0);
+static gchar *get_sig_data(gchar *rawtext, gchar *charset)
+{
+       gchar *conv;
 
-       if (procmime_mimeinfo_parent(mimeinfo) == NULL) {
-               privacy_set_error(_("Incorrect part"));
-               return 0; /* not parent */
+       conv = conv_codeset_strdup(rawtext, CS_UTF_8, charset);
+       if (!conv)
+               conv = conv_codeset_strdup(rawtext, CS_UTF_8, conv_get_locale_charset_str_no_utf8());
+
+       if (!conv) {
+               g_warning("can't convert charset to anything sane");
+               conv = conv_codeset_strdup(rawtext, CS_UTF_8, CS_US_ASCII);
        }
-       if (mimeinfo->type != MIMETYPE_TEXT) {
-               privacy_set_error(_("Not a text part"));
-               debug_print("type %d\n", mimeinfo->type);
-               return 0;
+
+       return conv;
+}
+
+static void pgpinline_check_sig_task(GTask *task,
+       gpointer source_object,
+       gpointer g_task_data,
+       GCancellable *cancellable)
+{
+       PGPInlineTaskData *task_data = (PGPInlineTaskData *)g_task_data;
+       GQuark domain;
+       gpgme_ctx_t ctx;
+       gpgme_error_t err;
+       gpgme_data_t sigdata = NULL;
+       gpgme_data_t plain = NULL;
+       gpgme_verify_result_t gpgme_res;
+       gboolean return_err = TRUE;
+       gboolean cancelled = FALSE;
+       SigCheckTaskResult *task_result = NULL;
+       gchar *textstr;
+       char err_str[GPGERR_BUFSIZE] = "";
+
+       domain = g_quark_from_static_string("claws_pgpinline");
+
+       err = gpgme_new(&ctx);
+       if (err != GPG_ERR_NO_ERROR) {
+               gpgme_strerror_r(err, err_str, GPGERR_BUFSIZE);
+               g_warning("couldn't initialize GPG context: %s", err_str);
+               goto out;
        }
-       cm_return_val_if_fail(mimeinfo->privacy != NULL, 0);
-       data = (PrivacyDataPGP *) mimeinfo->privacy;
 
-       textdata = procmime_get_part_as_string(mimeinfo, TRUE);
+       gpgme_set_textmode(ctx, 1);
+       gpgme_set_armor(ctx, 1);
 
-       if (!textdata) {
-               g_free(textdata);
-               privacy_set_error(_("Couldn't get text data."));
-               return 0;
+       textstr = get_sig_data(task_data->rawtext, task_data->charset);
+       if (!textstr) {
+               err = GPG_ERR_GENERAL;
+               g_snprintf(err_str, GPGERR_BUFSIZE, "Couldn't convert text data to any sane charset.");
+               goto out_ctx;
        }
 
-       /* gtk2: convert back from utf8 */
-       tmp = conv_codeset_strdup(textdata, CS_UTF_8,
-                       procmime_mimeinfo_get_parameter(mimeinfo, "charset"));
-       if (!tmp) {
-               tmp = conv_codeset_strdup(textdata, CS_UTF_8,
-                       conv_get_locale_charset_str_no_utf8());
+       err = gpgme_data_new_from_mem(&sigdata, textstr, strlen(textstr), 1);
+       if (err != GPG_ERR_NO_ERROR) {
+               gpgme_strerror_r(err, err_str, GPGERR_BUFSIZE);
+               g_warning("gpgme_data_new_from_mem failed: %s", err_str);
+               goto out_textstr;
        }
-       if (!tmp) {
-               g_warning("can't convert charset to anything sane");
-               tmp = conv_codeset_strdup(textdata, CS_UTF_8, CS_US_ASCII);
+
+       err = gpgme_data_new(&plain);
+       if (err != GPG_ERR_NO_ERROR) {
+               gpgme_strerror_r(err, err_str, GPGERR_BUFSIZE);
+               g_warning("gpgme_data_new failed: %s", err_str);
+               goto out_sigdata;
        }
-       g_free(textdata);
 
-       if (!tmp) {
-               privacy_set_error(_("Couldn't convert text data to any sane charset."));
-               return 0;
+       if (g_task_return_error_if_cancelled(task)) {
+               debug_print("task was cancelled, aborting task:%p\n", task);
+               cancelled = TRUE;
+               goto out_sigdata;
        }
-       textdata = g_strdup(tmp);
-       g_free(tmp);
-       
-       if ((err = gpgme_new(&data->ctx)) != GPG_ERR_NO_ERROR) {
-               debug_print(("Couldn't initialize GPG context, %s\n"), gpgme_strerror(err));
-               privacy_set_error(_("Couldn't initialize GPG context, %s"), gpgme_strerror(err));
-               g_free(textdata);
-               return 0;
+
+       err = gpgme_op_verify(ctx, sigdata, NULL, plain);
+       if (err != GPG_ERR_NO_ERROR) {
+               gpgme_strerror_r(err, err_str, GPGERR_BUFSIZE);
+               g_warning("gpgme_op_verify failed: %s\n", err_str);
+               goto out_plain;
        }
-       gpgme_set_textmode(data->ctx, 1);
-       gpgme_set_armor(data->ctx, 1);
-       
-       gpgme_data_new_from_mem(&plain, textdata, (size_t)strlen(textdata), 1);
-       gpgme_data_new(&cipher);
 
-       data->sigstatus = sgpgme_verify_signature(data->ctx, plain, NULL, cipher);
-       
+       if (g_task_return_error_if_cancelled(task)) {
+               debug_print("task was cancelled, aborting task:%p\n", task);
+               cancelled = TRUE;
+               goto out_sigdata;
+       }
+
+       gpgme_res = gpgme_op_verify_result(ctx);
+       if (gpgme_res && gpgme_res->signatures == NULL) {
+               err = GPG_ERR_SYSTEM_ERROR;
+               g_warning("no signature found");
+               g_snprintf(err_str, GPGERR_BUFSIZE, "No signature found");
+               goto out_plain;
+       }
+
+       task_result = g_new0(SigCheckTaskResult, 1);
+       task_result->sig_data = g_new0(SignatureData, 1);
+
+       task_result->sig_data->status = sgpgme_sigstat_gpgme_to_privacy(ctx, gpgme_res);
+       task_result->sig_data->info_short = sgpgme_sigstat_info_short(ctx, gpgme_res);
+       task_result->sig_data->info_full = sgpgme_sigstat_info_full(ctx, gpgme_res);
+
+       return_err = FALSE;
+
+out_plain:
        gpgme_data_release(plain);
-       gpgme_data_release(cipher);
-       
-       g_free(textdata);
-       
-       return 0;
+out_sigdata:
+       gpgme_data_release(sigdata);
+out_textstr:
+       g_free(textstr);
+out_ctx:
+       gpgme_release(ctx);
+out:
+       if (cancelled)
+               return;
+
+       if (return_err)
+               g_task_return_new_error(task, domain, err, "%s", err_str);
+       else
+               g_task_return_pointer(task, task_result, privacy_free_sig_check_task_result);
 }
 
-static SignatureStatus pgpinline_get_sig_status(MimeInfo *mimeinfo)
+static gint pgpinline_check_sig_async(MimeInfo *mimeinfo,
+       GCancellable *cancellable,
+       GAsyncReadyCallback callback,
+       gpointer user_data)
 {
-       PrivacyDataPGP *data = (PrivacyDataPGP *) mimeinfo->privacy;
+       GTask *task;
+       PGPInlineTaskData *task_data;
+       gchar *rawtext;
+       const gchar *charset;
 
-       cm_return_val_if_fail(data != NULL, SIGNATURE_INVALID);
+       if (procmime_mimeinfo_parent(mimeinfo) == NULL) {
+               g_warning("Checking signature on incorrect part");
+               return -1;
+       }
 
-       return sgpgme_sigstat_gpgme_to_privacy(data->ctx, data->sigstatus);
-}
+       if (mimeinfo->type != MIMETYPE_TEXT) {
+               g_warning("Checking signature on a non-text part");
+               return -1;
+       }
 
-static gchar *pgpinline_get_sig_info_short(MimeInfo *mimeinfo)
-{
-       PrivacyDataPGP *data = (PrivacyDataPGP *) mimeinfo->privacy;
+       rawtext = procmime_get_part_as_string(mimeinfo, TRUE);
+       if (rawtext == NULL) {
+               g_warning("Failed to get part as string");
+               return -1;
+       }
 
-       cm_return_val_if_fail(data != NULL, g_strdup("Error"));
+       charset = procmime_mimeinfo_get_parameter(mimeinfo, "charset");
 
-       return sgpgme_sigstat_info_short(data->ctx, data->sigstatus);
-}
+       task_data = g_new0(PGPInlineTaskData, 1);
+       task_data->rawtext = rawtext;
+       task_data->charset = g_strdup(charset);
 
-static gchar *pgpinline_get_sig_info_full(MimeInfo *mimeinfo)
-{
-       PrivacyDataPGP *data = (PrivacyDataPGP *) mimeinfo->privacy;
-       
-       cm_return_val_if_fail(data != NULL, g_strdup("Error"));
+       task = g_task_new(NULL, cancellable, callback, user_data);
+       mimeinfo->last_sig_check_task = task;
 
-       return sgpgme_sigstat_info_full(data->ctx, data->sigstatus);
+       g_task_set_task_data(task, task_data, pgpinline_free_task_data);
+       debug_print("creating check sig async task:%p task_data:%p\n", task, task_data);
+       g_task_set_return_on_cancel(task, TRUE);
+       g_task_run_in_thread(task, pgpinline_check_sig_task);
+       g_object_unref(task);
+
+       return 0;
 }
 
 static gboolean pgpinline_is_encrypted(MimeInfo *mimeinfo)
@@ -301,6 +368,7 @@ static MimeInfo *pgpinline_decrypt(MimeInfo *mimeinfo)
        const gchar *begin_indicator = "-----BEGIN PGP MESSAGE-----";
        const gchar *end_indicator = "-----END PGP MESSAGE-----";
        gchar *pos;
+       SignatureData *sig_data = NULL;
        
        if (gpgme_new(&ctx) != GPG_ERR_NO_ERROR)
                return NULL;
@@ -329,27 +397,37 @@ static MimeInfo *pgpinline_decrypt(MimeInfo *mimeinfo)
        gpgme_data_new_from_mem(&cipher, textdata, (size_t)strlen(textdata), 1);
 
        plain = sgpgme_decrypt_verify(cipher, &sigstat, ctx);
-       if (sigstat && !sigstat->signatures)
-               sigstat = NULL;
 
+       if (sigstat != NULL && sigstat->signatures != NULL) {
+               sig_data = g_new0(SignatureData, 1);
+               sig_data->status = sgpgme_sigstat_gpgme_to_privacy(ctx, sigstat);
+               sig_data->info_short = sgpgme_sigstat_info_short(ctx, sigstat);
+               sig_data->info_full = sgpgme_sigstat_info_full(ctx, sigstat);
+       }
+
+       gpgme_release(ctx);
        gpgme_data_release(cipher);
        
        if (plain == NULL) {
-               gpgme_release(ctx);
+               g_free(textdata);
+               if (sig_data)
+                       privacy_free_signature_data(sig_data);
                return NULL;
        }
 
-       fname = g_strdup_printf("%s%cplaintext.%08x",
+       fname = g_strdup_printf("%s%cplaintext.%08x",
                get_mime_tmp_dir(), G_DIR_SEPARATOR, ++id);
 
-       if ((dstfp = claws_fopen(fname, "wb")) == NULL) {
-               FILE_OP_ERROR(fname, "claws_fopen");
+       if ((dstfp = claws_fopen(fname, "wb")) == NULL) {
+               FILE_OP_ERROR(fname, "claws_fopen");
                privacy_set_error(_("Couldn't open decrypted file %s"), fname);
-               g_free(fname);
-               gpgme_data_release(plain);
-               gpgme_release(ctx);
+               if (sig_data)
+                       privacy_free_signature_data(sig_data);
+               g_free(textdata);
+               g_free(fname);
+               gpgme_data_release(plain);
                return NULL;
-       }
+       }
 
        src_codeset = procmime_mimeinfo_get_parameter(mimeinfo, "charset");
        if (src_codeset == NULL)
@@ -360,7 +438,7 @@ static MimeInfo *pgpinline_decrypt(MimeInfo *mimeinfo)
                        "Content-Transfer-Encoding: 8bit\r\n"
                        "\r\n",
                        src_codeset) < 0) {
-               FILE_OP_ERROR(fname, "fprintf");
+               FILE_OP_ERROR(fname, "fprintf");
                privacy_set_error(_("Couldn't write to decrypted file %s"), fname);
                goto FILE_ERROR;
        }
@@ -368,13 +446,13 @@ static MimeInfo *pgpinline_decrypt(MimeInfo *mimeinfo)
        /* Store any part before encrypted text */
        pos = pgp_locate_armor_header(textdata, begin_indicator);
        if (pos != NULL && (pos - textdata) > 0) {
-           if (claws_fwrite(textdata, 1, pos - textdata, dstfp) < pos - textdata) {
-               FILE_OP_ERROR(fname, "claws_fwrite");
-               privacy_set_error(_("Couldn't write to decrypted file %s"), fname);
-               goto FILE_ERROR;
-           }
+               if (claws_fwrite(textdata, 1, pos - textdata, dstfp) < pos - textdata) {
+                       FILE_OP_ERROR(fname, "claws_fwrite");
+                       privacy_set_error(_("Couldn't write to decrypted file %s"), fname);
+                       goto FILE_ERROR;
+               }
        }
-       
+
        if (claws_fwrite(_("\n--- Start of PGP/Inline encrypted data ---\n"), 1,
                strlen(_("\n--- Start of PGP/Inline encrypted data ---\n")), 
                dstfp) < strlen(_("\n--- Start of PGP/Inline encrypted data ---\n"))) {
@@ -412,12 +490,15 @@ static MimeInfo *pgpinline_decrypt(MimeInfo *mimeinfo)
            }
        }
 
+       g_free(textdata);
+
        if (claws_safe_fclose(dstfp) == EOF) {
                FILE_OP_ERROR(fname, "claws_fclose");
                privacy_set_error(_("Couldn't close decrypted file %s"), fname);
                g_free(fname);
                gpgme_data_release(plain);
-               gpgme_release(ctx);
+               if (sig_data)
+                       privacy_free_signature_data(sig_data);
                return NULL;
        }
        
@@ -425,16 +506,18 @@ static MimeInfo *pgpinline_decrypt(MimeInfo *mimeinfo)
        g_free(fname);
        
        if (parseinfo == NULL) {
-               gpgme_release(ctx);
                privacy_set_error(_("Couldn't scan decrypted file."));
+               if (sig_data)
+                       privacy_free_signature_data(sig_data);
                return NULL;
        }
        decinfo = g_node_first_child(parseinfo->node) != NULL ?
                g_node_first_child(parseinfo->node)->data : NULL;
                
        if (decinfo == NULL) {
-               gpgme_release(ctx);
                privacy_set_error(_("Couldn't scan decrypted file parts."));
+               if (sig_data)
+                       privacy_free_signature_data(sig_data);
                return NULL;
        }
 
@@ -443,7 +526,7 @@ static MimeInfo *pgpinline_decrypt(MimeInfo *mimeinfo)
 
        decinfo->tmp = TRUE;
 
-       if (sigstat != GPGME_SIG_STAT_NONE) {
+       if (sig_data != NULL) {
                if (decinfo->privacy != NULL) {
                        data = (PrivacyDataPGP *) decinfo->privacy;
                } else {
@@ -453,21 +536,19 @@ static MimeInfo *pgpinline_decrypt(MimeInfo *mimeinfo)
                if (data != NULL) {
                        data->done_sigtest = TRUE;
                        data->is_signed = TRUE;
-                       data->sigstatus = sigstat;
-                       if (data->ctx)
-                               gpgme_release(data->ctx);
-                       data->ctx = ctx;
+                       decinfo->sig_data = sig_data;
                }
-       } else
-               gpgme_release(ctx);
+       }
 
        return decinfo;
 
 FILE_ERROR:
+       if (sig_data)
+               privacy_free_signature_data(sig_data);
+       g_free(textdata);
        claws_fclose(dstfp);
        g_free(fname);
        gpgme_data_release(plain);
-       gpgme_release(ctx);
        return NULL;
 }
 
@@ -668,6 +749,8 @@ static gboolean pgpinline_encrypt(MimeInfo *mimeinfo, const gchar *encrypt_data)
                if (err) {
                        debug_print("can't add key '%s'[%d] (%s)\n", fprs[i],i, gpgme_strerror(err));
                        privacy_set_error(_("Couldn't add GPG key %s, %s"), fprs[i], gpgme_strerror(err));
+                       for (gint x = 0; x < i; x++)
+                               gpgme_key_unref(kset[x]);
                        g_free(kset);
                        g_free(fprs);
                        return FALSE;
@@ -685,6 +768,8 @@ static gboolean pgpinline_encrypt(MimeInfo *mimeinfo, const gchar *encrypt_data)
                if (!msgcontent->node->children) {
                        debug_print("msgcontent->node->children NULL, bailing\n");
                        privacy_set_error(_("Malformed message"));
+                       for (gint x = 0; x < i; x++)
+                               gpgme_key_unref(kset[x]);
                        g_free(kset);
                        g_free(fprs);
                        return FALSE;
@@ -698,6 +783,8 @@ static gboolean pgpinline_encrypt(MimeInfo *mimeinfo, const gchar *encrypt_data)
        if (fp == NULL) {
                privacy_set_error(_("Couldn't create temporary file, %s"), g_strerror(errno));
                perror("my_tmpfile");
+               for (gint x = 0; x < i; x++)
+                       gpgme_key_unref(kset[x]);
                g_free(kset);
                g_free(fprs);
                return FALSE;
@@ -716,6 +803,8 @@ static gboolean pgpinline_encrypt(MimeInfo *mimeinfo, const gchar *encrypt_data)
        if ((err = gpgme_new(&ctx)) != GPG_ERR_NO_ERROR) {
                debug_print(("Couldn't initialize GPG context, %s\n"), gpgme_strerror(err));
                privacy_set_error(_("Couldn't initialize GPG context, %s"), gpgme_strerror(err));
+               for (gint x = 0; x < i; x++)
+                       gpgme_key_unref(kset[x]);
                g_free(kset);
                g_free(fprs);
                return FALSE;
@@ -725,6 +814,8 @@ static gboolean pgpinline_encrypt(MimeInfo *mimeinfo, const gchar *encrypt_data)
        err = gpgme_op_encrypt(ctx, kset, GPGME_ENCRYPT_ALWAYS_TRUST, gpgtext, gpgenc);
 
        enccontent = sgpgme_data_release_and_get_mem(gpgenc, &len);
+       for (gint x = 0; x < i; x++)
+               gpgme_key_unref(kset[x]);
        g_free(kset);
 
        if (enccontent == NULL || len <= 0) {
@@ -769,10 +860,7 @@ static PrivacySystem pgpinline_system = {
        pgpinline_free_privacydata,     /* free_privacydata */
 
        pgpinline_is_signed,            /* is_signed(MimeInfo *) */
-       pgpinline_check_signature,      /* check_signature(MimeInfo *) */
-       pgpinline_get_sig_status,       /* get_sig_status(MimeInfo *) */
-       pgpinline_get_sig_info_short,   /* get_sig_info_short(MimeInfo *) */
-       pgpinline_get_sig_info_full,    /* get_sig_info_full(MimeInfo *) */
+       pgpinline_check_sig_async,
 
        pgpinline_is_encrypted,         /* is_encrypted(MimeInfo *) */
        pgpinline_decrypt,              /* decrypt(MimeInfo *) */
index 94ebbcfcedf9137b9bdd57c5675c8cf2b560b878..239fa6e7592d86224c1602e1d54f1e001746bab5 100644 (file)
@@ -35,7 +35,7 @@
 
 gint plugin_init(gchar **error)
 {
-       if (!check_plugin_version(MAKE_NUMERIC_VERSION(2,9,2,72),
+       if (!check_plugin_version(MAKE_NUMERIC_VERSION(3,18,0,277),
                                VERSION_NUMERIC, PLUGIN_NAME, error))
                return -1;
 
index 7f8f7001b2e982f66c76b637135ac2fc8c0e6c46..8dfafcefb2e4ba56e71505c1a9f5febd937a46ae 100644 (file)
@@ -1,17 +1,18 @@
 LIBRARY CLAWS-MAIL.EXE
 EXPORTS
 canonicalize_str
-claws_fopen
-claws_fdopen
+check_plugin_version
 claws_fclose
+claws_fdopen
+claws_fopen
 claws_safe_fclose
-check_plugin_version
 debug_print_real
 debug_srcname
 file_read_stream_to_str
 generate_mime_boundary
 get_mime_tmp_dir
 my_tmpfile
+privacy_free_signature_data
 privacy_register_system
 privacy_reset_error
 privacy_set_error
index ef81580722e58de0c87b37d419b3a74e661daef0..a0e70c369026aef700847d03e0132d4a6e64cb43 100644 (file)
@@ -1,7 +1,11 @@
 LIBRARY PGPCORE.DLL
 EXPORTS
+cm_check_detached_sig_async
+cm_gpgme_data_rewind
 gpgmegtk_passphrase_cb
+pgp_locate_armor_header
 prefs_gpg_add_skip_encryption_warning
+prefs_gpg_auto_check_signatures
 prefs_gpg_enable_agent
 prefs_gpg_get_config
 prefs_gpg_remove_skip_encryption_warning
@@ -15,6 +19,3 @@ sgpgme_sigstat_gpgme_to_privacy
 sgpgme_sigstat_info_full
 sgpgme_sigstat_info_short
 sgpgme_verify_signature
-cm_gpgme_data_rewind
-pgp_locate_armor_header
-prefs_gpg_auto_check_signatures
index 618bb6fa2e605414b6d6090f05ef6f4b40d3a7b6..a3e1142e64e8f86785e5f60fe29e5000d5622457 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2016 the Claws Mail team
+ * Copyright (C) 1999-2021 the Claws Mail team
  *
  * 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
@@ -52,37 +52,22 @@ struct _PrivacyDataPGP
        
        gboolean        done_sigtest;
        gboolean        is_signed;
-       gpgme_verify_result_t   sigstatus;
-       gpgme_ctx_t     ctx;
 };
 
 static PrivacySystem pgpmime_system;
 
-static gint pgpmime_check_signature(MimeInfo *mimeinfo);
-
 static PrivacyDataPGP *pgpmime_new_privacydata()
 {
        PrivacyDataPGP *data;
-       gpgme_error_t err;
 
        data = g_new0(PrivacyDataPGP, 1);
        data->data.system = &pgpmime_system;
-       data->done_sigtest = FALSE;
-       data->is_signed = FALSE;
-       data->sigstatus = NULL;
-       if ((err = gpgme_new(&data->ctx)) != GPG_ERR_NO_ERROR) {
-               g_warning("couldn't initialize GPG context: %s", gpgme_strerror(err));
-        g_free(data);
-               return NULL;
-       }
        
        return data;
 }
 
-static void pgpmime_free_privacydata(PrivacyData *_data)
+static void pgpmime_free_privacydata(PrivacyData *data)
 {
-       PrivacyDataPGP *data = (PrivacyDataPGP *) _data;
-       gpgme_release(data->ctx);
        g_free(data);
 }
 
@@ -139,7 +124,6 @@ static gboolean pgpmime_is_signed(MimeInfo *mimeinfo)
 
 static gchar *get_canonical_content(FILE *fp, const gchar *boundary)
 {
-       gchar *ret;
        GString *textbuffer;
        guint boundary_len;
        gchar buf[BUFFSIZE];
@@ -162,106 +146,20 @@ static gchar *get_canonical_content(FILE *fp, const gchar *boundary)
        }
        g_string_truncate(textbuffer, textbuffer->len - 2);
                
-       ret = textbuffer->str;
-       g_string_free(textbuffer, FALSE);
-
-       return ret;
+       return g_string_free(textbuffer, FALSE);
 }
 
-static gint pgpmime_check_signature(MimeInfo *mimeinfo)
+static gint pgpmime_check_sig_async(MimeInfo *mimeinfo,
+       GCancellable *cancellable,
+       GAsyncReadyCallback callback,
+       gpointer user_data)
 {
-       PrivacyDataPGP *data;
-       MimeInfo *parent, *signature;
-       FILE *fp;
-       gchar *boundary;
-       gchar *textstr;
-       gpgme_data_t sigdata = NULL, textdata = NULL;
-       gpgme_error_t err;
-       cm_return_val_if_fail(mimeinfo != NULL, -1);
-       cm_return_val_if_fail(mimeinfo->privacy != NULL, -1);
-       data = (PrivacyDataPGP *) mimeinfo->privacy;
-       if ((err = gpgme_new(&data->ctx)) != GPG_ERR_NO_ERROR) {
-               debug_print(("Couldn't initialize GPG context, %s\n"), gpgme_strerror(err));
-               privacy_set_error(_("Couldn't initialize GPG context, %s"), gpgme_strerror(err));
-               return 0;
-       }
-
-       
-       debug_print("Checking PGP/MIME signature\n");
-
-       err = gpgme_set_protocol(data->ctx, GPGME_PROTOCOL_OpenPGP);
-
-       if (err) {
-               debug_print ("gpgme_set_protocol failed: %s\n",
-                   gpgme_strerror (err));
-       }
-       parent = procmime_mimeinfo_parent(mimeinfo);
-
-       fp = claws_fopen(parent->data.filename, "rb");
-       cm_return_val_if_fail(fp != NULL, SIGNATURE_INVALID);
-       
-       boundary = g_hash_table_lookup(parent->typeparameters, "boundary");
-       if (!boundary) {
-               privacy_set_error(_("Signature boundary not found."));
-               claws_fclose(fp);
-               return 0;
-       }
-       textstr = get_canonical_content(fp, boundary);
-
-       err = gpgme_data_new_from_mem(&textdata, textstr, (size_t)strlen(textstr), 0);
-       if (err) {
-               debug_print ("gpgme_data_new_from_mem failed: %s\n",
-                   gpgme_strerror (err));
-       }
-       signature = (MimeInfo *) mimeinfo->node->next->data;
-       sigdata = sgpgme_data_from_mimeinfo(signature);
-
-       err = 0;
-       if (signature->encoding_type == ENC_BASE64) {
-               err = gpgme_data_set_encoding (sigdata, GPGME_DATA_ENCODING_BASE64);
-       }
-       
-       if (err) {
-               debug_print ("gpgme_data_set_encoding failed: %s\n",
-                       gpgme_strerror (err));
-       }
-
-       data->sigstatus =
-               sgpgme_verify_signature (data->ctx, sigdata, textdata, NULL);
-
-       gpgme_data_release(sigdata);
-       gpgme_data_release(textdata);
-       g_free(textstr);
-       claws_fclose(fp);
-       
-       return 0;
-}
-
-static SignatureStatus pgpmime_get_sig_status(MimeInfo *mimeinfo)
-{
-       PrivacyDataPGP *data = (PrivacyDataPGP *) mimeinfo->privacy;
-       
-       cm_return_val_if_fail(data != NULL, SIGNATURE_INVALID);
-
-       return sgpgme_sigstat_gpgme_to_privacy(data->ctx, data->sigstatus);
-}
-
-static gchar *pgpmime_get_sig_info_short(MimeInfo *mimeinfo)
-{
-       PrivacyDataPGP *data = (PrivacyDataPGP *) mimeinfo->privacy;
-       
-       cm_return_val_if_fail(data != NULL, g_strdup("Error"));
-
-       return sgpgme_sigstat_info_short(data->ctx, data->sigstatus);
-}
-
-static gchar *pgpmime_get_sig_info_full(MimeInfo *mimeinfo)
-{
-       PrivacyDataPGP *data = (PrivacyDataPGP *) mimeinfo->privacy;
-
-       cm_return_val_if_fail(data != NULL, g_strdup("Error"));
-
-       return sgpgme_sigstat_info_full(data->ctx, data->sigstatus);
+       return cm_check_detached_sig_async(mimeinfo,
+               cancellable,
+               callback,
+               user_data,
+               GPGME_PROTOCOL_OpenPGP,
+               get_canonical_content);
 }
 
 static gboolean pgpmime_is_encrypted(MimeInfo *mimeinfo)
@@ -325,6 +223,7 @@ static MimeInfo *pgpmime_decrypt(MimeInfo *mimeinfo)
        gchar *chars;
        size_t len;
        gpgme_error_t err;
+       SignatureData *sig_data = NULL;
 
        if ((err = gpgme_new(&ctx)) != GPG_ERR_NO_ERROR) {
                debug_print(("Couldn't initialize GPG context, %s\n"), gpgme_strerror(err));
@@ -339,33 +238,44 @@ static MimeInfo *pgpmime_decrypt(MimeInfo *mimeinfo)
        cipher = sgpgme_data_from_mimeinfo(encinfo);
        plain = sgpgme_decrypt_verify(cipher, &sigstat, ctx);
 
+       if (sigstat != NULL && sigstat->signatures != NULL) {
+               sig_data = g_new0(SignatureData, 1);
+               sig_data->status = sgpgme_sigstat_gpgme_to_privacy(ctx, sigstat);
+               sig_data->info_short = sgpgme_sigstat_info_short(ctx, sigstat);
+               sig_data->info_full = sgpgme_sigstat_info_full(ctx, sigstat);
+       }
+
+       gpgme_release(ctx);
        gpgme_data_release(cipher);
        if (plain == NULL) {
                debug_print("plain is null!\n");
-               gpgme_release(ctx);
+               if (sig_data)
+                       privacy_free_signature_data(sig_data);
                return NULL;
        }
 
-       fname = g_strdup_printf("%s%cplaintext.%08x",
+       fname = g_strdup_printf("%s%cplaintext.%08x",
                get_mime_tmp_dir(), G_DIR_SEPARATOR, ++id);
 
-       if ((dstfp = claws_fopen(fname, "wb")) == NULL) {
-               FILE_OP_ERROR(fname, "claws_fopen");
+       if ((dstfp = claws_fopen(fname, "wb")) == NULL) {
+               FILE_OP_ERROR(fname, "claws_fopen");
                privacy_set_error(_("Couldn't open decrypted file %s"), fname);
-               g_free(fname);
-               gpgme_data_release(plain);
-               gpgme_release(ctx);
+               if (sig_data)
+                       privacy_free_signature_data(sig_data);
+               g_free(fname);
+               gpgme_data_release(plain);
                debug_print("can't open!\n");
                return NULL;
-       }
+       }
 
        if (fprintf(dstfp, "MIME-Version: 1.0\n") < 0) {
-               FILE_OP_ERROR(fname, "fprintf");
+               FILE_OP_ERROR(fname, "fprintf");
                claws_fclose(dstfp);
                privacy_set_error(_("Couldn't write to decrypted file %s"), fname);
-               g_free(fname);
-               gpgme_data_release(plain);
-               gpgme_release(ctx);
+               if (sig_data)
+                       privacy_free_signature_data(sig_data);
+               g_free(fname);
+               gpgme_data_release(plain);
                debug_print("can't open!\n");
                return NULL;
        }
@@ -373,13 +283,14 @@ static MimeInfo *pgpmime_decrypt(MimeInfo *mimeinfo)
        chars = sgpgme_data_release_and_get_mem(plain, &len);
        if (len > 0) {
                if (claws_fwrite(chars, 1, len, dstfp) < len) {
-                       FILE_OP_ERROR(fname, "claws_fwrite");
+                       FILE_OP_ERROR(fname, "claws_fwrite");
                        g_free(chars);
                        claws_fclose(dstfp);
                        privacy_set_error(_("Couldn't write to decrypted file %s"), fname);
-                       g_free(fname);
-                       gpgme_data_release(plain);
-                       gpgme_release(ctx);
+                       if (sig_data)
+                               privacy_free_signature_data(sig_data);
+                       g_free(fname);
+                       gpgme_data_release(plain);
                        debug_print("can't open!\n");
                        return NULL;
                }
@@ -387,11 +298,12 @@ static MimeInfo *pgpmime_decrypt(MimeInfo *mimeinfo)
        g_free(chars);
 
        if (claws_safe_fclose(dstfp) == EOF) {
-               FILE_OP_ERROR(fname, "claws_fclose");
+               FILE_OP_ERROR(fname, "claws_fclose");
                privacy_set_error(_("Couldn't close decrypted file %s"), fname);
-               g_free(fname);
-               gpgme_data_release(plain);
-               gpgme_release(ctx);
+               if (sig_data)
+                       privacy_free_signature_data(sig_data);
+               g_free(fname);
+               gpgme_data_release(plain);
                debug_print("can't open!\n");
                return NULL;
        }
@@ -399,15 +311,17 @@ static MimeInfo *pgpmime_decrypt(MimeInfo *mimeinfo)
        parseinfo = procmime_scan_file(fname);
        g_free(fname);
        if (parseinfo == NULL) {
-               gpgme_release(ctx);
                privacy_set_error(_("Couldn't parse decrypted file."));
+               if (sig_data)
+                       privacy_free_signature_data(sig_data);
                return NULL;
        }
        decinfo = g_node_first_child(parseinfo->node) != NULL ?
                g_node_first_child(parseinfo->node)->data : NULL;
        if (decinfo == NULL) {
                privacy_set_error(_("Couldn't parse decrypted file parts."));
-               gpgme_release(ctx);
+               if (sig_data)
+                       privacy_free_signature_data(sig_data);
                return NULL;
        }
 
@@ -416,23 +330,20 @@ static MimeInfo *pgpmime_decrypt(MimeInfo *mimeinfo)
 
        decinfo->tmp = TRUE;
 
-       if (sigstat != NULL && sigstat->signatures != NULL) {
+       if (sig_data != NULL) {
                if (decinfo->privacy != NULL) {
                        data = (PrivacyDataPGP *) decinfo->privacy;
                } else {
                        data = pgpmime_new_privacydata();
-                       decinfo->privacy = (PrivacyData *) data;        
+                       decinfo->privacy = (PrivacyData *) data;
                }
+
                if (data != NULL) {
                        data->done_sigtest = TRUE;
                        data->is_signed = TRUE;
-                       data->sigstatus = sigstat;
-                       if (data->ctx)
-                               gpgme_release(data->ctx);
-                       data->ctx = ctx;
+                       decinfo->sig_data = sig_data;
                }
-       } else
-               gpgme_release(ctx);
+       }
 
        return decinfo;
 }
@@ -588,6 +499,7 @@ gboolean pgpmime_sign(MimeInfo *mimeinfo, PrefsAccount *account, const gchar *fr
                privacy_set_error(_("Data signing failed, no contents."));
                g_free(micalg);
                g_free(sigcontent);
+               gpgme_release(ctx);
                return FALSE;
        }
 
@@ -651,8 +563,7 @@ gboolean pgpmime_encrypt(MimeInfo *mimeinfo, const gchar *encrypt_data)
                i++;
        }
        
-       kset = g_malloc(sizeof(gpgme_key_t)*(i+1));
-       memset(kset, 0, sizeof(gpgme_key_t)*(i+1));
+       kset = g_malloc0(sizeof(gpgme_key_t)*(i+1));
        if ((err = gpgme_new(&ctx)) != GPG_ERR_NO_ERROR) {
                debug_print(("Couldn't initialize GPG context, %s\n"), gpgme_strerror(err));
                privacy_set_error(_("Couldn't initialize GPG context, %s"), gpgme_strerror(err));
@@ -667,8 +578,11 @@ gboolean pgpmime_encrypt(MimeInfo *mimeinfo, const gchar *encrypt_data)
                if (err) {
                        debug_print("can't add key '%s'[%d] (%s)\n", fprs[i],i, gpgme_strerror(err));
                        privacy_set_error(_("Couldn't add GPG key %s, %s"), fprs[i], gpgme_strerror(err));
+                       for (gint x = 0; x < i; x++)
+                               gpgme_key_unref(kset[x]);
                        g_free(kset);
                        g_free(fprs);
+                       gpgme_release(ctx);
                        return FALSE;
                }
                debug_print("found %s at %d\n", fprs[i], i);
@@ -698,9 +612,12 @@ gboolean pgpmime_encrypt(MimeInfo *mimeinfo, const gchar *encrypt_data)
        if (fp == NULL) {
                perror("my_tmpfile");
                privacy_set_error(_("Couldn't create temporary file, %s"), g_strerror(errno));
+               for (gint x = 0; x < i; x++)
+                       gpgme_key_unref(kset[x]);
                g_free(kset);
                g_free(boundary);
                g_free(fprs);
+               gpgme_release(ctx);
                return FALSE;
        }
        procmime_write_mimeinfo(encmultipart, fp);
@@ -723,6 +640,8 @@ gboolean pgpmime_encrypt(MimeInfo *mimeinfo, const gchar *encrypt_data)
        enccontent = sgpgme_data_release_and_get_mem(gpgenc, &len);
        gpgme_data_release(gpgtext);
        g_free(textstr);
+       for (gint x = 0; x < i; x++)
+               gpgme_key_unref(kset[x]);
        g_free(kset);
 
        if (enccontent == NULL || len <= 0) {
@@ -772,10 +691,7 @@ static PrivacySystem pgpmime_system = {
        pgpmime_free_privacydata,       /* free_privacydata */
 
        pgpmime_is_signed,              /* is_signed(MimeInfo *) */
-       pgpmime_check_signature,        /* check_signature(MimeInfo *) */
-       pgpmime_get_sig_status,         /* get_sig_status(MimeInfo *) */
-       pgpmime_get_sig_info_short,     /* get_sig_info_short(MimeInfo *) */
-       pgpmime_get_sig_info_full,      /* get_sig_info_full(MimeInfo *) */
+       pgpmime_check_sig_async,
 
        pgpmime_is_encrypted,           /* is_encrypted(MimeInfo *) */
        pgpmime_decrypt,                /* decrypt(MimeInfo *) */
index fe339cbc892c92c26f98ed995eb6ac42cb0c8f68..dfd435e8b34b0d746594610a2cb3808015ea2503 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2012 the Claws Mail team
+ * Copyright (C) 1999-2021 the Claws Mail team
  *
  * 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
@@ -35,7 +35,7 @@
 
 gint plugin_init(gchar **error)
 {
-       if (!check_plugin_version(MAKE_NUMERIC_VERSION(2,9,2,72),
+       if (!check_plugin_version(MAKE_NUMERIC_VERSION(3,18,0,277),
                                VERSION_NUMERIC, PLUGIN_NAME, error))
                return -1;
 
index 3a4d8d5766c5cabe11cbff33da72bc84528a2ba2..0cda250e75d1016e2c4c7a76c2407497d06a1bb2 100644 (file)
@@ -15,8 +15,6 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "clawsmailmodule.h"
-
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
 #include "claws-features.h"
@@ -25,6 +23,7 @@
 #include <glib.h>
 #include <glib/gi18n.h>
 
+#include "clawsmailmodule.h"
 #include "nodetype.h"
 #include "composewindowtype.h"
 #include "folderpropertiestype.h"
index 96d009591de4f1533c9f7891a89176ec0e8acfaf..5ea29f29958e37e2f77f380a1934c4f6b9e39412 100644 (file)
@@ -20,6 +20,9 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+
+#include "config.h"
+
 #include <gdk/gdkkeysyms.h>
 #include <string.h>
 
index cb7c6d21b9d3eb52b3bc6da1526089a146ba674d..2e62c04b9f9bf0f7e31c566a50ba855436e0e9dc 100644 (file)
@@ -32,9 +32,6 @@
 #  include <config.h>
 #endif
 
-/* this is needed for strptime() */
-#define _XOPEN_SOURCE /* glibc2 needs this */
-
 #include <time.h>
 #include <glib.h>
 //#include <locale.h>
index cac9af825f05562c3b2ca189eb00e930ff9a919a..f467eb64541e68cd0235a8bf7671014e2bf2f4c1 100644 (file)
@@ -17,7 +17,7 @@
  * Boston, MA 02111-1307, USA.
  */
 
-#define __USE_GNU
+#include "config.h"
 
 #include <stdlib.h>
 #include <glib.h>
index d766cdcdc3c5bf22c5592b72c260d1dd5aaa5a19..8268b8398b010324bccd780233a17dbf9a7c04fe 100644 (file)
@@ -17,7 +17,7 @@
  * Boston, MA 02111-1307, USA.
  */
 
-#define __USE_GNU
+#include "config.h"
 
 #include <stdlib.h>
 #include <glib.h>
index 0716003d67a55d51fbfaec02da06724e4ccb1b14..6e01230af338d2ba90f71080b6be8edae2d4940e 100644 (file)
@@ -17,7 +17,7 @@
  * Boston, MA 02111-1307, USA.
  */
 
-#define __USE_GNU
+#include "config.h"
 
 #include <stdlib.h>
 #include <glib.h>
index c463be67355ecffe798fcdbe65a7bcb37f003330..71f2068b0e8cea8d0ed54e7cc3c08a4e335eded9 100644 (file)
@@ -16,7 +16,8 @@
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
-#define __USE_GNU
+
+#include "config.h"
 
 #include <glib.h>
 #include <expat.h>
index 575ffc9d363c52a33f6af2621e53770f43dc665c..cbf5bbed47d14f9b9bdc771ab8d6705fdcae209c 100644 (file)
@@ -17,6 +17,8 @@
  * Boston, MA 02111-1307, USA.
  */
 
+#include "config.h"
+
 #include <glib.h>
 #include <curl/curl.h>
 #include <expat.h>
index 361c5a8ba75e140ec129711368dab048ce8f8c68..74017d7f37e533224cdaf6921f0ce6aced55f11a 100644 (file)
@@ -16,7 +16,8 @@
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
-#define __USE_GNU
+
+#include "config.h"
 
 #include <glib.h>
 #include <expat.h>
index c40789430e4c4dd5c518a752c3c41d217f730683..872cf2f5ef7071846a992cf6fda2d1d1c6ce4a76 100644 (file)
@@ -16,7 +16,8 @@
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
-#define __USE_GNU
+
+#include "config.h"
 
 #include <glib.h>
 #include <expat.h>
index cb08224b5307faec5ceb5106dde78674ac1849a2..c07a77eae23d1c4674f5fc2af875763391825a3f 100644 (file)
@@ -1,3 +1,5 @@
+#include "config.h"
+
 #include <glib.h>
 
 #include "date.h"
index 514d19ae0273c5da2cbb737bdf09b7b72dd5e16e..aa001d0438f66e3e595994ad227e7412a289b9fc 100644 (file)
@@ -1,3 +1,5 @@
+#include "config.h"
+
 #include <glib.h>
 
 #include "feed.h"
index 15e0bd98352a21e0eb66d4de6ce232bc95a08ad2..d41db2b60e1254effc85adb2d9c82bb912a8d2dc 100644 (file)
@@ -19,6 +19,8 @@
 
 /* Expat parser for old feeds.xml */
 
+#include "config.h"
+
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
 #include <expat.h>
index b3c976b44ae80c3295f4349a693141d698e92719..406fc5f9e0de794f4d3cc8442703471522e5496f 100644 (file)
@@ -1,3 +1,5 @@
+#include "config.h"
+
 #include "strutils.h"
 
 /* It's safe to mock this out here, we are interested in
index 351805937d4210c9ba0545ba6451a2093f6272d3..77e8fd83650db19762b897d5e8ab0febc97ac4e8 100644 (file)
@@ -3,11 +3,11 @@ EXPORTS
 alertpanel_error
 canonicalize_file_replace
 canonicalize_str
-claws_fopen
-claws_fdopen
+check_plugin_version
 claws_fclose
+claws_fdopen
+claws_fopen
 claws_safe_fclose
-check_plugin_version
 claws_unlink
 debug_print_real
 debug_srcname
@@ -18,12 +18,15 @@ generate_mime_boundary
 get_mime_tmp_dir
 get_tmp_file
 my_tmpfile
+privacy_free_sig_check_task_result
+privacy_free_signature_data
 privacy_register_system
 privacy_set_error
 privacy_unregister_system
 procmime_decode_content
 procmime_encode_content
 procmime_get_part
+procmime_get_part_as_string
 procmime_mimeinfo_free_all
 procmime_mimeinfo_get_parameter
 procmime_mimeinfo_new
index 44dd8d22e10904c199045ab8525c91323b8ef068..f2a911c6148d0e8d4a2b24f3d24be73a1ad33cc6 100644 (file)
@@ -1,7 +1,10 @@
 LIBRARY PGPCORE.DLL
 EXPORTS
+cm_check_detached_sig_async
+cm_gpgme_data_rewind
 gpgmegtk_passphrase_cb
 prefs_gpg_add_skip_encryption_warning
+prefs_gpg_auto_check_signatures
 prefs_gpg_enable_agent
 prefs_gpg_get_config
 prefs_gpg_remove_skip_encryption_warning
@@ -15,5 +18,3 @@ sgpgme_sigstat_gpgme_to_privacy
 sgpgme_sigstat_info_full
 sgpgme_sigstat_info_short
 sgpgme_verify_signature
-cm_gpgme_data_rewind
-prefs_gpg_auto_check_signatures
index d31c1b339079f52408cd1aca41845cfded3e81c9..579ea513ed59a9d1e26f9eede7411dbf62268461 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2012 Colin Leroy <colin@colino.net> and 
+ * Copyright (C) 1999-2021 Colin Leroy <colin@colino.net> and 
  * the Claws Mail team
  *
  * This program is free software; you can redistribute it and/or modify
 #include "common/claws.h"
 #include "smime.h"
 
+#define PLUGIN_NAME (_("S/MIME"))
+
 gint plugin_init(gchar **error)
 {
-       if (!check_plugin_version(MAKE_NUMERIC_VERSION(2,9,2,72),
-                               VERSION_NUMERIC, _("S/MIME"), error))
+       if (!check_plugin_version(MAKE_NUMERIC_VERSION(3,18,0,277),
+                               VERSION_NUMERIC, PLUGIN_NAME, error))
                return -1;
 
        smime_init();
@@ -51,7 +53,7 @@ gboolean plugin_done(void)
 
 const gchar *plugin_name(void)
 {
-       return _("S/MIME");
+       return PLUGIN_NAME;
 }
 
 const gchar *plugin_desc(void)
index 324fc67df62551a6bbc1f26090cfe94584d2e29b..e920936aea43b602569363623d5ecdbc50d66c59 100644 (file)
@@ -1,6 +1,6 @@
 /* 
  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2016 Colin Leroy and the Claws Mail team
+ * Copyright (C) 1999-2021 Colin Leroy and the Claws Mail team
  *
  * 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
@@ -52,41 +52,34 @@ struct _PrivacyDataPGP
        
        gboolean        done_sigtest;
        gboolean        is_signed;
-       gpgme_verify_result_t   sigstatus;
-       gpgme_ctx_t     ctx;
+       gboolean        inserted_mimeinfo;
 };
 
-static PrivacySystem smime_system;
+typedef struct _PKCS7MimeTaskData {
+       gchar *textstr;
+       EncodingType encoding;
+       gboolean create_mimeinfo;
+} PKCS7MimeTaskData;
 
-static gint smime_check_signature(MimeInfo *mimeinfo);
+static PrivacySystem smime_system;
 
 static PrivacyDataPGP *smime_new_privacydata()
 {
        PrivacyDataPGP *data;
-       gpgme_ctx_t     ctx;
-
-       if (gpgme_new(&ctx) != GPG_ERR_NO_ERROR) {
-               debug_print("gpgme_new failed\n");
-               return NULL;
-       }
 
        data = g_new0(PrivacyDataPGP, 1);
        data->data.system = &smime_system;
-       data->done_sigtest = FALSE;
-       data->is_signed = FALSE;
-       data->sigstatus = NULL;
-       data->ctx = ctx;
        
        return data;
 }
 
-static void smime_free_privacydata(PrivacyData *_data)
+static void smime_free_privacydata(PrivacyData *data)
 {
-       PrivacyDataPGP *data = (PrivacyDataPGP *) _data;
-       gpgme_release(data->ctx);
        g_free(data);
 }
 
+static gint check_pkcs7_mime_sig(MimeInfo *, GCancellable *, GAsyncReadyCallback, gpointer);
+
 static gboolean smime_is_signed(MimeInfo *mimeinfo)
 {
        MimeInfo *parent;
@@ -114,7 +107,7 @@ static gboolean smime_is_signed(MimeInfo *mimeinfo)
 
                        data->done_sigtest = TRUE;
                        data->is_signed = TRUE;
-                       smime_check_signature(mimeinfo);
+                       check_pkcs7_mime_sig(mimeinfo, NULL, NULL, NULL);
                        return TRUE;
                }
        }
@@ -163,7 +156,6 @@ static gboolean smime_is_signed(MimeInfo *mimeinfo)
 
 static gchar *get_canonical_content(FILE *fp, const gchar *boundary)
 {
-       gchar *ret;
        GString *textbuffer;
        guint boundary_len = 0;
        gchar buf[BUFFSIZE];
@@ -188,190 +180,339 @@ static gchar *get_canonical_content(FILE *fp, const gchar *boundary)
        }
        g_string_truncate(textbuffer, textbuffer->len - 2);
                
-       ret = textbuffer->str;
-       g_string_free(textbuffer, FALSE);
+       return g_string_free(textbuffer, FALSE);
+}
 
-       return ret;
+static void free_pkcs7_mime_task_data(gpointer data)
+{
+       PKCS7MimeTaskData *task_data = (PKCS7MimeTaskData *)data;
+
+       g_free(task_data->textstr);
+       g_free(task_data);
 }
 
-static gint smime_check_signature(MimeInfo *mimeinfo)
+static gboolean create_mimeinfo_for_plaintext(const GString *verified, MimeInfo **created)
 {
-       PrivacyDataPGP *data;
-       MimeInfo *parent, *signature;
-       FILE *fp;
-       gchar *boundary;
-       gchar *textstr = NULL;
-       const gchar *tmpstr;
-       gpgme_data_t sigdata = NULL, textdata = NULL;
+       gchar *tmpfile;
+       MimeInfo *newinfo = NULL;
+       MimeInfo *decinfo = NULL;
+
+       tmpfile = get_tmp_file();
+
+       str_write_to_file(verified->str, tmpfile, TRUE);
+       newinfo = procmime_scan_file(tmpfile);
+       g_free(tmpfile);
+       decinfo = g_node_first_child(newinfo->node) != NULL ?
+               g_node_first_child(newinfo->node)->data : NULL;
+
+       if (decinfo == NULL)
+               return FALSE;
+
+       g_node_unlink(decinfo->node);
+       procmime_mimeinfo_free_all(&newinfo);
+       decinfo->tmp = TRUE;
+
+       *created = decinfo;
+       return TRUE;
+}
+
+static void check_pkcs7_mime_sig_task(GTask *task,
+       gpointer source_object,
+       gpointer _task_data,
+       GCancellable *cancellable)
+{
+       PKCS7MimeTaskData *task_data = (PKCS7MimeTaskData *)_task_data;
+       GQuark domain;
+       gpgme_ctx_t ctx;
        gpgme_error_t err;
-       EncodingType oldenc = ENC_BINARY;
+       gpgme_data_t sigdata = NULL;
+       gpgme_data_t plain;
+       gpgme_verify_result_t gpgme_res;
+       size_t len;
+       gboolean return_err = TRUE;
+       gboolean cancelled = FALSE;
+       SigCheckTaskResult *task_result = NULL;
+       MimeInfo *created = NULL;
+       GString *verified;
+       gchar *tmp;
+       char err_str[GPGERR_BUFSIZE] = "";
 
-       cm_return_val_if_fail(mimeinfo != NULL, -1);
-       cm_return_val_if_fail(mimeinfo->privacy != NULL, -1);
+       domain = g_quark_from_static_string("claws_smime");
 
-       data = (PrivacyDataPGP *) mimeinfo->privacy;
+       err = gpgme_new(&ctx);
+       if (err != GPG_ERR_NO_ERROR) {
+               gpgme_strerror_r(err, err_str, GPGERR_BUFSIZE);
+               g_warning("couldn't initialize GPG context: %s", err_str);
+               goto out;
+       }
 
-       if (!data->ctx) {
-               if ((err = gpgme_new(&data->ctx)) != GPG_ERR_NO_ERROR) {
-                       debug_print("gpgme_new failed: %s\n",
-                               gpgme_strerror(err));
-                       return -1;
+       err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_CMS);
+       if (err != GPG_ERR_NO_ERROR) {
+               gpgme_strerror_r(err, err_str, GPGERR_BUFSIZE);
+               g_warning("couldn't set GPG protocol: %s", err_str);
+               goto out_ctx;
+       }
+
+       err = gpgme_data_new_from_mem(&sigdata,
+               task_data->textstr,
+               task_data->textstr ? strlen(task_data->textstr) : 0,
+               0);
+       if (err != GPG_ERR_NO_ERROR) {
+               gpgme_strerror_r(err, err_str, GPGERR_BUFSIZE);
+               g_warning("gpgme_data_new_from_mem failed: %s", err_str);
+               goto out_ctx;
+       }
+
+       if (task_data->encoding == ENC_BASE64) {
+               err = gpgme_data_set_encoding (sigdata, GPGME_DATA_ENCODING_BASE64);
+               if (err != GPG_ERR_NO_ERROR) {
+                       gpgme_strerror_r(err, err_str, GPGERR_BUFSIZE);
+                       g_warning("gpgme_data_set_encoding failed: %s\n", err_str);
+                       goto out_sigdata;
                }
        }
 
-       debug_print("Checking S/MIME signature\n");
+       err = gpgme_data_new(&plain);
+       if (err != GPG_ERR_NO_ERROR) {
+               gpgme_strerror_r(err, err_str, GPGERR_BUFSIZE);
+               g_warning("gpgme_data_new failed: %s", err_str);
+               goto out_sigdata;
+       }
 
-       err = gpgme_set_protocol(data->ctx, GPGME_PROTOCOL_CMS);
+       if (g_task_return_error_if_cancelled(task)) {
+               debug_print("task was cancelled, aborting task:%p\n", task);
+               cancelled = TRUE;
+               goto out_sigdata;
+       }
 
-       if (err) {
-               debug_print ("gpgme_set_protocol failed: %s\n",
-                   gpgme_strerror (err));
+       err = gpgme_op_verify(ctx, sigdata, NULL, plain);
+       if (err != GPG_ERR_NO_ERROR) {
+               gpgme_strerror_r(err, err_str, GPGERR_BUFSIZE);
+               g_warning("gpgme_op_verify failed: %s\n", err_str);
+               goto out_plain;
        }
-       parent = procmime_mimeinfo_parent(mimeinfo);
 
-       fp = claws_fopen(parent->data.filename, "rb");
-       cm_return_val_if_fail(fp != NULL, SIGNATURE_INVALID);
-       
-       boundary = g_hash_table_lookup(parent->typeparameters, "boundary");
-       if (!boundary) {
-               gchar *tmpfile = get_tmp_file();
-               debug_print("no boundary\n");
-               if (tmpfile) {
-                       if (mimeinfo->encoding_type != ENC_BASE64) {
-                               procmime_encode_content(mimeinfo, ENC_BASE64);
-                       }
-                       oldenc = mimeinfo->encoding_type;
-                       if (mimeinfo->encoding_type == ENC_BASE64)
-                               mimeinfo->encoding_type = ENC_BINARY;
-                       if (procmime_get_part(tmpfile, mimeinfo) == 0) {
-                               textstr = file_read_to_str(tmpfile);
-                       } else {
-                               textstr = NULL;
-                       }
-                       if (mimeinfo->encoding_type != oldenc)
-                               mimeinfo->encoding_type = oldenc;
-               }
-               g_free(tmpfile);
-       } else {
-               textstr = get_canonical_content(fp, boundary);
+       if (g_task_return_error_if_cancelled(task)) {
+               debug_print("task was cancelled, aborting task:%p\n", task);
+               cancelled = TRUE;
+               goto out_sigdata;
        }
-       err = gpgme_data_new_from_mem(&textdata, textstr, textstr?strlen(textstr):0, 0);
-       
-       if (err) {
-               debug_print ("gpgme_data_new_from_mem failed: %s\n",
-                   gpgme_strerror (err));
+
+       gpgme_res = gpgme_op_verify_result(ctx);
+       if (gpgme_res && gpgme_res->signatures == NULL) {
+               err = GPG_ERR_SYSTEM_ERROR;
+               g_warning("no signature found");
+               g_snprintf(err_str, GPGERR_BUFSIZE, "No signature found");
+               goto out_plain;
        }
 
-       if (!g_ascii_strcasecmp(mimeinfo->subtype, "pkcs7-mime") ||
-           !g_ascii_strcasecmp(mimeinfo->subtype, "x-pkcs7-mime")) {
-               tmpstr = procmime_mimeinfo_get_parameter(mimeinfo, "smime-type");
-               if (tmpstr && !g_ascii_strcasecmp(tmpstr, "signed-data")) {
-                       gpgme_data_t cipher;
-                       size_t len;
-                       if (oldenc == ENC_BASE64)
-                               gpgme_data_set_encoding (textdata, GPGME_DATA_ENCODING_BASE64);
-                       gpgme_data_new(&cipher);
-                       data->sigstatus =
-                               sgpgme_verify_signature (data->ctx, textdata, NULL, cipher);
-                       gpgme_data_release(textdata);
-                       g_free(textstr);
-                       cm_gpgme_data_rewind(cipher);
-                       textstr = sgpgme_data_release_and_get_mem(cipher, &len);
-                       claws_fclose(fp);
-                       if (textstr && len > 0)
-                               textstr[len-1]='\0';
-
-                       if (textstr && len) {
-                               gchar *tmp_file = get_tmp_file();
-                               MimeInfo *newinfo = NULL, *decinfo = NULL, *parentinfo = NULL;
-
-                               str_write_to_file(textstr, tmp_file, TRUE);
-                               newinfo = procmime_scan_file(tmp_file);
-                               decinfo = g_node_first_child(newinfo->node) != NULL ?
-                                       g_node_first_child(newinfo->node)->data : NULL;
-
-                               if (decinfo == NULL) {
-                                       g_free(textstr);
-                                       return -1;
-                               }
-
-                               g_node_unlink(decinfo->node);
-                               procmime_mimeinfo_free_all(&newinfo);
-                               decinfo->tmp = TRUE;
-                               parentinfo = procmime_mimeinfo_parent(mimeinfo);
-
-                               if (parentinfo->type == MIMETYPE_MESSAGE && 
-                                   !strcmp(parentinfo->subtype, "rfc822")) {
-                                       procmime_decode_content(parentinfo);
-                                       procmime_encode_content(parentinfo, ENC_BASE64);
-                                       procmime_encode_content(parentinfo, ENC_8BIT);
-                                       if (parentinfo->content == MIMECONTENT_MEM) {
-                                               gint newlen = 
-                                                       (gint)(strstr(parentinfo->data.mem, "\n\n") - parentinfo->data.mem);
-                                               if (newlen > 0)
-                                                       parentinfo->length = newlen;
-                                       }
-                               }
-                               g_node_prepend(parentinfo->node, decinfo->node);
-                               g_free(textstr);
-                               return 0;
-                       } else {
-                               if (textstr)
-                                       g_free(textstr);
-                               return -1;
-                       }
+       if (task_data->create_mimeinfo) {
+               tmp = gpgme_data_release_and_get_mem(plain, &len);
+               if (!tmp) {
+                       debug_print("S/MIME signed message had no plaintext\n");
+                       goto out_sigdata;
                }
-       }
 
-       signature = (MimeInfo *) mimeinfo->node->next->data;
-       sigdata = sgpgme_data_from_mimeinfo(signature);
+               verified = g_string_new_len(tmp, len);
+               gpgme_free(tmp);
 
-       err = 0;
-       if (signature->encoding_type == ENC_BASE64) {
-               err = gpgme_data_set_encoding (sigdata, GPGME_DATA_ENCODING_BASE64);
-       }
-       
-       if (err) {
-               debug_print ("gpgme_data_set_encoding failed: %s\n",
-                       gpgme_strerror (err));
+               if (!create_mimeinfo_for_plaintext(verified, &created)) {
+                       g_warning("Failed to create new mimeinfo from plaintext");
+                       g_string_free(verified, TRUE);
+                       goto out_sigdata;
+               }
+
+               g_string_free(verified, TRUE);
+       } else {
+               gpgme_data_release(plain);
        }
 
-       data->sigstatus =
-               sgpgme_verify_signature (data->ctx, sigdata, textdata, NULL);
+       task_result = g_new0(SigCheckTaskResult, 1);
+       task_result->sig_data = g_new0(SignatureData, 1);
+
+       task_result->sig_data->status = sgpgme_sigstat_gpgme_to_privacy(ctx, gpgme_res);
+       task_result->sig_data->info_short = sgpgme_sigstat_info_short(ctx, gpgme_res);
+       task_result->sig_data->info_full = sgpgme_sigstat_info_full(ctx, gpgme_res);
+
+       task_result->newinfo = created;
+       return_err = FALSE;
+
+       goto out_sigdata;
 
+out_plain:
+       gpgme_data_release(plain);
+out_sigdata:
        gpgme_data_release(sigdata);
-       gpgme_data_release(textdata);
-       g_free(textstr);
-       claws_fclose(fp);
-       
-       return 0;
+out_ctx:
+       gpgme_release(ctx);
+out:
+       if (cancelled)
+               return;
+
+       if (return_err)
+               g_task_return_new_error(task, domain, err, "%s", err_str);
+       else
+               g_task_return_pointer(task, task_result, privacy_free_sig_check_task_result);
 }
 
-static SignatureStatus smime_get_sig_status(MimeInfo *mimeinfo)
+/* Check PKCS7-MIME signed-data type signature either synchronously or asynchronously.
+ * Check it asynchronously if the caller provides a callback.
+ * If the caller does not provide a callback, and we have not already done so, create
+ * and insert a new MimeInfo for the plaintext data returned by the sig verification.
+ */
+static gint check_pkcs7_mime_sig(MimeInfo *mimeinfo,
+       GCancellable *_cancellable,
+       GAsyncReadyCallback callback,
+       gpointer user_data)
 {
-       PrivacyDataPGP *data = (PrivacyDataPGP *) mimeinfo->privacy;
-       
-       cm_return_val_if_fail(data != NULL, SIGNATURE_INVALID);
+       MimeInfo *parent;
+       const gchar *tmp;
+       EncodingType real_enc;
+       gchar *textstr = NULL;
+       PrivacyDataPGP *privacy_data;
+       GCancellable *cancellable;
+       GTask *task;
+       PKCS7MimeTaskData *task_data;
+       SigCheckTaskResult *task_result;
+       GError *error;
+       gboolean unref_cancellable = FALSE;
 
-       return sgpgme_sigstat_gpgme_to_privacy(data->ctx, data->sigstatus);
-}
+       debug_print("Checking pkcs7-mime signature\n");
 
-static gchar *smime_get_sig_info_short(MimeInfo *mimeinfo)
-{
-       PrivacyDataPGP *data = (PrivacyDataPGP *) mimeinfo->privacy;
-       
-       cm_return_val_if_fail(data != NULL, g_strdup("Error"));
+       parent = procmime_mimeinfo_parent(mimeinfo);
+       tmp = g_hash_table_lookup(parent->typeparameters, "boundary");
+       if (tmp) {
+               g_warning("Unexpected S/MIME message format subtype:%s boundary:%s",
+                       mimeinfo->subtype, tmp);
+               return -1;
+       }
+
+       if (g_ascii_strcasecmp(mimeinfo->subtype, "pkcs7-mime") &&
+               g_ascii_strcasecmp(mimeinfo->subtype, "x-pkcs7-mime"))
+       {
+               g_warning("Unexpected S/MIME subtype:%s", mimeinfo->subtype);
+               return -1;
+       }
+
+       tmp = procmime_mimeinfo_get_parameter(mimeinfo, "smime-type");
+       if (!tmp || g_ascii_strcasecmp(tmp, "signed-data")) {
+               g_warning("Unexpected S/MIME smime-type parameter:%s", tmp);
+               return -1;
+       }
+
+       real_enc = mimeinfo->encoding_type;
+       mimeinfo->encoding_type = ENC_BINARY;
+       textstr = procmime_get_part_as_string(mimeinfo, TRUE);
+       mimeinfo->encoding_type = real_enc;
+       if (!textstr) {
+               g_warning("Failed to get PKCS7-Mime signature data");
+               return -1;
+       }
+
+       privacy_data = (PrivacyDataPGP *)mimeinfo->privacy;
+
+       task_data = g_new0(PKCS7MimeTaskData, 1);
+       task_data->textstr = textstr;
+       task_data->encoding = mimeinfo->encoding_type;
+
+       if (!callback && !privacy_data->inserted_mimeinfo)
+               task_data->create_mimeinfo = TRUE;
+
+       if (_cancellable != NULL) {
+               cancellable = _cancellable;
+       } else {
+               cancellable = g_cancellable_new();
+               unref_cancellable = TRUE;
+       }
+
+       task = g_task_new(NULL, cancellable, callback, user_data);
+       mimeinfo->last_sig_check_task = task;
+
+       g_task_set_task_data(task, task_data, free_pkcs7_mime_task_data);
+       g_task_set_return_on_cancel(task, TRUE);
+
+       if (callback) {
+               debug_print("creating check sig async task:%p task_data:%p\n", task, task_data);
+               g_task_run_in_thread(task, check_pkcs7_mime_sig_task);
+               g_object_unref(task);
+               return 0;
+       }
+
+       debug_print("creating check sig sync task:%p task_data:%p\n", task, task_data);
+       g_task_run_in_thread_sync(task, check_pkcs7_mime_sig_task);
+       mimeinfo->last_sig_check_task = NULL;
+
+       task_result = g_task_propagate_pointer(task, &error);
+       if (unref_cancellable)
+               g_object_unref(cancellable);
+
+       if (mimeinfo->sig_data) {
+               privacy_free_signature_data(mimeinfo->sig_data);
+               mimeinfo->sig_data = NULL;
+       }
+
+       if (task_result == NULL) {
+               debug_print("sig check task propagated NULL task:%p GError: domain:%s code:%d message:\"%s\"\n",
+                       task, g_quark_to_string(error->domain), error->code, error->message);
+                g_object_unref(task);
+               g_error_free(error);
+               return -1;
+       }
+       g_object_unref(task);
+
+       mimeinfo->sig_data = task_result->sig_data;
 
-       return sgpgme_sigstat_info_short(data->ctx, data->sigstatus);
+       if (task_result->newinfo) {
+               if (parent->type == MIMETYPE_MESSAGE && !strcmp(parent->subtype, "rfc822")) {
+                       if (parent->content == MIMECONTENT_MEM) {
+                               gint newlen = (gint)(strstr(parent->data.mem, "\n\n") - parent->data.mem);
+                               if (newlen > 0)
+                               parent->length = newlen;
+                       }
+               }
+
+               g_node_prepend(parent->node, task_result->newinfo->node);
+               privacy_data->inserted_mimeinfo = TRUE;
+       }
+
+       /* Only free the task result struct, not the SigData and MimeInfo */
+       g_free(task_result);
+
+       return 1;
 }
 
-static gchar *smime_get_sig_info_full(MimeInfo *mimeinfo)
+static gint smime_check_sig_async(MimeInfo *mimeinfo,
+       GCancellable *cancellable,
+       GAsyncReadyCallback callback,
+       gpointer user_data)
 {
-       PrivacyDataPGP *data = (PrivacyDataPGP *) mimeinfo->privacy;
-       
-       cm_return_val_if_fail(data != NULL, g_strdup("Error"));
+       MimeInfo *parent;
+       gchar *boundary;
+
+       /* Detached signature with a boundary */
+       if (g_ascii_strcasecmp(mimeinfo->subtype, "pkcs7-mime") &&
+               g_ascii_strcasecmp(mimeinfo->subtype, "x-pkcs7-mime"))
+       {
+               parent = procmime_mimeinfo_parent(mimeinfo);
+               boundary = g_hash_table_lookup(parent->typeparameters, "boundary");
 
-       return sgpgme_sigstat_info_full(data->ctx, data->sigstatus);
+               if (boundary == NULL) {
+                       g_warning("Unexpected S/MIME format subtype:%s without a boundary",
+                               mimeinfo->subtype);
+                       return -1;
+               }
+
+               return cm_check_detached_sig_async(mimeinfo,
+                       cancellable,
+                       callback,
+                       user_data,
+                       GPGME_PROTOCOL_CMS,
+                       get_canonical_content);
+
+       /* Opaque pkcs7-mime blob with smime-type=signed-data */
+       } else {
+               return check_pkcs7_mime_sig(mimeinfo, cancellable, callback, user_data);
+       }
 }
 
 static gboolean smime_is_encrypted(MimeInfo *mimeinfo)
@@ -410,6 +551,7 @@ static MimeInfo *smime_decrypt(MimeInfo *mimeinfo)
        gpgme_error_t err;
        gchar *chars;
        size_t len;
+       SignatureData *sig_data = NULL;
 
        cm_return_val_if_fail(smime_is_encrypted(mimeinfo), NULL);
        
@@ -434,10 +576,19 @@ static MimeInfo *smime_decrypt(MimeInfo *mimeinfo)
        
        plain = sgpgme_decrypt_verify(cipher, &sigstat, ctx);
 
+       if (sigstat != NULL && sigstat->signatures != NULL) {
+               sig_data = g_new0(SignatureData, 1);
+               sig_data->status = sgpgme_sigstat_gpgme_to_privacy(ctx, sigstat);
+               sig_data->info_short = sgpgme_sigstat_info_short(ctx, sigstat);
+               sig_data->info_full = sgpgme_sigstat_info_full(ctx, sigstat);
+       }
+
+       gpgme_release(ctx);
        gpgme_data_release(cipher);
        if (plain == NULL) {
                debug_print("plain is null!\n");
-               gpgme_release(ctx);
+               if (sig_data)
+                       privacy_free_signature_data(sig_data);
                return NULL;
        }
 
@@ -448,9 +599,10 @@ static MimeInfo *smime_decrypt(MimeInfo *mimeinfo)
                FILE_OP_ERROR(fname, "claws_fopen");
                g_free(fname);
                gpgme_data_release(plain);
-               gpgme_release(ctx);
                debug_print("can't open!\n");
                privacy_set_error(_("Couldn't open temporary file"));
+               if (sig_data)
+                       privacy_free_signature_data(sig_data);
                return NULL;
        }
 
@@ -459,9 +611,10 @@ static MimeInfo *smime_decrypt(MimeInfo *mimeinfo)
                g_free(fname);
                claws_fclose(dstfp);
                gpgme_data_release(plain);
-               gpgme_release(ctx);
                debug_print("can't close!\n");
                privacy_set_error(_("Couldn't write to temporary file"));
+               if (sig_data)
+                       privacy_free_signature_data(sig_data);
                return NULL;
        }
 
@@ -474,9 +627,10 @@ static MimeInfo *smime_decrypt(MimeInfo *mimeinfo)
                        g_free(fname);
                        g_free(chars);
                        gpgme_data_release(plain);
-                       gpgme_release(ctx);
                        debug_print("can't write!\n");
                        privacy_set_error(_("Couldn't write to temporary file"));
+                       if (sig_data)
+                               privacy_free_signature_data(sig_data);
                        return NULL;
                }
        }
@@ -485,9 +639,10 @@ static MimeInfo *smime_decrypt(MimeInfo *mimeinfo)
                g_free(fname);
                        g_free(chars);
                gpgme_data_release(plain);
-               gpgme_release(ctx);
                debug_print("can't close!\n");
                privacy_set_error(_("Couldn't close temporary file"));
+               if (sig_data)
+                       privacy_free_signature_data(sig_data);
                return NULL;
        }
        g_free(chars);
@@ -496,14 +651,16 @@ static MimeInfo *smime_decrypt(MimeInfo *mimeinfo)
        g_free(fname);
        if (parseinfo == NULL) {
                privacy_set_error(_("Couldn't parse decrypted file."));
-               gpgme_release(ctx);
+               if (sig_data)
+                       privacy_free_signature_data(sig_data);
                return NULL;
        }
        decinfo = g_node_first_child(parseinfo->node) != NULL ?
                g_node_first_child(parseinfo->node)->data : NULL;
        if (decinfo == NULL) {
                privacy_set_error(_("Couldn't parse decrypted file parts."));
-               gpgme_release(ctx);
+               if (sig_data)
+                       privacy_free_signature_data(sig_data);
                return NULL;
        }
 
@@ -512,28 +669,24 @@ static MimeInfo *smime_decrypt(MimeInfo *mimeinfo)
 
        decinfo->tmp = TRUE;
 
-       if (sigstat != NULL && sigstat->signatures != NULL) {
+       if (sig_data != NULL) {
                if (decinfo->privacy != NULL) {
                        data = (PrivacyDataPGP *) decinfo->privacy;
                } else {
                        data = smime_new_privacydata();
                        if (!data) {
-                               gpgme_release(ctx);
                                return NULL;
                        }
                        decinfo->privacy = (PrivacyData *) data;        
                }
-               data->done_sigtest = TRUE;
-               data->is_signed = TRUE;
-               data->sigstatus = sigstat;
-               if (data->ctx)
-                       gpgme_release(data->ctx);
-               data->ctx = ctx;
-       } else
-               gpgme_release(ctx);
-       
-       
-       
+
+               if (data != NULL) {
+                       data->done_sigtest = TRUE;
+                       data->is_signed = TRUE;
+                       decinfo->sig_data = sig_data;
+               }
+       }
+
        return decinfo;
 }
 
@@ -803,6 +956,8 @@ gboolean smime_encrypt(MimeInfo *mimeinfo, const gchar *encrypt_data)
        fp = claws_fopen(tmpfile, "wb");
        if (fp == NULL) {
                FILE_OP_ERROR(tmpfile, "create");
+               for (gint x = 0; x < i; x++)
+                       gpgme_key_unref(kset[x]);
                g_free(kset);
                g_free(tmpfile);
                return FALSE;
@@ -815,6 +970,8 @@ gboolean smime_encrypt(MimeInfo *mimeinfo, const gchar *encrypt_data)
        fp = claws_fopen(tmpfile, "rb");
        if (fp == NULL) {
                FILE_OP_ERROR(tmpfile, "open");
+               for (gint x = 0; x < i; x++)
+                       gpgme_key_unref(kset[x]);
                g_free(kset);
                g_free(tmpfile);
                return FALSE;
@@ -834,6 +991,8 @@ gboolean smime_encrypt(MimeInfo *mimeinfo, const gchar *encrypt_data)
        gpgme_op_encrypt(ctx, kset, GPGME_ENCRYPT_ALWAYS_TRUST, gpgtext, gpgenc);
 
        gpgme_release(ctx);
+       for (gint x = 0; x < i; x++)
+               gpgme_key_unref(kset[x]);
        g_free(kset);
        enccontent = sgpgme_data_release_and_get_mem(gpgenc, &len);
 
@@ -887,10 +1046,7 @@ static PrivacySystem smime_system = {
        smime_free_privacydata, /* free_privacydata */
 
        smime_is_signed,                /* is_signed(MimeInfo *) */
-       smime_check_signature,  /* check_signature(MimeInfo *) */
-       smime_get_sig_status,           /* get_sig_status(MimeInfo *) */
-       smime_get_sig_info_short,       /* get_sig_info_short(MimeInfo *) */
-       smime_get_sig_info_full,        /* get_sig_info_full(MimeInfo *) */
+       smime_check_sig_async,
 
        smime_is_encrypted,             /* is_encrypted(MimeInfo *) */
        smime_decrypt,                  /* decrypt(MimeInfo *) */
index 0e130fbc6a6203fcbb08f960fbb90b213156f5a8..136524e532c9c4f3541f125f7110228c5152e83b 100644 (file)
@@ -16,6 +16,8 @@
  * </@LICENSE>
  */
 
+#include "config.h"
+
 #ifndef _WIN32
 #include <unistd.h>
 #include <sys/uio.h>
index 54d288d33cd743b40bf8caf4d3b1ae4f4f1cd204..bd96741761995f746267d3d26a63d4adcb91cd9e 100644 (file)
@@ -153,6 +153,7 @@ remove_dir_recursive
 slist_free_strings
 slist_free_strings_full
 statusbar_progress_all
+strcrlftrunc
 strretchomp
 str_write_to_file
 subst_for_filename
index 9c07fbec28b703e541e5efc09a91e16eedf5b570..6a39e35de19e1c8d04cf4e9a0c9dded45658419e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2015 Colin Leroy <colin@colino.net> and
+ * Copyright (C) 1999-2021 Colin Leroy <colin@colino.net> and
  * the Claws Mail team
  *
  * This program is free software; you can redistribute it and/or modify
@@ -1789,19 +1789,10 @@ static gchar *feed_get_title(const gchar *str)
        gchar *title = NULL;
        if (strstr(str, "X-WR-CALNAME:")) {
                title = g_strdup(strstr(str, "X-WR-CALNAME:")+strlen("X-WR-CALNAME:"));
-               if (strstr(title, "\n"))
-                       *(strstr(title, "\n")) = '\0';
-               if (strstr(title, "\r"))
-                       *(strstr(title, "\r")) = '\0';          
        } else if (strstr(str, "X-WR-CALDESC:")) {
                title = g_strdup(strstr(str, "X-WR-CALDESC:")+strlen("X-WR-CALDESC:"));
-               if (strstr(title, "\n"))
-                       *(strstr(title, "\n")) = '\0';
-               if (strstr(title, "\r"))
-                       *(strstr(title, "\r")) = '\0';          
        }
-       
-       return title;
+       return strcrlftrunc(title);
 }
 
 static void update_subscription_finish(const gchar *uri, gchar *feed, gboolean verbose, gchar *error)
@@ -1958,8 +1949,45 @@ static void subscribe_cal_cb(GtkAction *action, gpointer data)
 {
        gchar *uri = NULL;
        gchar *tmp = NULL;
+       gchar *clip_text = NULL, *str = NULL;
+
+    clip_text = gtk_clipboard_wait_for_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD));
+
+    if (clip_text) {
+        str = clip_text;
+#if GLIB_CHECK_VERSION(2,66,0)
+        GError *error = NULL;
+        GUri *uri = NULL;
+
+        /* skip any leading white-space */
+        while (str && *str && g_ascii_isspace(*str))
+            str++;
+        uri = g_uri_parse(str, G_URI_FLAGS_PARSE_RELAXED, &error);
+        if (error) {
+            g_warning("could not parse clipboard text for URI: '%s'", error->message);
+            g_error_free(error);
+        }
+        if (uri) {
+            gchar* newstr = g_uri_to_string(uri);
+
+            debug_print("URI: '%s' -> '%s'\n", str, newstr ? newstr : "N/A");
+            if (newstr)
+                g_free(newstr);
+            g_uri_unref(uri);
+        } else {
+#else
+        if (!is_uri_string(str)) {
+#endif
+            /* if no URL, ignore clipboard text */
+            str = NULL;
+        }
+    }
+
+       tmp = input_dialog(_("Subscribe to Webcal"), _("Enter the Webcal URL:"), str ? str : "");
+
+       if (clip_text)
+               g_free(clip_text);
 
-       tmp = input_dialog(_("Subscribe to Webcal"), _("Enter the Webcal URL:"), NULL);
        if (tmp == NULL)
                return;
        
index 790b2c8c58ae4accf1587890ca13097c6afdf75c..b1dd0ccb465d2ccc0d889bb5869280d874b77650 100644 (file)
@@ -4259,8 +4259,8 @@ static gboolean sslcert_get_client_cert_hook(gpointer source, gpointer data)
 }
 
 struct GetPassData {
-       GCond *cond;
-       GMutex* mutex;
+       GCond cond;
+       GMutex mutex;
        gchar **pass;
 };
 
@@ -4268,38 +4268,28 @@ struct GetPassData {
 static gboolean do_get_pass(gpointer data)
 {
        struct GetPassData *pass_data = (struct GetPassData *)data;
-       g_mutex_lock(pass_data->mutex);
+       g_mutex_lock(&pass_data->mutex);
        *(pass_data->pass) = input_dialog_query_password("the PKCS12 client certificate", NULL);
-       g_cond_signal(pass_data->cond);
-       g_mutex_unlock(pass_data->mutex);
+       g_cond_signal(&pass_data->cond);
+       g_mutex_unlock(&pass_data->mutex);
        return FALSE;
 }
 static gboolean sslcert_get_password(gpointer source, gpointer data)
 { 
        struct GetPassData pass_data;
        /* do complicated stuff to be able to call GTK from the mainloop */
-#if !GLIB_CHECK_VERSION(2,32,0)
-       pass_data.cond = g_cond_new();
-#else
-       pass_data.cond = g_new0(GCond, 1);
-       g_cond_init(pass_data.cond);
-#endif
-       pass_data.mutex = cm_mutex_new();
+       g_cond_init(&pass_data.cond);
+       g_mutex_init(&pass_data.mutex);
        pass_data.pass = (gchar **)source;
 
-       g_mutex_lock(pass_data.mutex);
+       g_mutex_lock(&pass_data.mutex);
 
        g_idle_add(do_get_pass, &pass_data);
 
-       g_cond_wait(pass_data.cond, pass_data.mutex);
-#if !GLIB_CHECK_VERSION(2,32,0)
-       g_cond_free(pass_data.cond);
-#else
-       g_cond_clear(pass_data.cond);
-       g_free(pass_data.cond);
-#endif
-       g_mutex_unlock(pass_data.mutex);
-       cm_mutex_free(pass_data.mutex);
+       g_cond_wait(&pass_data.cond, &pass_data.mutex);
+       g_cond_clear(&pass_data.cond);
+       g_mutex_unlock(&pass_data.mutex);
+       g_mutex_clear(&pass_data.mutex);
 
        return TRUE;
 }
index ba7eb723e4e4d5b223b74f2ccd45eebec0f9ca4a..7b3b0c26a04c01f4edb4848d52b6c59959a0788e 100644 (file)
@@ -20,7 +20,6 @@
 #define __PREFS_COMMON_H__
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
 #include "claws-features.h"
 #endif
 
index 1e8dc7df0357c5d873f5f86d34b392b75c2e17e3..0c3e11b6444fe3728660f4fd2a0ae0ad90632856 100644 (file)
@@ -1500,7 +1500,7 @@ static MatcherProp *prefs_matcher_dialog_to_matcher(void)
        gboolean case_sensitive;
        const gchar *header;
        const gchar *expr;
-    gboolean expr_to_free = FALSE;
+       gboolean expr_to_free = FALSE;
        gint value, sel;
        gint year, month, day, hour, minute;
 
@@ -1692,7 +1692,7 @@ static MatcherProp *prefs_matcher_dialog_to_matcher(void)
                                      expr, value);
 
        if (expr_to_free)
-               g_free(expr);
+               g_free((gchar *)expr);
 
        return matcherprop;
 }
index 617938ba986f0c325d751a5e39287db8ac63fecf..5d055f7325a12364770594ceb91d546374fc54f6 100644 (file)
@@ -17,6 +17,8 @@
  *
  */
 
+#include "config.h"
+
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
index ea3a938d64d7b24f45256467e8dcd559ef4ce2cf..fed2f4a0c2bc44cf4dfc2ed953105ac6530106c3 100644 (file)
@@ -18,6 +18,7 @@
  * 
  */
 
+#include "config.h"
 #include "defs.h"
 
 #include <glib.h>
index 01b282a6b3196c797a1b91f6a290b7bce2ef19cf..56da4ce172633a481db65c74b56b36afdcec879f 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2012 Hiroyuki Yamamoto & the Claws Mail team
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2021 the Claws Mail team and Hiroyuki Yamamoto
  *
  * 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
@@ -17,6 +17,8 @@
  * 
  */
 
+#include "config.h"
+
 #include <glib.h>
 #include <glib/gi18n.h>
 
@@ -109,6 +111,27 @@ void privacy_free_privacydata(PrivacyData *privacydata)
        system->free_privacydata(privacydata);
 }
 
+void privacy_free_signature_data(gpointer data)
+{
+       SignatureData *sig_data = (SignatureData *)data;
+
+       cm_return_if_fail(sig_data != NULL);
+
+       g_free(sig_data->info_short);
+       g_free(sig_data->info_full);
+       g_free(sig_data);
+}
+
+void privacy_free_sig_check_task_result(gpointer data)
+{
+       SigCheckTaskResult *result = (SigCheckTaskResult *)data;
+
+       privacy_free_signature_data(result->sig_data);
+       if (result->newinfo)
+               procmime_mimeinfo_free_all(&result->newinfo);
+       g_free(result);
+}
+
 /**
  * Check if a MimeInfo is signed with one of the available
  * privacy system. If a privacydata is set in the MimeInfo
@@ -193,26 +216,32 @@ void privacy_msginfo_get_signed_state(MsgInfo *msginfo, gchar **system)
  * \return Error code indicating the result of the check,
  *         < 0 if an error occurred
  */
-gint privacy_mimeinfo_check_signature(MimeInfo *mimeinfo)
+gint privacy_mimeinfo_check_signature(MimeInfo *mimeinfo,
+       GCancellable *cancellable,
+       GAsyncReadyCallback callback,
+       gpointer user_data)
 {
        PrivacySystem *system;
 
-       cm_return_val_if_fail(mimeinfo != NULL, -1);
+       if (mimeinfo == NULL)
+               g_error("siginfo was NULL");
+
+       if (mimeinfo->privacy == NULL) {
+               g_warning("mimeinfo->privacy was NULL");
 
-       if (mimeinfo->privacy == NULL)
                privacy_mimeinfo_is_signed(mimeinfo);
-       
-       if (mimeinfo->privacy == NULL)
-               return -1;
-       
+               if (mimeinfo->privacy == NULL) {
+                       g_error("failed to set up PrivacyData");
+               }
+       }
+
        system = privacy_data_get_system(mimeinfo->privacy);
        if (system == NULL)
-               return -1;
+               g_error("failed to get privacy system");
+       else if (system->check_signature == NULL)
+               g_error("didn't find check_signature function");
 
-       if (system->check_signature == NULL)
-               return -1;
-       
-       return system->check_signature(mimeinfo);
+       return system->check_signature(mimeinfo, cancellable, callback, user_data);
 }
 
 SignatureStatus privacy_mimeinfo_get_sig_status(MimeInfo *mimeinfo)
@@ -221,61 +250,49 @@ SignatureStatus privacy_mimeinfo_get_sig_status(MimeInfo *mimeinfo)
 
        cm_return_val_if_fail(mimeinfo != NULL, -1);
 
-       if (mimeinfo->privacy == NULL)
+       if (mimeinfo->privacy == NULL) {
                privacy_mimeinfo_is_signed(mimeinfo);
-       
-       if (mimeinfo->privacy == NULL)
-               return SIGNATURE_UNCHECKED;
-       
+
+               if (mimeinfo->privacy == NULL)
+                       return SIGNATURE_UNCHECKED;
+       }
+
        system = privacy_data_get_system(mimeinfo->privacy);
        if (system == NULL)
                return SIGNATURE_UNCHECKED;
-       if (system->get_sig_status == NULL)
+
+       if (mimeinfo->sig_data == NULL)
                return SIGNATURE_UNCHECKED;
-       
-       return system->get_sig_status(mimeinfo);
+       else
+               return mimeinfo->sig_data->status;
 }
 
-gchar *privacy_mimeinfo_sig_info_short(MimeInfo *mimeinfo)
+gchar *privacy_mimeinfo_get_sig_info(MimeInfo *mimeinfo, gboolean full)
 {
        PrivacySystem *system;
+       gchar *info;
 
        cm_return_val_if_fail(mimeinfo != NULL, NULL);
 
-       if (mimeinfo->privacy == NULL)
+       if (mimeinfo->privacy == NULL) {
                privacy_mimeinfo_is_signed(mimeinfo);
-       
-       if (mimeinfo->privacy == NULL)
-               return g_strdup(_("No signature found"));
-       
+
+               if (mimeinfo->privacy == NULL)
+                       return _("No signature found");
+       }
+
        system = privacy_data_get_system(mimeinfo->privacy);
        if (system == NULL)
-               return g_strdup(_("No signature found"));
-       if (system->get_sig_info_short == NULL)
-               return g_strdup(_("No information available"));
-       
-       return system->get_sig_info_short(mimeinfo);
-}
+               return _("No signature found");
 
-gchar *privacy_mimeinfo_sig_info_full(MimeInfo *mimeinfo)
-{
-       PrivacySystem *system;
+       if (mimeinfo->sig_data == NULL)
+               return _("No information available");
 
-       cm_return_val_if_fail(mimeinfo != NULL, NULL);
+       info = full ? mimeinfo->sig_data->info_full : mimeinfo->sig_data->info_short;
+       if (info == NULL)
+               return _("No information available");
 
-       if (mimeinfo->privacy == NULL)
-               privacy_mimeinfo_is_signed(mimeinfo);
-       
-       if (mimeinfo->privacy == NULL)
-               return g_strdup(_("No signature found"));
-       
-       system = privacy_data_get_system(mimeinfo->privacy);
-       if (system == NULL)
-               return g_strdup(_("No signature found"));
-       if (system->get_sig_info_full == NULL)
-               return g_strdup(_("No information available"));
-       
-       return system->get_sig_info_full(mimeinfo);
+       return info;
 }
 
 gboolean privacy_mimeinfo_is_encrypted(MimeInfo *mimeinfo)
index ebc191972355fc6200e3039401824e55908f560a..3aafae9ad011587d28efee2b1e69c27aa2213a11 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2012 Hiroyuki Yamamoto and the Claws Mail team
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2021 the Claws Mail team and Hiroyuki Yamamoto
  *
  * 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
@@ -30,9 +30,21 @@ typedef enum {
        SIGNATURE_KEY_EXPIRED,
        SIGNATURE_INVALID,
        SIGNATURE_CHECK_FAILED,
-       SIGNATURE_CHECK_TIMEOUT
+       SIGNATURE_CHECK_TIMEOUT,
+       SIGNATURE_CHECK_ERROR
 } SignatureStatus;
 
+typedef struct _SignatureData {
+       SignatureStatus status;
+       gchar *info_short;
+       gchar *info_full;
+} SignatureData;
+
+typedef struct _SigCheckTaskResult {
+       SignatureData *sig_data;
+       struct _MimeInfo *newinfo;
+} SigCheckTaskResult;
+
 #include <glib.h>
 
 #include "procmime.h"
@@ -42,13 +54,17 @@ void privacy_register_system                        (PrivacySystem *system);
 void privacy_unregister_system                 (PrivacySystem *system);
 
 void privacy_free_privacydata                  (PrivacyData *);
+void privacy_free_signature_data               (gpointer);
+void privacy_free_sig_check_task_result        (gpointer);
 
 void privacy_msginfo_get_signed_state          (MsgInfo *, gchar **system);
 gboolean privacy_mimeinfo_is_signed            (MimeInfo *);
-gint privacy_mimeinfo_check_signature          (MimeInfo *);
+gint privacy_mimeinfo_check_signature  (MimeInfo *mimeinfo,
+       GCancellable *cancellable,
+       GAsyncReadyCallback callback,
+       gpointer user_data);
 SignatureStatus privacy_mimeinfo_get_sig_status        (MimeInfo *);
-gchar *privacy_mimeinfo_sig_info_short         (MimeInfo *);
-gchar *privacy_mimeinfo_sig_info_full          (MimeInfo *);
+gchar *privacy_mimeinfo_get_sig_info           (MimeInfo *, gboolean);
 
 gboolean privacy_mimeinfo_is_encrypted         (MimeInfo *);
 gint privacy_mimeinfo_decrypt                  (MimeInfo *);
@@ -83,10 +99,10 @@ struct _PrivacySystem {
        void             (*free_privacydata)    (PrivacyData *data);
 
        gboolean         (*is_signed)           (MimeInfo *mimeinfo);
-       gint             (*check_signature)     (MimeInfo *mimeinfo);
-       SignatureStatus  (*get_sig_status)      (MimeInfo *mimeinfo);
-       gchar           *(*get_sig_info_short)  (MimeInfo *mimeinfo);
-       gchar           *(*get_sig_info_full)   (MimeInfo *mimeinfo);
+       gint             (*check_signature)     (MimeInfo *mimeinfo,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
 
        gboolean         (*is_encrypted)        (MimeInfo *mimeinfo);
        MimeInfo        *(*decrypt)             (MimeInfo *mimeinfo);
index 64c7af29db4c9a67d86a793703dfa5327f876002..8a3efefef4c6da42174796ad79b6da33a2993819 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2021 the Claws Mail Team and Hiroyuki Yamamoto
+ * Copyright (C) 1999-2021 the Claws Mail team and Hiroyuki Yamamoto
  *
  * 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
@@ -59,7 +59,9 @@
 #define REG_MIME_TYPE_VALUE "Content Type"
 #endif
 
+#ifndef G_OS_WIN32
 static GHashTable *procmime_get_mime_type_table        (void);
+#endif
 static MimeInfo *procmime_scan_file_short(const gchar *filename);
 static MimeInfo *procmime_scan_queue_file_short(const gchar *filename);
 static MimeInfo *procmime_scan_queue_file_full(const gchar *filename, gboolean short_scan);
@@ -144,6 +146,9 @@ static gboolean free_func(GNode *node, gpointer data)
        if (mimeinfo->privacy)
                privacy_free_privacydata(mimeinfo->privacy);
 
+       if (mimeinfo->sig_data)
+               privacy_free_signature_data(mimeinfo->sig_data);
+
        g_free(mimeinfo);
 
        return FALSE;
@@ -1110,6 +1115,7 @@ gchar *procmime_get_mime_type(const gchar *filename)
 #endif
 }
 
+#ifndef G_OS_WIN32
 static guint procmime_str_hash(gconstpointer gptr)
 {
        guint hash_result = 0;
@@ -1166,6 +1172,7 @@ static GHashTable *procmime_get_mime_type_table(void)
 
        return table;
 }
+#endif
 
 GList *procmime_get_mime_type_list(void)
 {
index e87a276245dcda00d09d8dd92661cfc04a91340e..8b6859f9b2f18b09418e0170589824d10499238d 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2012 Hiroyuki Yamamoto and the Claws Mail team
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2021 the Claws Mail team and Hiroyuki Yamamoto
  *
  * 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
@@ -29,6 +29,7 @@
 
 #include "utils.h"
 #include "proctypes.h"
+#include "privacy.h"
 typedef enum
 {
        ENC_7BIT,
@@ -149,6 +150,8 @@ struct _MimeInfo
 
        /* Privacy */
        struct _PrivacyData     *privacy;
+       GTask *last_sig_check_task;
+       SignatureData *sig_data;
 
        gboolean         broken;
 };
index 4c7efb5e3fe26b46978e52cf484cc28cc70100a2..1dc660190df0a822e43d4019ebd5c7e81bf3bbd0 100644 (file)
@@ -16,6 +16,7 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "config.h"
 #include "defs.h"
 
 #include <glib.h>
@@ -1291,8 +1292,8 @@ MsgInfo *procmsg_msginfo_copy(MsgInfo *msginfo)
        if (msginfo->extradata) {
                newmsginfo->extradata = g_new0(MsgInfoExtraData, 1);
                if (msginfo->extradata->avatars) {
-                       newmsginfo->extradata->avatars = slist_copy_deep(msginfo->extradata->avatars,
-                                                               (GCopyFunc) procmsg_msginfoavatar_copy);
+                       newmsginfo->extradata->avatars = g_slist_copy_deep(msginfo->extradata->avatars,
+                                                               (GCopyFunc) procmsg_msginfoavatar_copy, NULL);
                }
                MEMBDUP(extradata->dispositionnotificationto);
                MEMBDUP(extradata->returnreceiptto);
@@ -1354,8 +1355,8 @@ MsgInfo *procmsg_msginfo_get_full_info_from_file(MsgInfo *msginfo, const gchar *
                if (!msginfo->extradata->list_owner)
                        msginfo->extradata->list_owner = g_strdup(full_msginfo->extradata->list_owner);
                if (!msginfo->extradata->avatars)
-                       msginfo->extradata->avatars = slist_copy_deep(full_msginfo->extradata->avatars,
-                                                                       (GCopyFunc) procmsg_msginfoavatar_copy);
+                       msginfo->extradata->avatars = g_slist_copy_deep(full_msginfo->extradata->avatars,
+                                                                       (GCopyFunc) procmsg_msginfoavatar_copy, NULL);
                if (!msginfo->extradata->dispositionnotificationto)
                        msginfo->extradata->dispositionnotificationto = 
                                g_strdup(full_msginfo->extradata->dispositionnotificationto);
index 360859c3d0b1d334d3d1f40c88c9f7916ad90749..38ff749d22709849d94bb0c4a434bd841c507fd6 100644 (file)
@@ -17,6 +17,8 @@
  * 
  */
 
+#include "config.h"
+
 #include <glib.h>
 
 #include "utils.h"
index f188c0fb69a3599d2d87b6ac1151314b5a932728..a9a1ae08ce2ddce501827e651f466b29ef029121 100644 (file)
@@ -17,6 +17,7 @@
  * 
  */
 
+#include "config.h"
 #include "defs.h"
 
 #include <glib.h>
index d61e82efed5b75020f216d1d483b32df7acc4ea8..39e120ebdd92e053f0f7ebcd6f70de7ca30d6233 100644 (file)
@@ -16,6 +16,7 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "config.h"
 #include "defs.h"
 
 #include <glib.h>
index 660572f865289d5393e8e80414878a8e5130d6b9..24bb92b190fa138b620a0eb62192ce4ce58f7445 100644 (file)
 #include <gdk/gdk.h>
 #include <gtk/gtk.h>
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include "viewtypes.h"
 typedef struct _SummaryColumnState     SummaryColumnState;
 
index c52a4a134fa120ccf3f320036540092a22332430..8ff23f90140c57f09d41223eeabb4268a32c69f1 100644 (file)
@@ -1,3 +1,5 @@
+#include "config.h"
+
 #include <glib.h>
 #include <stdio.h>
 
index e15d2cdb403f5542f32233eed1b3c741e82daf18..9d2babf8a71150a1ecc9655b407b4192ec492516 100644 (file)
@@ -709,7 +709,8 @@ static void textview_add_part(TextView *textview, MimeInfo *mimeinfo)
                        if (charcount > 0)
                                gtk_text_buffer_insert(buffer, &iter, "\n", 1);
                        
-                       if (procmime_mimeinfo_parent(mimeinfo) == NULL)
+                       if (procmime_mimeinfo_parent(mimeinfo) == NULL &&
+                           !prefs_common.display_header_pane)
                                textview_show_tags(textview);
                        textview_show_header(textview, headers);
                        procheader_header_array_destroy(headers);