[Commits] [SCM] claws branch, gtk3, updated. 3.16.0-345-gcee37b8

ticho at claws-mail.org ticho at claws-mail.org
Fri Sep 14 11:31:32 CEST 2018


The branch, gtk3 has been updated
       via  cee37b8da30735cb8fcd8dd5b74a3aed599980d9 (commit)
       via  623a8e1505a8cd04e178ebc46b5c17c81f5eebff (commit)
       via  deaf6940f7b5cadf1d7f1b1cf763fc11be95fd5d (commit)
       via  61f57a631226d5d679f6273c89a0b3ba34291b2d (commit)
       via  144e8a29110b880489bb71c216998d0d495a6182 (commit)
       via  a87829727ca5baade7b7f28999a1a35cc6d4e9c0 (commit)
       via  f629eb09a122d844fa6be5d1cfa0ec488d9ac9a5 (commit)
       via  f1394c40f47d552f714821dc0e1281cb89c3450c (commit)
       via  52fd858d5a8607f8044fb5977c8a2e0358284e30 (commit)
       via  6c2c5640b5b1981835689626d1db5bd334e619af (commit)
       via  e1616992e7840d0498b098e49eaacbd76385304b (commit)
       via  97692c16db4e11f9c3207a05dbf4d0ac8f9768b6 (commit)
       via  63f4da58b0bbf5960b863af74d390e0019334c79 (commit)
       via  72b3051958acd40fcb03a66d4894407bc90eaa54 (commit)
       via  ce5e2d54bbcf82c9dad5c07b36b04461e7d98c5a (commit)
       via  bd176c91f1e54dd5a81b99be9b78e6046c881de5 (commit)
       via  e03ba6bc4c8208eae57d0ad641058446a7f79279 (commit)
       via  9b08d34901af73d99ff3f792df7e598465050710 (commit)
       via  67bf3b862690c0ee9184e86a478bb1604228860b (commit)
       via  c76dd4709f160b719d3b96c9e3ecca943a9fd975 (commit)
       via  ab7e2b272a7c5017296571c38cf0c263989a35ab (commit)
       via  592f6d132518eb0609953a178adffd20a9151d1b (commit)
       via  892aff4b19956a75c05b4a7373d2e1edfcfc01fe (commit)
       via  ff4c2884e57ce8edb5634db9cf61d76c2198247f (commit)
       via  92c7a4301377ba64de781d41e08127e5b8d3a778 (commit)
       via  a0a7b52b6eb1a13f6fa332498d48681feb94096e (commit)
       via  b4d2f3de0144c634b78e65465dd06589a91e5516 (commit)
       via  9b183f5b1138280863bb21c89c4813a1886d2872 (commit)
       via  83362ed4242d1fff927fb0cecf6bd2f22fde9e77 (commit)
       via  566182e3904ae4c37cf609d7f2d391ac40a86787 (commit)
       via  55724482001168c38b98c338aa6ec32da346a2a0 (commit)
      from  853d84f38d01664a55b5e65d22d9dec55d79c324 (commit)

Summary of changes:
 .gitignore                                         |    1 +
 INSTALL                                            |   54 +----
 Makefile.am                                        |    4 +
 NEWS                                               |    9 +
 README                                             |   26 +-
 RELEASE_NOTES                                      |  143 +----------
 appdata/Makefile.am                                |    2 +
 config/Makefile.am                                 |    2 +
 config/test-driver                                 |  148 +++++++++++
 configure.ac                                       |   36 ++-
 doc/Makefile.am                                    |    2 +
 doc/man/Makefile.am                                |    2 +
 m4/Makefile.am                                     |    2 +
 manual/Makefile.am                                 |    2 +
 manual/de/Makefile.am                              |    2 +
 manual/de/dist/Makefile.am                         |    2 +
 manual/de/dist/html/Makefile.am                    |    2 +
 manual/de/dist/pdf/Makefile.am                     |    2 +
 manual/de/dist/ps/Makefile.am                      |    2 +
 manual/de/dist/txt/Makefile.am                     |    2 +
 manual/dist/Makefile.am                            |    2 +
 manual/dist/html/Makefile.am                       |    2 +
 manual/dist/pdf/Makefile.am                        |    2 +
 manual/dist/ps/Makefile.am                         |    2 +
 manual/dist/txt/Makefile.am                        |    2 +
 manual/dtd/Makefile.am                             |    2 +
 manual/es/Makefile.am                              |    2 +
 manual/es/dist/Makefile.am                         |    2 +
 manual/es/dist/html/Makefile.am                    |    2 +
 manual/es/dist/pdf/Makefile.am                     |    2 +
 manual/es/dist/ps/Makefile.am                      |    2 +
 manual/es/dist/txt/Makefile.am                     |    2 +
 manual/fr/Makefile.am                              |    2 +
 manual/fr/dist/Makefile.am                         |    2 +
 manual/fr/dist/html/Makefile.am                    |    2 +
 manual/fr/dist/pdf/Makefile.am                     |    2 +
 manual/fr/dist/ps/Makefile.am                      |    2 +
 manual/fr/dist/txt/Makefile.am                     |    2 +
 manual/pl/Makefile.am                              |    2 +
 manual/pl/dist/Makefile.am                         |    2 +
 manual/pl/dist/html/Makefile.am                    |    2 +
 manual/pl/dist/pdf/Makefile.am                     |    2 +
 manual/pl/dist/ps/Makefile.am                      |    2 +
 manual/pl/dist/txt/Makefile.am                     |    2 +
 src/Makefile.am                                    |   12 +-
 src/action.c                                       |    1 +
 src/advsearch.c                                    |    2 +-
 src/common/Makefile.am                             |   14 +-
 src/{ => common}/codeconv.c                        |   35 ++-
 src/{ => common}/codeconv.h                        |    4 +
 src/common/md5.c                                   |   13 +-
 src/common/prefs.c                                 |   24 +-
 src/common/proxy.c                                 |   22 +-
 src/common/template.c                              |    2 +-
 src/common/tests/Makefile.am                       |   31 +++
 src/common/tests/codeconv_test.c                   |  101 ++++++++
 .../Makefile.am => src/common/tests/data/empty.xml |    0
 src/common/tests/md5_test.c                        |  256 ++++++++++++++++++++
 src/common/tests/mock_prefs_common_get_use_shred.h |    5 +
 src/common/tests/pkcs5_pbkdf2_test.c               |  121 +++++++++
 src/common/tests/xml_test.c                        |   39 +++
 src/{ => common}/unmime.c                          |    0
 src/{ => common}/unmime.h                          |    0
 src/common/utils.c                                 |   15 +-
 src/common/utils.h                                 |    2 -
 src/common/version.h.in                            |   10 +-
 src/common/xml.c                                   |    7 +-
 src/compose.c                                      |   50 +++-
 src/etpan/Makefile.am                              |    2 +
 src/folder_item_prefs.c                            |    9 +-
 src/folder_item_prefs.h                            |   12 +-
 src/gtk/Makefile.am                                |    2 +
 src/imap.c                                         |    4 -
 src/main.c                                         |   11 +-
 src/mainwindow.c                                   |    8 +-
 src/password.c                                     |   25 +-
 src/plugins/Makefile.am                            |    4 +
 src/plugins/acpi_notifier/Makefile.am              |    2 +
 src/plugins/address_keeper/Makefile.am             |    2 +
 src/plugins/archive/Makefile.am                    |    2 +
 src/plugins/att_remover/Makefile.am                |    2 +
 src/plugins/attachwarner/Makefile.am               |    2 +
 src/plugins/bogofilter/Makefile.am                 |    2 +
 src/plugins/bsfilter/Makefile.am                   |    2 +
 src/plugins/clamd/Makefile.am                      |    2 +
 src/plugins/clamd/libclamd/Makefile.am             |    2 +
 src/plugins/demo/Makefile.am                       |    2 +
 src/plugins/dillo/Makefile.am                      |    2 +
 src/plugins/fancy/Makefile.am                      |    2 +
 src/plugins/fancy/fancy_viewer.c                   |   43 +++-
 src/plugins/fetchinfo/Makefile.am                  |    2 +
 src/plugins/gdata/Makefile.am                      |    2 +
 src/plugins/libravatar/Makefile.am                 |    2 +
 src/plugins/mailmbox/Makefile.am                   |    2 +
 src/plugins/managesieve/Makefile.am                |    2 +
 src/plugins/newmail/Makefile.am                    |    2 +
 src/plugins/notification/Makefile.am               |    2 +
 src/plugins/notification/gtkhotkey/Makefile.am     |    2 +
 src/plugins/pdf_viewer/Makefile.am                 |    2 +
 src/plugins/perl/Makefile.am                       |    2 +
 src/plugins/perl/tools/Makefile.am                 |    2 +
 src/plugins/pgpcore/Makefile.am                    |    2 +
 src/plugins/pgpinline/Makefile.am                  |    2 +
 src/plugins/pgpmime/Makefile.am                    |    2 +
 src/plugins/python/Makefile.am                     |    2 +
 src/plugins/python/examples/Makefile.am            |    2 +
 src/plugins/rssyl/Makefile.am                      |    4 +
 src/plugins/rssyl/libfeed/Makefile.am              |    6 +
 src/plugins/rssyl/libfeed/parser_opml.c            |    2 +-
 src/plugins/rssyl/libfeed/tests/Makefile.am        |   22 ++
 src/plugins/rssyl/libfeed/tests/date_test.c        |   34 +++
 src/plugins/rssyl/libfeed/tests/feed_test.c        |   30 +++
 .../libfeed/tests/mock_procheader_date_parse.h     |    7 +
 src/plugins/rssyl/strutils.h                       |    2 +
 src/plugins/rssyl/tests/Makefile.am                |   17 ++
 src/plugins/rssyl/tests/strutils_test.c            |   53 ++++
 src/plugins/smime/Makefile.am                      |    2 +
 src/plugins/spam_report/Makefile.am                |    2 +
 src/plugins/spamassassin/Makefile.am               |    2 +
 src/plugins/tnef_parse/Makefile.am                 |    2 +
 src/plugins/vcalendar/Makefile.am                  |    2 +
 src/plugins/vcalendar/vcal_folder.c                |    2 +-
 src/prefs_account.c                                |    2 +-
 src/prefs_common.c                                 |    2 +-
 src/prefs_folder_item.c                            |   95 +++++++-
 src/procmsg.c                                      |    3 -
 src/tests/Makefile.am                              |   17 ++
 src/tests/entity_test.c                            |   40 +++
 src/tests/mock_debug_print.h                       |    2 +
 tests.mk                                           |   67 +++++
 tools/Makefile.am                                  |    2 +
 131 files changed, 1521 insertions(+), 333 deletions(-)
 create mode 100755 config/test-driver
 rename src/{ => common}/codeconv.c (98%)
 rename src/{ => common}/codeconv.h (98%)
 create mode 100644 src/common/tests/Makefile.am
 create mode 100644 src/common/tests/codeconv_test.c
 copy config/Makefile.am => src/common/tests/data/empty.xml (100%)
 create mode 100644 src/common/tests/md5_test.c
 create mode 100644 src/common/tests/mock_prefs_common_get_use_shred.h
 create mode 100644 src/common/tests/pkcs5_pbkdf2_test.c
 create mode 100644 src/common/tests/xml_test.c
 rename src/{ => common}/unmime.c (100%)
 rename src/{ => common}/unmime.h (100%)
 create mode 100644 src/plugins/rssyl/libfeed/tests/Makefile.am
 create mode 100644 src/plugins/rssyl/libfeed/tests/date_test.c
 create mode 100644 src/plugins/rssyl/libfeed/tests/feed_test.c
 create mode 100644 src/plugins/rssyl/libfeed/tests/mock_procheader_date_parse.h
 create mode 100644 src/plugins/rssyl/tests/Makefile.am
 create mode 100644 src/plugins/rssyl/tests/strutils_test.c
 create mode 100644 src/tests/Makefile.am
 create mode 100644 src/tests/entity_test.c
 create mode 100644 src/tests/mock_debug_print.h
 create mode 100644 tests.mk


- Log -----------------------------------------------------------------
commit cee37b8da30735cb8fcd8dd5b74a3aed599980d9
Author: Ricardo Mones <ricardo at mones.org>
Date:   Wed Sep 12 16:59:24 2018 +0200

    Remove dead code

diff --git a/src/common/utils.c b/src/common/utils.c
index bf20ec3..33eb31d 100644
--- a/src/common/utils.c
+++ b/src/common/utils.c
@@ -155,19 +155,6 @@ guint str_case_hash(gconstpointer key)
 	return h;
 }
 
-void ptr_array_free_strings(GPtrArray *array)
-{
-	gint i;
-	gchar *str;
-
-	cm_return_if_fail(array != NULL);
-
-	for (i = 0; i < array->len; i++) {
-		str = g_ptr_array_index(array, i);
-		g_free(str);
-	}
-}
-
 gint to_number(const gchar *nstr)
 {
 	register const gchar *p;
diff --git a/src/common/utils.h b/src/common/utils.h
index c09032f..3573d40 100644
--- a/src/common/utils.h
+++ b/src/common/utils.h
@@ -268,8 +268,6 @@ gint str_case_equal		(gconstpointer	 v,
 				 gconstpointer	 v2);
 guint str_case_hash		(gconstpointer	 key);
 
-void ptr_array_free_strings	(GPtrArray	*array);
-
 /* number-string conversion */
 gint to_number			(const gchar *nstr);
 gchar *itos_buf			(gchar	     *nstr,
diff --git a/src/imap.c b/src/imap.c
index 23232f8..4982b61 100644
--- a/src/imap.c
+++ b/src/imap.c
@@ -3210,19 +3210,15 @@ static FolderItem *imap_create_folder(Folder *folder, FolderItem *parent,
 	strtailchomp(new_name, '/');
 
 	if (strcasecmp(dirpath, "INBOX") != 0) {
-		GPtrArray *argbuf;
 		int r;
 		clist * lep_list;
 		
-		argbuf = g_ptr_array_new();
 		r = imap_threaded_list(folder, "", imap_path, &lep_list);
 		if (r != MAILIMAP_NO_ERROR) {
 			imap_handle_error(SESSION(session), NULL, r);
 			log_warning(LOG_PROTOCOL, _("can't create mailbox: LIST failed\n"));
 			g_free(imap_path);
 			g_free(dirpath);
-			ptr_array_free_strings(argbuf);
-			g_ptr_array_free(argbuf, TRUE);
 			return NULL;
 		}
 		

commit 623a8e1505a8cd04e178ebc46b5c17c81f5eebff
Author: Andrej Kacian <ticho at claws-mail.org>
Date:   Tue Sep 11 17:48:57 2018 +0200

    Remove unused macro G_STRING_APPEND_ENCODED_URI.

diff --git a/src/main.c b/src/main.c
index ce6de6a..398dadd 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1764,13 +1764,6 @@ static void exit_claws(MainWindow *mainwin)
 	claws_done();
 }
 
-#define G_STRING_APPEND_ENCODED_URI(gstring,source)	\
-	{						\
-		gchar tmpbuf[BUFFSIZE];			\
-		encode_uri(tmpbuf, BUFFSIZE, (source));	\
-		g_string_append((gstring), tmpbuf);	\
-	}
-
 #define G_PRINT_EXIT(msg)	\
 	{			\
 		g_print(msg);	\
@@ -1841,7 +1834,6 @@ static GString * parse_cmd_compose_from_file(const gchar *fn)
 	return body;
 }
 
-#undef G_STRING_APPEND_ENCODED_URI
 #undef G_PRINT_EXIT
 
 static void parse_cmd_opt(int argc, char *argv[])

commit deaf6940f7b5cadf1d7f1b1cf763fc11be95fd5d
Author: Paul <paul at claws-mail.org>
Date:   Mon Sep 10 13:30:05 2018 +0100

    fix warning dialogue when a re-edited draft compose window is closed after a send failure
    
    prevents unexpected loss of drafted message

diff --git a/src/compose.c b/src/compose.c
index 49ee00c..cf04e6f 100644
--- a/src/compose.c
+++ b/src/compose.c
@@ -10734,7 +10734,7 @@ static void compose_close_cb(GtkAction *action, gpointer data)
 			debug_print("couldn't lock mutex, probably sending\n");
 			return;
 		}
-		if (!reedit) {
+		if (!reedit || compose->folder->stype == F_DRAFT) {
 			val = alertpanel(_("Discard message"),
 				 _("This message has been modified. Discard it?"),
 				 _("_Discard"), _("_Save to Drafts"), GTK_STOCK_CANCEL,

commit 61f57a631226d5d679f6273c89a0b3ba34291b2d
Author: Andrej Kacian <ticho at claws-mail.org>
Date:   Fri Sep 7 22:19:43 2018 +0200

    Restore the hovering-over-link callback in Fancy viewer.
    
    We still need it to display the hovered-over link in statusbar.

diff --git a/src/plugins/fancy/fancy_viewer.c b/src/plugins/fancy/fancy_viewer.c
index 5cb133c..52a90e5 100644
--- a/src/plugins/fancy/fancy_viewer.c
+++ b/src/plugins/fancy/fancy_viewer.c
@@ -580,6 +580,13 @@ static void load_finished_cb(WebKitWebView *view, gint progress,
 	gtk_progress_bar_set_text(GTK_PROGRESS_BAR(viewer->progress), "");
 }
 
+static void over_link_cb(WebKitWebView *view, const gchar *wtf,
+		const gchar *link, FancyViewer *viewer, void *wtfa)
+{
+	/* Display the link in the bottom statusbar. */
+	gtk_label_set_text(GTK_LABEL(viewer->l_link), link);
+}
+
 static void load_progress_cb(WebKitWebView *view, GParamSpec* pspec,
 			     FancyViewer *viewer)
 {
@@ -1074,6 +1081,8 @@ static MimeViewer *fancy_viewer_create(void)
 			 G_CALLBACK(load_start_cb), viewer);
 	g_signal_connect(G_OBJECT(viewer->view), "load-finished",
 			 G_CALLBACK(load_finished_cb), viewer);
+	g_signal_connect(G_OBJECT(viewer->view), "hovering-over-link",
+			G_CALLBACK(over_link_cb), viewer);
 
 	g_signal_connect(G_OBJECT(viewer->view), "notify::progress",
 			 G_CALLBACK(load_progress_cb), viewer);

commit 144e8a29110b880489bb71c216998d0d495a6182
Author: wwp <subscript at free.fr>
Date:   Fri Sep 7 08:05:22 2018 +0200

    Add new folder options: enable/disable per-folder signing and
    encrypting (by default: obey to applicable account preference).

diff --git a/src/compose.c b/src/compose.c
index 4e22165..49ee00c 100644
--- a/src/compose.c
+++ b/src/compose.c
@@ -499,6 +499,7 @@ static void compose_update_privacy_system_menu_item(Compose * compose, gboolean
 static void compose_activate_privacy_system     (Compose *compose, 
                                          PrefsAccount *account,
 					 gboolean warn);
+static void compose_apply_folder_privacy_settings(Compose *compose, FolderItem *folder_item);
 static void compose_toggle_return_receipt_cb(GtkToggleAction *action,
 					 gpointer	 data);
 static void compose_toggle_remove_refs_cb(GtkToggleAction *action,
@@ -1014,6 +1015,7 @@ Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderI
 	cm_return_val_if_fail(account != NULL, NULL);
 
 	compose = compose_create(account, item, COMPOSE_NEW, FALSE);
+	compose_apply_folder_privacy_settings(compose, item);
 
 	/* override from name if mailto asked for it */
 	if (mailto_from) {
@@ -1566,6 +1568,7 @@ static Compose *compose_generic_reply(MsgInfo *msginfo,
 	cm_return_val_if_fail(account != NULL, NULL);
 
 	compose = compose_create(account, msginfo->folder, COMPOSE_REPLY, FALSE);
+	compose_apply_folder_privacy_settings(compose, msginfo->folder);
 
 	compose->updating = TRUE;
 
@@ -1753,6 +1756,7 @@ Compose *compose_forward(PrefsAccount *account, MsgInfo *msginfo,
 	else
 		mode = COMPOSE_FORWARD;
 	compose = compose_create(account, msginfo->folder, mode, batch);
+	compose_apply_folder_privacy_settings(compose, msginfo->folder);
 
 	compose->updating = TRUE;
 	compose->fwdinfo = procmsg_msginfo_get_full_info(msginfo);
@@ -1926,7 +1930,7 @@ Compose *compose_forward(PrefsAccount *account, MsgInfo *msginfo,
 
 	hooks_invoke(COMPOSE_CREATED_HOOKLIST, compose);
 
-        return compose;
+	return compose;
 }
 
 #undef INSERT_FW_HEADER
@@ -1970,6 +1974,7 @@ static Compose *compose_forward_multiple(PrefsAccount *account, GSList *msginfo_
 	}
 
 	compose = compose_create(account, ((MsgInfo *)msginfo_list->data)->folder, COMPOSE_FORWARD, FALSE);
+	compose_apply_folder_privacy_settings(compose, ((MsgInfo *)msginfo_list->data)->folder);
 
 	compose->updating = TRUE;
 
@@ -2381,6 +2386,7 @@ Compose *compose_reedit(MsgInfo *msginfo, gboolean batch)
 	} else {
 		compose_activate_privacy_system(compose, account, FALSE);
 	}
+	compose_apply_folder_privacy_settings(compose, msginfo->folder);
 
 	compose->targetinfo = procmsg_msginfo_copy(msginfo);
 	compose->targetinfo->tags = g_slist_copy(msginfo->tags);
@@ -2510,6 +2516,7 @@ Compose *compose_redirect(PrefsAccount *account, MsgInfo *msginfo,
 	cm_return_val_if_fail(account != NULL, NULL);
 
 	compose = compose_create(account, msginfo->folder, COMPOSE_REDIRECT, batch);
+	compose_apply_folder_privacy_settings(compose, msginfo->folder);
 
 	compose->updating = TRUE;
 
@@ -8332,8 +8339,8 @@ static Compose *compose_create(PrefsAccount *account,
 
 	/* Privacy Systems menu */
 	compose_update_privacy_systems_menu(compose);
-
 	compose_activate_privacy_system(compose, account, TRUE);
+
 	toolbar_set_style(compose->toolbar->toolbar, compose->handlebox, prefs_common.toolbar_style);
 	if (batch) {
 		gtk_widget_realize(window);
@@ -11543,6 +11550,20 @@ static void compose_activate_privacy_system(Compose *compose, PrefsAccount *acco
 	compose_update_privacy_system_menu_item(compose, warn);
 }
 
+static void compose_apply_folder_privacy_settings(Compose *compose, FolderItem *folder_item)
+{
+	if (folder_item != NULL) {
+		if (folder_item->prefs->always_sign != SIGN_OR_ENCRYPT_DEFAULT) {
+			compose_use_signing(compose,
+				(folder_item->prefs->always_sign == SIGN_OR_ENCRYPT_ALWAYS) ? TRUE : FALSE);
+		}
+		if (folder_item->prefs->always_encrypt != SIGN_OR_ENCRYPT_DEFAULT) {
+			compose_use_encryption(compose,
+				(folder_item->prefs->always_encrypt == SIGN_OR_ENCRYPT_ALWAYS) ? TRUE : FALSE);
+		}
+	}
+}
+
 static void compose_toggle_ruler_cb(GtkToggleAction *action, gpointer data)
 {
 	Compose *compose = (Compose *)data;
diff --git a/src/folder_item_prefs.c b/src/folder_item_prefs.c
index d65423b..874f18d 100644
--- a/src/folder_item_prefs.c
+++ b/src/folder_item_prefs.c
@@ -77,6 +77,10 @@ static PrefParam param[] = {
 	{"default_alt_dictionary", NULL, &tmp_prefs.default_alt_dictionary, P_STRING,
 	 NULL, NULL, NULL},
 #endif	 
+	{"always_sign", "0", &tmp_prefs.always_sign, P_ENUM,
+ 	 NULL, NULL, NULL},
+	{"always_encrypt", "0", &tmp_prefs.always_encrypt, P_ENUM,
+ 	 NULL, NULL, NULL},
 	{"save_copy_to_folder", NULL, &tmp_prefs.save_copy_to_folder, P_BOOL,
 	 NULL, NULL, NULL},
 	{"folder_color", "", &tmp_prefs.color, P_INT,
@@ -198,6 +202,8 @@ static FolderItemPrefs *folder_item_prefs_clear(FolderItemPrefs *prefs)
 	prefs->enable_default_alt_dictionary = FALSE;
 	prefs->default_alt_dictionary = NULL;
 #endif
+	prefs->always_sign = SIGN_OR_ENCRYPT_DEFAULT;
+	prefs->always_encrypt = SIGN_OR_ENCRYPT_DEFAULT;
 	prefs->save_copy_to_folder = FALSE;
 	prefs->color = 0;
 
@@ -305,6 +311,8 @@ void folder_item_prefs_copy_prefs(FolderItem * src, FolderItem * dest)
 	tmp_prefs.enable_default_alt_dictionary	= src->prefs->enable_default_alt_dictionary;
 	tmp_prefs.default_alt_dictionary	= g_strdup(src->prefs->default_alt_dictionary);
 #endif
+	tmp_prefs.always_sign    	= src->prefs->always_sign;
+	tmp_prefs.always_encrypt    = src->prefs->always_encrypt;
 	tmp_prefs.save_copy_to_folder		= src->prefs->save_copy_to_folder;
 	tmp_prefs.color				= src->prefs->color;
 
@@ -333,5 +341,4 @@ void folder_item_prefs_copy_prefs(FolderItem * src, FolderItem * dest)
 	dest->hide_read_threads = src->hide_read_threads;
 	dest->sort_key  = src->sort_key;
 	dest->sort_type = src->sort_type;
-
 }
diff --git a/src/folder_item_prefs.h b/src/folder_item_prefs.h
index 44e4998..aa649c4 100644
--- a/src/folder_item_prefs.h
+++ b/src/folder_item_prefs.h
@@ -31,12 +31,17 @@ typedef enum {
 	HTML_PROMOTE_NEVER,
 	HTML_PROMOTE_ALWAYS
 } HTMLPromoteType;
+typedef enum {
+	SIGN_OR_ENCRYPT_DEFAULT=0,
+	SIGN_OR_ENCRYPT_NEVER,
+	SIGN_OR_ENCRYPT_ALWAYS
+} SignOrEncryptType;
 
 struct _FolderItemPrefs {
 	gchar * directory;
 
-        int enable_processing; /* at start-up */
-        int enable_processing_when_opening;
+	int enable_processing; /* at start-up */
+	int enable_processing_when_opening;
 	GSList * processing;
 
 	int newmailcheck;
@@ -67,7 +72,8 @@ struct _FolderItemPrefs {
 	gchar *default_dictionary;
 	gboolean enable_default_alt_dictionary;
 	gchar *default_alt_dictionary;
-
+	SignOrEncryptType always_sign;
+	SignOrEncryptType always_encrypt;
 	gboolean save_copy_to_folder;
 	guint color;
 
diff --git a/src/prefs_folder_item.c b/src/prefs_folder_item.c
index df79bef..f04f908 100644
--- a/src/prefs_folder_item.c
+++ b/src/prefs_folder_item.c
@@ -134,6 +134,8 @@ struct _FolderItemComposePage
 	GtkWidget *combo_default_dictionary;
 	GtkWidget *combo_default_alt_dictionary;
 #endif
+	GtkWidget *always_sign;
+	GtkWidget *always_encrypt;
 
 	/* apply to sub folders */
 	GtkWidget *request_return_receipt_rec_checkbtn;
@@ -148,6 +150,8 @@ struct _FolderItemComposePage
 	GtkWidget *default_dictionary_rec_checkbtn;
 	GtkWidget *default_alt_dictionary_rec_checkbtn;
 #endif
+	GtkWidget *always_sign_rec_checkbtn;
+	GtkWidget *always_encrypt_rec_checkbtn;
 };
 
 struct _FolderItemTemplatesPage
@@ -663,7 +667,7 @@ static void prefs_folder_item_general_destroy_widget_func(PrefsPage *page_)
 
 /** \brief  Save the prefs in page to folder.
  *
- *  If the folder is not the one  specified in page->item, then only those properties 
+ *  If the folder is not the one specified in page->item, then only those properties 
  *  that have the relevant 'apply to sub folders' button checked are saved
  */
 static void general_save_folder_prefs(FolderItem *folder, FolderItemGeneralPage *page)
@@ -817,6 +821,7 @@ static void prefs_folder_item_compose_create_widget_func(PrefsPage * page_,
 	gchar *tr = NULL;
 
 	GtkWidget *table;
+	GtkWidget *hbox;
 	GtkWidget *label;
 	
 	GtkWidget *no_save_warning = NULL;
@@ -845,6 +850,10 @@ static void prefs_folder_item_compose_create_widget_func(PrefsPage * page_,
 	GtkWidget *default_alt_dictionary_rec_checkbtn = NULL;
 	gchar *dictionary;
 #endif
+	GtkWidget *always_sign;
+	GtkListStore *always_sign_menu;
+	GtkWidget *always_encrypt;
+	GtkListStore *always_encrypt_menu;
 	GtkWidget *request_return_receipt_rec_checkbtn = NULL;
 	GtkWidget *save_copy_to_folder_rec_checkbtn = NULL;
 	GtkWidget *default_to_rec_checkbtn = NULL;
@@ -853,6 +862,8 @@ static void prefs_folder_item_compose_create_widget_func(PrefsPage * page_,
 	GtkWidget *default_bcc_rec_checkbtn = NULL;
 	GtkWidget *default_replyto_rec_checkbtn = NULL;
 	GtkWidget *default_account_rec_checkbtn = NULL;
+	GtkWidget *always_sign_rec_checkbtn = NULL;
+	GtkWidget *always_encrypt_rec_checkbtn = NULL;
 
 	GList *cur_ac;
 	GList *account_list;
@@ -1131,7 +1142,7 @@ static void prefs_folder_item_compose_create_widget_func(PrefsPage * page_,
 	
 	rowcount++;
 
-	/* Default dictionary */
+	/* Default alternate dictionary */
 	checkbtn_enable_default_alt_dictionary = gtk_check_button_new_with_label(_("Default alternate dictionary"));
 	gtk_table_attach(GTK_TABLE(table), checkbtn_enable_default_alt_dictionary, 0, 1,
 	    		 rowcount, rowcount + 1, GTK_SHRINK | GTK_FILL, GTK_SHRINK, 0, 0);
@@ -1166,6 +1177,70 @@ static void prefs_folder_item_compose_create_widget_func(PrefsPage * page_,
 	rowcount++;
 #endif
 
+	/* PGP sign? */
+	hbox = gtk_hbox_new (FALSE, 2);
+	gtk_widget_show (hbox);
+	gtk_table_attach (GTK_TABLE(table), hbox, 0, 2,
+			rowcount, rowcount+1, GTK_FILL, GTK_FILL, 0, 0);
+
+	label = gtk_label_new(_("Always sign messages"));
+	gtk_widget_show (label);
+	gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+	always_sign = gtkut_sc_combobox_create (NULL, FALSE);
+	gtk_widget_show (always_sign);
+	gtk_box_pack_start (GTK_BOX(hbox), always_sign, FALSE, FALSE, 0);
+
+	always_sign_menu = GTK_LIST_STORE(gtk_combo_box_get_model(
+				GTK_COMBO_BOX(always_sign)));
+	COMBOBOX_ADD (always_sign_menu, _("Default"), SIGN_OR_ENCRYPT_DEFAULT);
+	COMBOBOX_ADD (always_sign_menu, _("No"), SIGN_OR_ENCRYPT_NEVER);
+	COMBOBOX_ADD (always_sign_menu, _("Yes"), SIGN_OR_ENCRYPT_ALWAYS);
+
+	combobox_select_by_data(GTK_COMBO_BOX(always_sign),
+			item->prefs->always_sign);
+
+	CLAWS_SET_TIP(hbox, _("\"Default\" will follow the applicable account preference"));
+
+	always_sign_rec_checkbtn = gtk_check_button_new();
+	gtk_widget_show (always_sign_rec_checkbtn);
+	gtk_table_attach(GTK_TABLE(table), always_sign_rec_checkbtn, 2, 3, 
+			 rowcount, rowcount + 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
+
+	rowcount++;
+
+	/* PGP encrypt? */
+	hbox = gtk_hbox_new (FALSE, 2);
+	gtk_widget_show (hbox);
+	gtk_table_attach (GTK_TABLE(table), hbox, 0, 2,
+			rowcount, rowcount+1, GTK_FILL, GTK_FILL, 0, 0);
+
+	label = gtk_label_new(_("Always encrypt messages"));
+	gtk_widget_show (label);
+	gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+	always_encrypt = gtkut_sc_combobox_create (NULL, FALSE);
+	gtk_widget_show (always_encrypt);
+	gtk_box_pack_start (GTK_BOX(hbox), always_encrypt, FALSE, FALSE, 0);
+
+	always_encrypt_menu = GTK_LIST_STORE(gtk_combo_box_get_model(
+				GTK_COMBO_BOX(always_encrypt)));
+	COMBOBOX_ADD (always_encrypt_menu, _("Default"), SIGN_OR_ENCRYPT_DEFAULT);
+	COMBOBOX_ADD (always_encrypt_menu, _("No"), SIGN_OR_ENCRYPT_NEVER);
+	COMBOBOX_ADD (always_encrypt_menu, _("Yes"), SIGN_OR_ENCRYPT_ALWAYS);
+
+	combobox_select_by_data(GTK_COMBO_BOX(always_encrypt),
+			item->prefs->always_encrypt);
+
+	CLAWS_SET_TIP(hbox, _("\"Default\" will follow the applicable account preference"));
+
+	always_encrypt_rec_checkbtn = gtk_check_button_new();
+	gtk_widget_show (always_encrypt_rec_checkbtn);
+	gtk_table_attach(GTK_TABLE(table), always_encrypt_rec_checkbtn, 2, 3, 
+			 rowcount, rowcount + 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
+
+	rowcount++;
+
 	gtk_widget_show_all(table);
 
 	page->window = GTK_WIDGET(window);
@@ -1191,6 +1266,8 @@ static void prefs_folder_item_compose_create_widget_func(PrefsPage * page_,
 	page->checkbtn_enable_default_alt_dictionary = checkbtn_enable_default_alt_dictionary;
 	page->combo_default_alt_dictionary = combo_default_alt_dictionary;
 #endif
+	page->always_sign = always_sign;
+	page->always_encrypt = always_encrypt;
 
 	page->request_return_receipt_rec_checkbtn = request_return_receipt_rec_checkbtn;
 	page->save_copy_to_folder_rec_checkbtn	  = save_copy_to_folder_rec_checkbtn;
@@ -1204,6 +1281,8 @@ static void prefs_folder_item_compose_create_widget_func(PrefsPage * page_,
 	page->default_dictionary_rec_checkbtn = default_dictionary_rec_checkbtn;
 	page->default_alt_dictionary_rec_checkbtn = default_alt_dictionary_rec_checkbtn;
 #endif
+	page->always_sign_rec_checkbtn = always_sign_rec_checkbtn;
+	page->always_encrypt_rec_checkbtn = always_encrypt_rec_checkbtn;
 
 	page->page.widget = table;
 }
@@ -1330,6 +1409,14 @@ static void compose_save_folder_prefs(FolderItem *folder, FolderItemComposePage
 				      GTK_COMBO_BOX(page->combo_default_alt_dictionary)));
 	}
 #endif
+	if (all || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->always_sign_rec_checkbtn))) {
+		prefs->always_sign = 
+				combobox_get_active_data(GTK_COMBO_BOX(page->always_sign));
+	}
+	if (all || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->always_encrypt_rec_checkbtn))) {
+		prefs->always_encrypt = 
+				combobox_get_active_data(GTK_COMBO_BOX(page->always_encrypt));
+	}
 
 	folder_item_prefs_save_config(folder);
 }	
@@ -1359,6 +1446,8 @@ static gboolean compose_save_recurse_func(GNode *node, gpointer data)
 	      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->default_dictionary_rec_checkbtn)) ||
 	      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->default_alt_dictionary_rec_checkbtn)) ||
 #endif
+	      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->always_sign_rec_checkbtn)) ||
+	      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->always_encrypt_rec_checkbtn)) ||
 	      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->default_reply_to_rec_checkbtn))
 			))
 		return TRUE;
@@ -1368,6 +1457,8 @@ static gboolean compose_save_recurse_func(GNode *node, gpointer data)
 	      || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->default_dictionary_rec_checkbtn))
 	      || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->default_alt_dictionary_rec_checkbtn))
 #endif
+	      || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->always_sign_rec_checkbtn))
+	      || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->always_encrypt_rec_checkbtn))
 		    ))
 		return TRUE;
 	else 

commit a87829727ca5baade7b7f28999a1a35cc6d4e9c0
Author: Andrej Kacian <ticho at claws-mail.org>
Date:   Thu Sep 6 23:31:16 2018 +0200

    Fix dangling pointer in proxy password handling.
    
    Initialize proxy_info.proxy_pass to NULL, and reset it
    back to NULL after use.

diff --git a/src/common/proxy.c b/src/common/proxy.c
index 7a30030..bffeb41 100644
--- a/src/common/proxy.c
+++ b/src/common/proxy.c
@@ -61,6 +61,7 @@ gint proxy_connect(SockInfo *sock, const gchar *hostname, gushort port,
 		if (proxy_info->proxy_pass != NULL) {
 			memset(proxy_info->proxy_pass, 0, strlen(proxy_info->proxy_pass));
 			g_free(proxy_info->proxy_pass);
+			proxy_info->proxy_pass = NULL;
 		}
 		return ret;
 	} else if (proxy_info->proxy_type == PROXY_SOCKS4) {
diff --git a/src/prefs_account.c b/src/prefs_account.c
index b49d221..ccb0796 100644
--- a/src/prefs_account.c
+++ b/src/prefs_account.c
@@ -874,7 +874,7 @@ static PrefParam proxy_param[] = {
 	&proxy_page.proxy_name_entry,
 	prefs_set_data_from_entry, prefs_set_entry},
 
-	{"proxy_pass", "", &tmp_ac_prefs.proxy_info.proxy_pass, P_PASSWORD,
+	{"proxy_pass", NULL, &tmp_ac_prefs.proxy_info.proxy_pass, P_PASSWORD,
 	NULL, NULL, NULL},
 
 
diff --git a/src/prefs_common.c b/src/prefs_common.c
index ed55ff4..3c74b05 100644
--- a/src/prefs_common.c
+++ b/src/prefs_common.c
@@ -1262,7 +1262,7 @@ static PrefParam param[] = {
 	{"proxy_port", "1080", &prefs_common.proxy_info.proxy_port, P_USHORT, NULL, NULL, NULL},
 	{"use_proxy_auth", "FALSE", &prefs_common.proxy_info.use_proxy_auth, P_BOOL, NULL, NULL, NULL},
 	{"proxy_name", "", &prefs_common.proxy_info.proxy_name, P_STRING, NULL, NULL, NULL},
-	{"proxy_pass", "", &prefs_common.proxy_info.proxy_pass, P_STRING, NULL, NULL, NULL},
+	{"proxy_pass", NULL, &prefs_common.proxy_info.proxy_pass, P_STRING, NULL, NULL, NULL},
 
 	{NULL, NULL, NULL, P_OTHER, NULL, NULL, NULL}
 };

commit f629eb09a122d844fa6be5d1cfa0ec488d9ac9a5
Author: Andrej Kacian <ticho at claws-mail.org>
Date:   Thu Sep 6 23:13:41 2018 +0200

    Show correct address:port in SOCKS5 proxy connection failure message.
    
    The address and port contained in the server response
    are what the proxy server has bound locally for the
    connection, not the destination address and port.

diff --git a/src/common/proxy.c b/src/common/proxy.c
index e790990..7a30030 100644
--- a/src/common/proxy.c
+++ b/src/common/proxy.c
@@ -254,25 +254,8 @@ gint socks5_connect(SockInfo *sock, const gchar *hostname, gushort port,
 		return -1;
 	}
 	if (socks_req[1] != 0) {
-		if (socks_req[3] == 1) { /* IPv4 address */
-			g_warning("socks5_connect: SOCKS5 connection to %u.%u.%u.%u:%u failed. (%u)", socks_req[4], socks_req[5], socks_req[6], socks_req[7], ntohs(*(gushort *)(socks_req + 8)), socks_req[1]);
-		} else if (socks_req[3] == 3) { /* Domain name */
-			gint hnlen = socks_req[4];
-			gchar *hn = malloc(hnlen + 1);
-			hn[hnlen] = '\0';
-			memcpy(hn, &socks_req[5], hnlen);
-			g_warning("socks5_connect: SOCKS5 connection to %s:%u failed. (%u)",
-					hn, ntohs(*(gushort *)(socks_req + 5 + hnlen)), socks_req[1]);
-			g_free(hn);
-		} else if (socks_req[3] == 4) { /* IPv6 address */
-			gint hnlen = 16;
-			gchar *hn = malloc(hnlen + 1);
-			hn[hnlen] = '\0';
-			memcpy(hn, &socks_req[4], hnlen);
-			g_warning("socks5_connect: SOCKS5 connection to IPv6 %s:%u failed. (%u)",
-					hn, ntohs(*(gushort *)(socks_req + 5 + hnlen)), socks_req[1]);
-			g_free(hn);
-		}
+		g_warning("socks5_connect: SOCKS5 connection to %s:%u failed. (%u)",
+				hostname, port, socks_req[1]);
 		return -1;
 	}
 

commit f1394c40f47d552f714821dc0e1281cb89c3450c
Author: Andrej Kacian <ticho at claws-mail.org>
Date:   Thu Sep 6 22:11:05 2018 +0200

    Handle corrupted decrypted passwords gracefully.
    
    Check whether the decrypted password is a valid UTF-8
    string, and return an empty string if not, instead of
    returning garbage, probably not NULL-terminated data,
    and causing problems down the road.

diff --git a/src/password.c b/src/password.c
index 8f764e3..463715b 100644
--- a/src/password.c
+++ b/src/password.c
@@ -418,6 +418,7 @@ gchar *password_decrypt_gnutls(const gchar *password,
 	unsigned char *buf;
 	guint rounds;
 	size_t commapos;
+	gboolean valid_utf8;
 
 	g_return_val_if_fail(password != NULL, NULL);
 	g_return_val_if_fail(decryption_passphrase != NULL, NULL);
@@ -522,7 +523,29 @@ gchar *password_decrypt_gnutls(const gchar *password,
 	g_free(iv.data);
 
 	/* 'buf+blocklen' should now be pointing to the plaintext
-	 * password string. The first block contains random data from the IV. */
+	 * password string.
+	 * (The first block contains random data from the IV.)
+	 *
+	 * At this point, it should be a valid UTF-8 string. Let's make sure. */
+
+	/* First, let's assume there's just garbage and play it safe
+	 * by looking for a first NULL byte within the decrypted range.
+	 * (We could really use g_strchr_len() here instead, but Glib
+	 * doesn't have that.) */
+	if (!g_strstr_len(buf + blocklen, len - blocklen, "\0")) {
+		debug_print("Could not find a NULL byte in the decrypted password.\n");
+		valid_utf8 = FALSE;
+	} else {
+		/* There is a NULL byte, we can rely on strlen() returning
+		 * a sane value, so we don't read past the end of the allocated
+		 * buffer. */
+		valid_utf8 = g_utf8_validate(buf + blocklen, strlen(buf + blocklen), NULL);
+	}
+
+	if (!valid_utf8)
+		debug_print("Decrypted password is not a valid UTF-8 string!\n");
+	cm_return_val_if_fail(valid_utf8, NULL);
+
 	tmp = g_strndup(buf + blocklen, strlen(buf + blocklen));
 	memset(buf, 0, len);
 	g_free(buf);

commit 52fd858d5a8607f8044fb5977c8a2e0358284e30
Author: Andrej Kacian <ticho at claws-mail.org>
Date:   Thu Sep 6 18:43:35 2018 +0200

    Avoid an unnecessary string copy in xml_attr_new_int().

diff --git a/src/common/xml.c b/src/common/xml.c
index 4127fd0..45fcd30 100644
--- a/src/common/xml.c
+++ b/src/common/xml.c
@@ -494,10 +494,8 @@ XMLAttr *xml_attr_new_int(const gchar *name, const gint value)
 
 	new_attr = g_new(XMLAttr, 1);
 	new_attr->name = XML_STRING_ADD(name);
-	new_attr->value = g_strdup(valuestr);
+	new_attr->value = valuestr;
  
-	g_free(valuestr);
-
 	return new_attr;
 }
 

commit 6c2c5640b5b1981835689626d1db5bd334e619af
Author: wwp <subscript at free.fr>
Date:   Thu Sep 6 16:21:15 2018 +0200

    Rename activate_privacy_system() to compose_activate_privacy_system().

diff --git a/src/compose.c b/src/compose.c
index 0904c35..4e22165 100644
--- a/src/compose.c
+++ b/src/compose.c
@@ -496,7 +496,7 @@ static void compose_toggle_encrypt_cb	(GtkToggleAction *action,
 					 gpointer	 data);
 static void compose_set_privacy_system_cb(GtkWidget *widget, gpointer data);
 static void compose_update_privacy_system_menu_item(Compose * compose, gboolean warn);
-static void activate_privacy_system     (Compose *compose, 
+static void compose_activate_privacy_system     (Compose *compose, 
                                          PrefsAccount *account,
 					 gboolean warn);
 static void compose_toggle_return_receipt_cb(GtkToggleAction *action,
@@ -2379,7 +2379,7 @@ Compose *compose_reedit(MsgInfo *msginfo, gboolean batch)
 		compose_use_encryption(compose, use_encryption);
 		compose_update_privacy_system_menu_item(compose, FALSE);
 	} else {
-		activate_privacy_system(compose, account, FALSE);
+		compose_activate_privacy_system(compose, account, FALSE);
 	}
 
 	compose->targetinfo = procmsg_msginfo_copy(msginfo);
@@ -4971,7 +4971,7 @@ static void compose_select_account(Compose *compose, PrefsAccount *account,
 	else
 		cm_toggle_menu_set_active_full(compose->ui_manager, "Menu/Options/Encrypt", FALSE);
 				       
-	activate_privacy_system(compose, account, FALSE);
+	compose_activate_privacy_system(compose, account, FALSE);
 
 	if (!init && compose->mode != COMPOSE_REDIRECT) {
 		undo_block(compose->undostruct);
@@ -8333,7 +8333,7 @@ static Compose *compose_create(PrefsAccount *account,
 	/* Privacy Systems menu */
 	compose_update_privacy_systems_menu(compose);
 
-	activate_privacy_system(compose, account, TRUE);
+	compose_activate_privacy_system(compose, account, TRUE);
 	toolbar_set_style(compose->toolbar->toolbar, compose->handlebox, prefs_common.toolbar_style);
 	if (batch) {
 		gtk_widget_realize(window);
@@ -11534,7 +11534,7 @@ static void compose_toggle_encrypt_cb(GtkToggleAction *action, gpointer data)
 	gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(compose->toolbar->privacy_encrypt_btn), compose->use_encryption);
 }
 
-static void activate_privacy_system(Compose *compose, PrefsAccount *account, gboolean warn) 
+static void compose_activate_privacy_system(Compose *compose, PrefsAccount *account, gboolean warn) 
 {
 	g_free(compose->privacy_system);
 	g_free(compose->encdata);

commit e1616992e7840d0498b098e49eaacbd76385304b
Author: Andrej Kacian <ticho at claws-mail.org>
Date:   Wed Sep 5 18:35:47 2018 +0200

    Bump up minimum required webkitgtk version to 1.10.0.
    
    That's when WebKitWebView's "context-menu" signal was
    added, we start using it in 288d3a708.

diff --git a/configure.ac b/configure.ac
index 468e810..95e6270 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1156,7 +1156,7 @@ AC_SUBST(EXPAT_CFLAGS)
 AC_SUBST(EXPAT_LIBS)
 
 dnl webkit *********************************************************************
-PKG_CHECK_MODULES(WEBKIT, webkit-1.0 >= 1.1.14, HAVE_WEBKIT=yes, HAVE_WEBKIT=no)
+PKG_CHECK_MODULES(WEBKIT, webkit-1.0 >= 1.10.0, HAVE_WEBKIT=yes, HAVE_WEBKIT=no)
 AC_SUBST(WEBKIT_LIBS)
 AC_SUBST(WEBKIT_CFLAGS)
 

commit 97692c16db4e11f9c3207a05dbf4d0ac8f9768b6
Author: Andrej Kacian <ticho at claws-mail.org>
Date:   Wed Sep 5 17:32:17 2018 +0200

    Fix links not being opened in browser when Fancy menu is opened with a keyboard.

diff --git a/src/plugins/fancy/fancy_viewer.c b/src/plugins/fancy/fancy_viewer.c
index 42fc16c..5cb133c 100644
--- a/src/plugins/fancy/fancy_viewer.c
+++ b/src/plugins/fancy/fancy_viewer.c
@@ -580,17 +580,6 @@ static void load_finished_cb(WebKitWebView *view, gint progress,
 	gtk_progress_bar_set_text(GTK_PROGRESS_BAR(viewer->progress), "");
 }
 
-static void over_link_cb(WebKitWebView *view, const gchar *wtf,
-			 const gchar *link, FancyViewer *viewer, void *wtfa)
-{
-	gtk_label_set_text(GTK_LABEL(viewer->l_link), link);
-	g_free(viewer->cur_link);
-	viewer->cur_link = NULL;
-	if(link) {
-		viewer->cur_link = g_strdup(link);
-	}
-}
-
 static void load_progress_cb(WebKitWebView *view, GParamSpec* pspec,
 			     FancyViewer *viewer)
 {
@@ -828,13 +817,35 @@ static void viewer_menu_handler(GtkWidget *menuitem, FancyViewer *viewer)
 	}
 }
 
-static gboolean populate_popup_cb (WebKitWebView *view, GtkWidget *menu,
-				   FancyViewer *viewer)
+static gboolean context_menu_cb (WebKitWebView *view, GtkWidget *menu,
+		WebKitHitTestResult *hit_test_result,
+		gboolean triggered_with_keyboard,
+		gpointer user_data)
 {
+	FancyViewer *viewer = (FancyViewer *)user_data;
 	Plugin *plugin = plugin_get_loaded_by_name("RSSyl");
+	WebKitHitTestResultContext context;
+	gchar *link_uri = NULL;
+
+	g_object_get(G_OBJECT(hit_test_result),
+			"context", &context,
+			"link-uri", &link_uri,
+			NULL);
+
+	debug_print("context %d, link-uri '%s'\n", context,
+			(link_uri != NULL ? link_uri : "(null)"));
+	if (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK &&
+			link_uri != NULL) {
+		if (viewer->cur_link != NULL)
+			g_free(viewer->cur_link);
+		/* g_object_get() already made a copy, no need to strdup() here */
+		viewer->cur_link = link_uri;
+	}
+
 	gtk_container_foreach(GTK_CONTAINER(menu),
 			      (GtkCallback)viewer_menu_handler,
 			      viewer);
+
 	if (plugin) {
 		GtkWidget *rssyl = gtk_image_menu_item_new_with_label(_("Import feed"));
 		GtkWidget *img = gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_MENU);
@@ -845,7 +856,8 @@ static gboolean populate_popup_cb (WebKitWebView *view, GtkWidget *menu,
 				 G_CALLBACK(import_feed_cb),
 				 (gpointer *) viewer);
 	}
-	return TRUE;
+
+	return FALSE;
 }
 
 static gint keypress_events_cb (GtkWidget *widget, GdkEventKey *event,
@@ -1062,8 +1074,6 @@ static MimeViewer *fancy_viewer_create(void)
 			 G_CALLBACK(load_start_cb), viewer);
 	g_signal_connect(G_OBJECT(viewer->view), "load-finished",
 			 G_CALLBACK(load_finished_cb), viewer);
-	g_signal_connect(G_OBJECT(viewer->view), "hovering-over-link",
-			 G_CALLBACK(over_link_cb), viewer);
 
 	g_signal_connect(G_OBJECT(viewer->view), "notify::progress",
 			 G_CALLBACK(load_progress_cb), viewer);
@@ -1075,8 +1085,8 @@ static MimeViewer *fancy_viewer_create(void)
 
 	g_signal_connect(G_OBJECT(viewer->view), "resource-request-starting",
 			G_CALLBACK(resource_request_starting_cb), viewer);
-	g_signal_connect(G_OBJECT(viewer->view), "populate-popup",
-			 G_CALLBACK(populate_popup_cb), viewer);
+	g_signal_connect(G_OBJECT(viewer->view), "context-menu",
+			G_CALLBACK(context_menu_cb), viewer);
 	g_signal_connect(G_OBJECT(viewer->view), "button-press-event",
 			 G_CALLBACK(press_button_cb), viewer);
 	g_signal_connect(G_OBJECT(viewer->view), "button-release-event",

commit 63f4da58b0bbf5960b863af74d390e0019334c79
Author: Andrej Kacian <ticho at claws-mail.org>
Date:   Wed Sep 5 00:17:59 2018 +0200

    Remove unused string copy from procmsg_msg_exist().

diff --git a/src/procmsg.c b/src/procmsg.c
index e484700..df05e9b 100644
--- a/src/procmsg.c
+++ b/src/procmsg.c
@@ -531,14 +531,11 @@ FILE *procmsg_open_message(MsgInfo *msginfo)
 
 gboolean procmsg_msg_exist(MsgInfo *msginfo)
 {
-	gchar *path;
 	gboolean ret;
 
 	if (!msginfo) return FALSE;
 
-	path = folder_item_get_path(msginfo->folder);
 	ret = !folder_item_is_msg_changed(msginfo->folder, msginfo);
-	g_free(path);
 
 	return ret;
 }

commit 72b3051958acd40fcb03a66d4894407bc90eaa54
Author: wwp <subscript at free.fr>
Date:   Mon Sep 3 12:17:12 2018 +0200

    Fix capitalization of a one Web[cC]al occurrence.

diff --git a/src/plugins/vcalendar/vcal_folder.c b/src/plugins/vcalendar/vcal_folder.c
index 9f00a9b..4cde1bc 100644
--- a/src/plugins/vcalendar/vcal_folder.c
+++ b/src/plugins/vcalendar/vcal_folder.c
@@ -1948,7 +1948,7 @@ static void subscribe_cal_cb(GtkAction *action, gpointer data)
 	gchar *uri = NULL;
 	gchar *tmp = NULL;
 
-	tmp = input_dialog(_("Subscribe to Webcal"), _("Enter the WebCal URL:"), NULL);
+	tmp = input_dialog(_("Subscribe to Webcal"), _("Enter the Webcal URL:"), NULL);
 	if (tmp == NULL)
 		return;
 	

commit ce5e2d54bbcf82c9dad5c07b36b04461e7d98c5a
Author: Ricardo Mones <ricardo at mones.org>
Date:   Fri Aug 31 20:36:54 2018 +0200

    Fix bug #3418 ‘Building on a Cross Compiling toolchain doesn't work’
    
    The bug is really fixed in commit 8eee2fd5ddb9d24d8f58bf88afdea8ca67daaea5
    This only adds a slight modification of the remaining portion of the
    patch checking the macro itself, from the original attached to the bug
    by ridai.govinda at gmail.com.

diff --git a/configure.ac b/configure.ac
index c4b3e48..468e810 100644
--- a/configure.ac
+++ b/configure.ac
@@ -65,6 +65,14 @@ AC_SUBST(GIT_VERSION)
 AC_CHECK_PROG(HAVE_GTK_ICON_CACHE, gtk-update-icon-cache, yes, no)
 AM_CONDITIONAL(UPDATE_GTK_ICON_CACHE, test x"$HAVE_GTK_ICON_CACHE" = xyes)
 
+dnl Require pkg-config
+m4_ifndef([PKG_PROG_PKG_CONFIG],
+    [m4_fatal([Could not locate the pkg-config autoconf macros. These
+are usually located in /usr/share/aclocal/pkg.m4. If your macros
+are in a different location, try setting the environment variable
+ACLOCAL_FLAGS before running ./autogen.sh or autoreconf again. E.g.:
+export ACLOCAL_FLAGS="-I/other/macro/dir"])
+])
 PKG_PROG_PKG_CONFIG
 
 dnl libtool versioning

commit bd176c91f1e54dd5a81b99be9b78e6046c881de5
Author: Andrej Kacian <ticho at claws-mail.org>
Date:   Fri Aug 31 14:39:41 2018 +0200

    Updated INSTALL file.
    
    Updated required GTK+ version, and removed the outdated
    list of configure options. The existing reference to --help
    should suffice there.

diff --git a/INSTALL b/INSTALL
index 7ff1786..a9a2b77 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,7 +1,7 @@
 Installation
 ============
 
-This program requires GTK+ 2.16 or higher to be compiled.
+This program requires GTK+ 2.24 or higher to be compiled.
 
 Build it
 ========
@@ -22,6 +22,7 @@ To run, just type:
 
 % claws-mail
 
+
 Additional libraries or programs
 ================================
 only needed if you require the additional functionality
@@ -100,57 +101,12 @@ SpamAssassin
     for SpamAssassin plugin support
     http://spamassassin.apache.org/
 
+
 Options for configure script
 ============================
+For list of available options, refer to "./configure --help".
+
 Most options are automatically enabled if the dependencies
 are matched.
 
-  --with-config-dir=RCDIR      	    local config dir (default: ~/.claws-mail)
-  --disable-compface  		    disable compface (X-Face) support
-  --disable-ipv6      		    disable IPv6 support
-  --disable-libsm                   disable Session Management support
-  --disable-gnutls    		    disable GnuTLS support
-  --disable-libetpan		    disable IMAP4 and NNTP support
-  --disable-enchant     	    disable Enchant support
-  --disable-dbus                    disable D-Bus support
-  --disable-ldap       		    disable LDAP support
-  --disable-jpilot     		    disable JPilot support
-  --disable-networkmanager          disable NetworkManager support
-  --disable-startup-notification    disable startup notification support
-  --disable-valgrind                disable valgrind support for debugging
-  --enable-crash-dialog   	    enable crash dialog
-  --disable-startup-notification    disable startup notification support
-  --disable-acpi_notifier-plugin    do not build ACPI notifier plugin
-  --disable-address_keeper-plugin   do not build Address Keeper plugin
-  --disable-archive-plugin          do not build Archive plugin
-  --disable-att_remover-plugin      do not build Att Remover plugin
-  --disable-attachwarner-plugin     do not build Attachwarner plugin
-  --disable-bogofilter-plugin       do not build Bogofilter plugin
-  --disable-bsfilter-plugin         do not build BSfilter plugin
-  --disable-clamd-plugin            do not build Clamd plugin
-  --disable-fancy-plugin            do not build Fancy plugin
-  --disable-fetchinfo-plugin        do not build Fetchinfo plugin
-  --disable-gdata-plugin            do not build GData plugin
-  --disable-libravatar-plugin       do not build Libravatar plugin
-  --disable-mailmbox-plugin         do not build MailMbox plugin
-  --disable-managesieve-plugin      do not build ManageSieve plugin
-  --disable-newmail-plugin          do not build NewMail plugin
-  --disable-notification-plugin     do not build Notification plugin
-  --disable-pdf_viewer-plugin       do not build PDF Viewer plugin
-  --disable-perl-plugin             do not build Perl plugin
-  --disable-python-plugin           do not build Python plugin
-  --disable-pgpcore-plugin          do not build PGP/Core plugin
-  --disable-pgpmime-plugin          do not build PGP/MIME plugin
-  --disable-pgpinline-plugin        do not build PGP/Inline plugin
-  --disable-rssyl-plugin            do not build RSSyl plugin
-  --disable-smime-plugin            do not build S/MIME plugin
-  --disable-spamassassin-plugin     do not build SpamAssassin plugin
-  --disable-spam_report-plugin      do not build Spam Report plugin
-  --disable-tnef_parse-plugin       do not build TNEF Parse plugin
-  --disable-vcalendar-plugin        do not build vCalendar plugin
-  --disable-manual		    do not build user manuals
-  --disable-nls           	    do not use Native Language Support
-
-For other options, refer to ./configure --help .
-
 

commit e03ba6bc4c8208eae57d0ad641058446a7f79279
Author: Andrej Kacian <ticho at claws-mail.org>
Date:   Fri Aug 31 13:48:30 2018 +0200

    Added unit test framework, and some initial unit tests.

diff --git a/.gitignore b/.gitignore
index 0cb7868..bebe946 100644
--- a/.gitignore
+++ b/.gitignore
@@ -102,6 +102,7 @@ Makefile.in
 /src/matcher_parser_parse.c
 /src/matcher_parser_parse.h
 /src/plugins/notification/gtkhotkey/x11/.dirstamp
+*_test
 /src/quote_fmt_lex.c
 /src/quote_fmt_parse.c
 /src/quote_fmt_parse.h
diff --git a/Makefile.am b/Makefile.am
index 3fdb4aa..cbbe2f2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3,6 +3,10 @@
 # terms of the General Public License version 3 (or later).
 # See COPYING file for license details.
 
+if BUILD_TESTS
+include $(top_srcdir)/tests.mk
+endif
+
 ACLOCAL_AMFLAGS = -I m4
 AUTOMAKE_OPTIONS = dist-bzip2 dist-xz
 
diff --git a/appdata/Makefile.am b/appdata/Makefile.am
index 15066a2..30e47f5 100644
--- a/appdata/Makefile.am
+++ b/appdata/Makefile.am
@@ -40,3 +40,5 @@ appdata_DATA = $(appdata_in_files:.xml.in=.xml)
 
 EXTRA_DIST = $(appdata_DATA) $(appdata_in_files)
 
+
+.PHONY: test
diff --git a/config/Makefile.am b/config/Makefile.am
index e69de29..d4b3f0a 100644
--- a/config/Makefile.am
+++ b/config/Makefile.am
@@ -0,0 +1,2 @@
+
+.PHONY: test
diff --git a/config/test-driver b/config/test-driver
new file mode 100755
index 0000000..0218a01
--- /dev/null
+++ b/config/test-driver
@@ -0,0 +1,148 @@
+#! /bin/sh
+# test-driver - basic testsuite driver script.
+
+scriptversion=2016-01-11.22; # UTC
+
+# Copyright (C) 2011-2017 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake at gnu.org> or send patches to
+# <automake-patches at gnu.org>.
+
+# Make unconditional expansion of undefined variables an error.  This
+# helps a lot in preventing typo-related bugs.
+set -u
+
+usage_error ()
+{
+  echo "$0: $*" >&2
+  print_usage >&2
+  exit 2
+}
+
+print_usage ()
+{
+  cat <<END
+Usage:
+  test-driver --test-name=NAME --log-file=PATH --trs-file=PATH
+              [--expect-failure={yes|no}] [--color-tests={yes|no}]
+              [--enable-hard-errors={yes|no}] [--]
+              TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS]
+The '--test-name', '--log-file' and '--trs-file' options are mandatory.
+END
+}
+
+test_name= # Used for reporting.
+log_file=  # Where to save the output of the test script.
+trs_file=  # Where to save the metadata of the test run.
+expect_failure=no
+color_tests=no
+enable_hard_errors=yes
+while test $# -gt 0; do
+  case $1 in
+  --help) print_usage; exit $?;;
+  --version) echo "test-driver $scriptversion"; exit $?;;
+  --test-name) test_name=$2; shift;;
+  --log-file) log_file=$2; shift;;
+  --trs-file) trs_file=$2; shift;;
+  --color-tests) color_tests=$2; shift;;
+  --expect-failure) expect_failure=$2; shift;;
+  --enable-hard-errors) enable_hard_errors=$2; shift;;
+  --) shift; break;;
+  -*) usage_error "invalid option: '$1'";;
+   *) break;;
+  esac
+  shift
+done
+
+missing_opts=
+test x"$test_name" = x && missing_opts="$missing_opts --test-name"
+test x"$log_file"  = x && missing_opts="$missing_opts --log-file"
+test x"$trs_file"  = x && missing_opts="$missing_opts --trs-file"
+if test x"$missing_opts" != x; then
+  usage_error "the following mandatory options are missing:$missing_opts"
+fi
+
+if test $# -eq 0; then
+  usage_error "missing argument"
+fi
+
+if test $color_tests = yes; then
+  # Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.
+  red='' # Red.
+  grn='' # Green.
+  lgn='' # Light green.
+  blu='' # Blue.
+  mgn='' # Magenta.
+  std=''     # No color.
+else
+  red= grn= lgn= blu= mgn= std=
+fi
+
+do_exit='rm -f $log_file $trs_file; (exit $st); exit $st'
+trap "st=129; $do_exit" 1
+trap "st=130; $do_exit" 2
+trap "st=141; $do_exit" 13
+trap "st=143; $do_exit" 15
+
+# Test script is run here.
+"$@" >$log_file 2>&1
+estatus=$?
+
+if test $enable_hard_errors = no && test $estatus -eq 99; then
+  tweaked_estatus=1
+else
+  tweaked_estatus=$estatus
+fi
+
+case $tweaked_estatus:$expect_failure in
+  0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
+  0:*)   col=$grn res=PASS  recheck=no  gcopy=no;;
+  77:*)  col=$blu res=SKIP  recheck=no  gcopy=yes;;
+  99:*)  col=$mgn res=ERROR recheck=yes gcopy=yes;;
+  *:yes) col=$lgn res=XFAIL recheck=no  gcopy=yes;;
+  *:*)   col=$red res=FAIL  recheck=yes gcopy=yes;;
+esac
+
+# Report the test outcome and exit status in the logs, so that one can
+# know whether the test passed or failed simply by looking at the '.log'
+# file, without the need of also peaking into the corresponding '.trs'
+# file (automake bug#11814).
+echo "$res $test_name (exit status: $estatus)" >>$log_file
+
+# Report outcome to console.
+echo "${col}${res}${std}: $test_name"
+
+# Register the test result, and other relevant metadata.
+echo ":test-result: $res" > $trs_file
+echo ":global-test-result: $res" >> $trs_file
+echo ":recheck: $recheck" >> $trs_file
+echo ":copy-in-global-log: $gcopy" >> $trs_file
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/configure.ac b/configure.ac
index 05dc923..c4b3e48 100644
--- a/configure.ac
+++ b/configure.ac
@@ -292,6 +292,10 @@ AC_ARG_ENABLE(svg,
         [  --disable-svg                   Do not build SVG support],
         [enable_svg=$enableval], [enable_svg=yes])
 
+AC_ARG_ENABLE(tests,
+				[ --enable-tests                   Build unit tests],
+				[enable_tests=$enableval], [enable_tests=no])
+
 manualdir='${docdir}/manual'
 AC_ARG_WITH(manualdir,
 	[  --with-manualdir=DIR    Manual directory],
@@ -953,6 +957,14 @@ else
 fi
 AM_CONDITIONAL(CLAWS_VALGRIND, test x"$enable_valgrind" = x"yes")
 
+AC_MSG_CHECKING([whether to build unit tests])
+if test x$enable_tests = xyes; then
+	AC_MSG_RESULT(yes)
+else
+	AC_MSG_RESULT(no)
+fi
+AM_CONDITIONAL(BUILD_TESTS, test "x$enable_tests" = "xyes")
+
 dnl *************************
 dnl ** section for plugins **
 dnl *************************
@@ -1085,7 +1097,7 @@ AC_ARG_ENABLE(vcalendar-plugin,
 
 dnl disabled by default
 AC_ARG_ENABLE(demo-plugin,
-		[  --enable-demo-plugin		Build demo plugin],
+		[  --enable-demo-plugin            Build demo plugin],
 		[enable_demo_plugin=$enableval], [enable_demo_plugin=no])
 
 
@@ -2017,6 +2029,7 @@ src/common/version.h
 src/Makefile
 src/common/Makefile
 src/common/passcrypt.h
+src/common/tests/Makefile
 src/gtk/Makefile
 src/etpan/Makefile
 src/plugins/Makefile
@@ -2049,12 +2062,15 @@ src/plugins/pgpcore/Makefile
 src/plugins/pgpmime/Makefile
 src/plugins/pgpinline/Makefile
 src/plugins/rssyl/Makefile
+src/plugins/rssyl/tests/Makefile
 src/plugins/rssyl/libfeed/Makefile
+src/plugins/rssyl/libfeed/tests/Makefile
 src/plugins/smime/Makefile
 src/plugins/spamassassin/Makefile
 src/plugins/spam_report/Makefile
 src/plugins/tnef_parse/Makefile
 src/plugins/vcalendar/Makefile
+src/tests/Makefile
 doc/Makefile
 doc/man/Makefile
 tools/Makefile
@@ -2108,6 +2124,7 @@ echo "Generic UMPC code  : $enable_generic_umpc"
 echo "SVG support        : $enable_svg"
 echo "Config dir         : $ac_cv_with_config_dir"
 echo "Password crypto    : $pwd_crypto"
+echo "Unit tests         : $enable_tests"
 
 echo "Plugins"
 echo "   Built:"
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 5beeea0..a808617 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -4,3 +4,5 @@
 # See COPYING file for license details.
 
 SUBDIRS = man
+
+.PHONY: test
diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
index 54e06ae..c2c91a4 100644
--- a/doc/man/Makefile.am
+++ b/doc/man/Makefile.am
@@ -7,3 +7,5 @@ man_MANS = \
      claws-mail.1
 
 EXTRA_DIST = $(man_MANS)
+
+.PHONY: test
diff --git a/m4/Makefile.am b/m4/Makefile.am
index b409865..be424a8 100644
--- a/m4/Makefile.am
+++ b/m4/Makefile.am
@@ -14,3 +14,5 @@ EXTRA_DIST = codeset.m4 glibc21.m4 intdiv0.m4 intmax.m4 inttypes.m4 inttypes_h.m
 	missing/gdk-pixbuf.m4 \
 	missing/gettext.m4 \
 	missing/gpgme.m4
+
+.PHONY: test
diff --git a/manual/Makefile.am b/manual/Makefile.am
index 179cd66..32f2495 100644
--- a/manual/Makefile.am
+++ b/manual/Makefile.am
@@ -21,3 +21,5 @@ EXTRA_DIST = \
 	plugins.xml \
 	starting.xml \
 	claws-mail-manual.xml
+
+.PHONY: test
diff --git a/manual/de/Makefile.am b/manual/de/Makefile.am
index 00f1ca8..1a605a6 100644
--- a/manual/de/Makefile.am
+++ b/manual/de/Makefile.am
@@ -21,3 +21,5 @@ EXTRA_DIST = \
 	plugins.xml \
 	starting.xml \
 	claws-mail-manual.xml
+
+.PHONY: test
diff --git a/manual/de/dist/Makefile.am b/manual/de/dist/Makefile.am
index 9bff2bd..c19a2fd 100644
--- a/manual/de/dist/Makefile.am
+++ b/manual/de/dist/Makefile.am
@@ -4,3 +4,5 @@
 # See COPYING file for license details.
 
 SUBDIRS=html pdf ps txt
+
+.PHONY: test
diff --git a/manual/de/dist/html/Makefile.am b/manual/de/dist/html/Makefile.am
index 3560fd4..9b09880 100644
--- a/manual/de/dist/html/Makefile.am
+++ b/manual/de/dist/html/Makefile.am
@@ -31,3 +31,5 @@ maintainer-clean:
 	-rm claws-mail-manual.html
 	-rm claws-mail-manual.html.raw
 endif
+
+.PHONY: test
diff --git a/manual/de/dist/pdf/Makefile.am b/manual/de/dist/pdf/Makefile.am
index 050a7d9..c5a3b9e 100644
--- a/manual/de/dist/pdf/Makefile.am
+++ b/manual/de/dist/pdf/Makefile.am
@@ -27,3 +27,5 @@ claws-mail-manual.pdf: \
 maintainer-clean:
 	-rm claws-mail-manual.pdf claws-mail-manual.fo claws-mail-manual.xsl
 endif
+
+.PHONY: test
diff --git a/manual/de/dist/ps/Makefile.am b/manual/de/dist/ps/Makefile.am
index 96a9069..8c2ca03 100644
--- a/manual/de/dist/ps/Makefile.am
+++ b/manual/de/dist/ps/Makefile.am
@@ -27,3 +27,5 @@ claws-mail-manual.ps: \
 maintainer-clean:
 	-rm claws-mail-manual.ps
 endif
+
+.PHONY: test
diff --git a/manual/de/dist/txt/Makefile.am b/manual/de/dist/txt/Makefile.am
index 020fbf2..26017b6 100644
--- a/manual/de/dist/txt/Makefile.am
+++ b/manual/de/dist/txt/Makefile.am
@@ -27,3 +27,5 @@ claws-mail-manual.txt: \
 maintainer-clean:
 	-rm claws-mail-manual.txt
 endif
+
+.PHONY: test
diff --git a/manual/dist/Makefile.am b/manual/dist/Makefile.am
index 9bff2bd..c19a2fd 100644
--- a/manual/dist/Makefile.am
+++ b/manual/dist/Makefile.am
@@ -4,3 +4,5 @@
 # See COPYING file for license details.
 
 SUBDIRS=html pdf ps txt
+
+.PHONY: test
diff --git a/manual/dist/html/Makefile.am b/manual/dist/html/Makefile.am
index 3f66e1c..cf1d577 100644
--- a/manual/dist/html/Makefile.am
+++ b/manual/dist/html/Makefile.am
@@ -31,3 +31,5 @@ maintainer-clean:
 	-rm claws-mail-manual.html
 	-rm claws-mail-manual.html.raw
 endif
+
+.PHONY: test
diff --git a/manual/dist/pdf/Makefile.am b/manual/dist/pdf/Makefile.am
index 2a78f05..10329e2 100644
--- a/manual/dist/pdf/Makefile.am
+++ b/manual/dist/pdf/Makefile.am
@@ -27,3 +27,5 @@ claws-mail-manual.pdf: \
 maintainer-clean:
 	-rm claws-mail-manual.pdf claws-mail-manual.fo claws-mail-manual.xsl
 endif
+
+.PHONY: test
diff --git a/manual/dist/ps/Makefile.am b/manual/dist/ps/Makefile.am
index d4f067c..0c82b57 100644
--- a/manual/dist/ps/Makefile.am
+++ b/manual/dist/ps/Makefile.am
@@ -27,3 +27,5 @@ claws-mail-manual.ps: \
 maintainer-clean:
 	-rm claws-mail-manual.ps
 endif
+
+.PHONY: test
diff --git a/manual/dist/txt/Makefile.am b/manual/dist/txt/Makefile.am
index 34ddc40..afda992 100644
--- a/manual/dist/txt/Makefile.am
+++ b/manual/dist/txt/Makefile.am
@@ -27,3 +27,5 @@ claws-mail-manual.txt: \
 maintainer-clean:
 	-rm claws-mail-manual.txt
 endif
+
+.PHONY: test
diff --git a/manual/dtd/Makefile.am b/manual/dtd/Makefile.am
index 0c134f1..024b07f 100644
--- a/manual/dtd/Makefile.am
+++ b/manual/dtd/Makefile.am
@@ -5,3 +5,5 @@
 
 EXTRA_DIST= \
 	manual.dsl  sdocbook.dtd
+
+.PHONY: test
diff --git a/manual/es/Makefile.am b/manual/es/Makefile.am
index 00f1ca8..1a605a6 100644
--- a/manual/es/Makefile.am
+++ b/manual/es/Makefile.am
@@ -21,3 +21,5 @@ EXTRA_DIST = \
 	plugins.xml \
 	starting.xml \
 	claws-mail-manual.xml
+
+.PHONY: test
diff --git a/manual/es/dist/Makefile.am b/manual/es/dist/Makefile.am
index 9bff2bd..c19a2fd 100644
--- a/manual/es/dist/Makefile.am
+++ b/manual/es/dist/Makefile.am
@@ -4,3 +4,5 @@
 # See COPYING file for license details.
 
 SUBDIRS=html pdf ps txt
+
+.PHONY: test
diff --git a/manual/es/dist/html/Makefile.am b/manual/es/dist/html/Makefile.am
index 155d8f9..05cec3a 100644
--- a/manual/es/dist/html/Makefile.am
+++ b/manual/es/dist/html/Makefile.am
@@ -31,3 +31,5 @@ maintainer-clean:
 	-rm claws-mail-manual.html
 	-rm claws-mail-manual.html.raw
 endif
+
+.PHONY: test
diff --git a/manual/es/dist/pdf/Makefile.am b/manual/es/dist/pdf/Makefile.am
index 4382322..ac779fb 100644
--- a/manual/es/dist/pdf/Makefile.am
+++ b/manual/es/dist/pdf/Makefile.am
@@ -27,3 +27,5 @@ claws-mail-manual.pdf: \
 maintainer-clean:
 	-rm claws-mail-manual.pdf claws-mail-manual.fo claws-mail-manual.xsl
 endif
+
+.PHONY: test
diff --git a/manual/es/dist/ps/Makefile.am b/manual/es/dist/ps/Makefile.am
index 7b26017..fa3e936 100644
--- a/manual/es/dist/ps/Makefile.am
+++ b/manual/es/dist/ps/Makefile.am
@@ -27,3 +27,5 @@ claws-mail-manual.ps: \
 maintainer-clean:
 	-rm claws-mail-manual.ps
 endif
+
+.PHONY: test
diff --git a/manual/es/dist/txt/Makefile.am b/manual/es/dist/txt/Makefile.am
index d3c7b61..8ced198 100644
--- a/manual/es/dist/txt/Makefile.am
+++ b/manual/es/dist/txt/Makefile.am
@@ -27,3 +27,5 @@ claws-mail-manual.txt: \
 maintainer-clean:
 	-rm claws-mail-manual.txt
 endif
+
+.PHONY: test
diff --git a/manual/fr/Makefile.am b/manual/fr/Makefile.am
index 00f1ca8..1a605a6 100644
--- a/manual/fr/Makefile.am
+++ b/manual/fr/Makefile.am
@@ -21,3 +21,5 @@ EXTRA_DIST = \
 	plugins.xml \
 	starting.xml \
 	claws-mail-manual.xml
+
+.PHONY: test
diff --git a/manual/fr/dist/Makefile.am b/manual/fr/dist/Makefile.am
index 9bff2bd..c19a2fd 100644
--- a/manual/fr/dist/Makefile.am
+++ b/manual/fr/dist/Makefile.am
@@ -4,3 +4,5 @@
 # See COPYING file for license details.
 
 SUBDIRS=html pdf ps txt
+
+.PHONY: test
diff --git a/manual/fr/dist/html/Makefile.am b/manual/fr/dist/html/Makefile.am
index a44d39d..0a04981 100644
--- a/manual/fr/dist/html/Makefile.am
+++ b/manual/fr/dist/html/Makefile.am
@@ -31,3 +31,5 @@ maintainer-clean:
 	-rm claws-mail-manual.html
 	-rm claws-mail-manual.html.raw
 endif
+
+.PHONY: test
diff --git a/manual/fr/dist/pdf/Makefile.am b/manual/fr/dist/pdf/Makefile.am
index b7a8a53..2c8f1c3 100644
--- a/manual/fr/dist/pdf/Makefile.am
+++ b/manual/fr/dist/pdf/Makefile.am
@@ -27,3 +27,5 @@ claws-mail-manual.pdf: \
 maintainer-clean:
 	-rm claws-mail-manual.pdf claws-mail-manual.fo claws-mail-manual.xsl
 endif
+
+.PHONY: test
diff --git a/manual/fr/dist/ps/Makefile.am b/manual/fr/dist/ps/Makefile.am
index 53f5bdb..bb9a6da 100644
--- a/manual/fr/dist/ps/Makefile.am
+++ b/manual/fr/dist/ps/Makefile.am
@@ -27,3 +27,5 @@ claws-mail-manual.ps: \
 maintainer-clean:
 	-rm claws-mail-manual.ps
 endif
+
+.PHONY: test
diff --git a/manual/fr/dist/txt/Makefile.am b/manual/fr/dist/txt/Makefile.am
index 957b1bf..1647679 100644
--- a/manual/fr/dist/txt/Makefile.am
+++ b/manual/fr/dist/txt/Makefile.am
@@ -27,3 +27,5 @@ claws-mail-manual.txt: \
 maintainer-clean:
 	-rm claws-mail-manual.txt
 endif
+
+.PHONY: test
diff --git a/manual/pl/Makefile.am b/manual/pl/Makefile.am
index 00f1ca8..1a605a6 100644
--- a/manual/pl/Makefile.am
+++ b/manual/pl/Makefile.am
@@ -21,3 +21,5 @@ EXTRA_DIST = \
 	plugins.xml \
 	starting.xml \
 	claws-mail-manual.xml
+
+.PHONY: test
diff --git a/manual/pl/dist/Makefile.am b/manual/pl/dist/Makefile.am
index 9bff2bd..c19a2fd 100644
--- a/manual/pl/dist/Makefile.am
+++ b/manual/pl/dist/Makefile.am
@@ -4,3 +4,5 @@
 # See COPYING file for license details.
 
 SUBDIRS=html pdf ps txt
+
+.PHONY: test
diff --git a/manual/pl/dist/html/Makefile.am b/manual/pl/dist/html/Makefile.am
index c1f3ef6..680e4a4 100644
--- a/manual/pl/dist/html/Makefile.am
+++ b/manual/pl/dist/html/Makefile.am
@@ -31,3 +31,5 @@ maintainer-clean:
 	-rm claws-mail-manual.html
 	-rm claws-mail-manual.html.raw
 endif
+
+.PHONY: test
diff --git a/manual/pl/dist/pdf/Makefile.am b/manual/pl/dist/pdf/Makefile.am
index 02eec0b..a599ace 100644
--- a/manual/pl/dist/pdf/Makefile.am
+++ b/manual/pl/dist/pdf/Makefile.am
@@ -27,3 +27,5 @@ claws-mail-manual.pdf: \
 maintainer-clean:
 	-rm claws-mail-manual.pdf claws-mail-manual.fo claws-mail-manual.xsl
 endif
+
+.PHONY: test
diff --git a/manual/pl/dist/ps/Makefile.am b/manual/pl/dist/ps/Makefile.am
index 48a27df..64ad9c0 100644
--- a/manual/pl/dist/ps/Makefile.am
+++ b/manual/pl/dist/ps/Makefile.am
@@ -27,3 +27,5 @@ claws-mail-manual.ps: \
 maintainer-clean:
 	-rm claws-mail-manual.ps
 endif
+
+.PHONY: test
diff --git a/manual/pl/dist/txt/Makefile.am b/manual/pl/dist/txt/Makefile.am
index 31c051d..17f970f 100644
--- a/manual/pl/dist/txt/Makefile.am
+++ b/manual/pl/dist/txt/Makefile.am
@@ -27,3 +27,5 @@ claws-mail-manual.txt: \
 maintainer-clean:
 	-rm claws-mail-manual.txt
 endif
+
+.PHONY: test
diff --git a/src/Makefile.am b/src/Makefile.am
index 30e85a4..9844f30 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -11,7 +11,11 @@ etpan_dir =
 etpan_library = 
 endif
 
-SUBDIRS = common gtk $(etpan_dir) . plugins 
+SUBDIRS = common gtk $(etpan_dir) . plugins
+if BUILD_TESTS
+include $(top_srcdir)/tests.mk
+SUBDIRS += tests
+endif
 
 bin_PROGRAMS = claws-mail
 install-exec-hook:
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 56b6cdb..5c4f249 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -3,6 +3,11 @@
 # terms of the General Public License version 3 (or later).
 # See COPYING file for license details.
 
+if BUILD_TESTS
+include $(top_srcdir)/tests.mk
+SUBDIRS = . tests
+endif
+
 PLUGINDIR = $(pkglibdir)/plugins/
 DESKTOPFILEPATH=$(datadir)/applications/claws-mail.desktop
 
@@ -98,4 +103,3 @@ libclawscommon_la_LIBADD = \
 
 EXTRA_DIST = \
 	version.h.in
-
diff --git a/src/common/tests/Makefile.am b/src/common/tests/Makefile.am
new file mode 100644
index 0000000..7b18f88
--- /dev/null
+++ b/src/common/tests/Makefile.am
@@ -0,0 +1,31 @@
+include $(top_srcdir)/tests.mk
+
+common_ldadd = \
+	$(GLIB_LIBS)
+
+AM_CPPFLAGS = \
+	$(GLIB_CFLAGS) \
+	-DLOCALEDIR=\""$(localedir)"\" \
+	-DPLUGINDIR=\"$(PLUGINDIR)\" \
+	-I$(top_srcdir)/src \
+	-I..
+
+TEST_PROGS += xml_test
+xml_test_SOURCES = xml_test.c
+xml_test_LDADD = $(common_ldadd) ../xml.o ../stringtable.o ../utils.o ../codeconv.o ../quoted-printable.o ../unmime.o
+
+TEST_PROGS += codeconv_test
+codeconv_test_SOURCES = codeconv_test.c
+codeconv_test_LDADD = $(common_ldadd) ../codeconv.o ../utils.o ../quoted-printable.o ../unmime.o
+
+TEST_PROGS += md5_test
+md5_test_SOURCES = md5_test.c
+md5_test_LDADD = $(common_ldadd) ../md5.o
+
+TEST_PROGS += pkcs5_pbkdf2_test
+pkcs5_pbkdf2_test_SOURCES = pkcs5_pbkdf2_test.c
+pkcs5_pbkdf2_test_LDADD = $(common_ldadd) ../pkcs5_pbkdf2.o
+
+noinst_PROGRAMS = $(TEST_PROGS)
+
+.PHONY: test
diff --git a/src/common/tests/codeconv_test.c b/src/common/tests/codeconv_test.c
new file mode 100644
index 0000000..3b93eae
--- /dev/null
+++ b/src/common/tests/codeconv_test.c
@@ -0,0 +1,101 @@
+#include <glib.h>
+
+#include "codeconv.h"
+
+#include "mock_prefs_common_get_use_shred.h"
+
+struct td {
+	gchar *pre; /* Input string */
+	gchar *post; /* Expected output */
+};
+
+struct td from_utf8_empty = { "", "" };
+/* TODO: more tests */
+
+struct td to_utf8_empty = { "", "" };
+/* TODO: more tests */
+
+static void
+test_filename_from_utf8_null()
+{
+	if (!g_test_undefined())
+		return;
+
+	if (g_test_subprocess()) {
+		gchar *out;
+
+		out = conv_filename_from_utf8(NULL);
+		g_assert_null(out);
+		return;
+	}
+
+	g_test_trap_subprocess(NULL, 0, 0);
+	g_test_trap_assert_stdout("*Condition*failed*");
+	g_test_trap_assert_passed();
+}
+
+static void
+test_filename_from_utf8(gconstpointer user_data)
+{
+	struct td *data = (struct td *)user_data;
+
+	if (!g_test_undefined())
+		return;
+
+	if (g_test_subprocess()) {
+		gchar *out;
+
+		out = conv_filename_from_utf8(data->pre);
+		g_assert_cmpstr(out, ==, data->post);
+
+		g_free(out);
+		return;
+	}
+
+	g_test_trap_subprocess(NULL, 0, 0);
+	g_test_trap_assert_passed();
+}
+
+static void
+test_filename_to_utf8(gconstpointer user_data)
+{
+	struct td *data = (struct td *)user_data;
+
+	if (!g_test_undefined())
+		return;
+
+	if (g_test_subprocess()) {
+		gchar *out;
+
+		out = conv_filename_to_utf8(data->pre);
+		g_assert_cmpstr(out, ==, data->post);
+
+		g_free(out);
+		return;
+	}
+
+	g_test_trap_subprocess(NULL, 0, 0);
+	g_test_trap_assert_passed();
+}
+
+int
+main(int argc, char *argv[])
+{
+	g_test_init(&argc, &argv, NULL);
+
+	g_test_add_func("/common/codeconv/filename_from_utf8/null",
+			test_filename_from_utf8_null);
+	g_test_add_data_func("/common/codeconv/filename_from_utf8/empty",
+			&from_utf8_empty,
+			test_filename_from_utf8);
+
+	g_test_add_func("/common/codeconv/filename_to_utf8/null",
+			test_filename_from_utf8_null);
+	g_test_add_data_func("/common/codeconv/filename_to_utf8/empty",
+			&to_utf8_empty,
+			test_filename_to_utf8);
+
+	/* TODO: more tests */
+
+	return g_test_run();
+}
diff --git a/config/Makefile.am b/src/common/tests/data/empty.xml
similarity index 100%
copy from config/Makefile.am
copy to src/common/tests/data/empty.xml
diff --git a/src/common/tests/md5_test.c b/src/common/tests/md5_test.c
new file mode 100644
index 0000000..e78d118
--- /dev/null
+++ b/src/common/tests/md5_test.c
@@ -0,0 +1,256 @@
+#include <glib.h>
+
+#include <common/md5.h>
+
+struct td_digest {
+	gchar *input;
+	gchar *expected_output;
+};
+
+struct td_digest td_rfc1321_1 = { "", "d41d8cd98f00b204e9800998ecf8427e" };
+struct td_digest td_rfc1321_2 = { "a", "0cc175b9c0f1b6a831c399e269772661" };
+struct td_digest td_rfc1321_3 = { "abc", "900150983cd24fb0d6963f7d28e17f72" };
+struct td_digest td_rfc1321_4 = { "message digest", "f96b697d7cb7938d525a2f31aaf161d0" };
+struct td_digest td_rfc1321_5 = { "abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b" };
+struct td_digest td_rfc1321_6 = { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "d174ab98d277d9f5a5611c2c9f419d9f" };
+struct td_digest td_rfc1321_7 = { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", "57edf4a22be3c955ac49da2e2107b67a" };
+
+struct td_hmac {
+	gchar *key;
+	int key_len;
+	gchar *data;
+	int data_len;
+	gchar *expected_output;
+};
+
+struct td_hmac td_hmac_null_key = {
+	NULL, 50,
+	"", 0,
+	""
+};
+struct td_hmac td_hmac_negative_key_length = {
+	"", -1,
+	"", 0,
+	""
+};
+struct td_hmac td_hmac_null_data = {
+	"", 0,
+	NULL, 50,
+	""
+};
+struct td_hmac td_hmac_negative_data_length = {
+	"abc", 3,
+	"", -1,
+	"",
+};
+
+struct td_hmac td_rfc2202_1 = {
+	"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 16,
+	"Hi There", 8,
+	"9294727a3638bb1c13f48ef8158bfc9d"
+};
+struct td_hmac td_rfc2202_2 = {
+	"Jefe", 4,
+	"what do ya want for nothing?", 28,
+	"750c783e6ab0b503eaa86e310a5db738"
+};
+struct td_hmac td_rfc2202_3 = {
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 16,
+	"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", 50,
+	"56be34521d144c88dbb8c733f0e8b3f6"
+};
+struct td_hmac td_rfc2202_4 = {
+	"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", 25,
+	"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", 50,
+	"697eaf0aca3a3aea3a75164746ffaa79"
+};
+struct td_hmac td_rfc2202_5 = {
+	"\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", 16,
+	"Test With Truncation", 20,
+	"56461ef2342edc00f9bab995690efd4c"
+};
+struct td_hmac td_rfc2202_6 = {
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 80,
+	"Test Using Larger Than Block-Size Key - Hash Key First", 54,
+	"6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd"
+};
+struct td_hmac td_rfc2202_7 = {
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 80,
+	"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", 73,
+	"6f630fad67cda0ee1fb1f562db3aa53e"
+};
+
+static void
+test_md5_hex_digest_null_input(void)
+{
+	char outbuf[33];
+
+	outbuf[0] = '\0';
+
+	if (!g_test_undefined())
+		return;
+
+	if (g_test_subprocess()) {
+		md5_hex_digest(outbuf, NULL);
+		return;
+	}
+
+	g_test_trap_subprocess(NULL, 0, 0);
+	g_test_trap_assert_failed();
+	g_test_trap_assert_stderr("*CRITICAL*md5_hex_digest: assertion*failed*");
+	g_assert_cmpint(outbuf[0], ==, '\0');
+}
+
+static void
+test_md5_hex_digest_null_output(void)
+{
+	if (!g_test_undefined())
+		return;
+
+	if (g_test_subprocess()) {
+		md5_hex_digest(NULL, "");
+		return;
+	}
+
+	g_test_trap_subprocess(NULL, 0, 0);
+	g_test_trap_assert_failed();
+	g_test_trap_assert_stderr("*CRITICAL*md5_hex_digest: assertion*failed*");
+}
+
+static void
+test_md5_hex_digest(gconstpointer user_data)
+{
+	char outbuf[33];
+	struct td_digest *data = (struct td_digest *)user_data;
+
+	md5_hex_digest(outbuf, data->input);
+
+	g_assert_cmpint(outbuf[32], ==, '\0');
+	g_assert_cmpstr(outbuf, ==, data->expected_output);
+}
+
+static void
+test_md5_hex_hmac_null_output(void)
+{
+	if (!g_test_undefined())
+		return;
+
+	if (g_test_subprocess()) {
+		md5_hex_hmac(NULL, "", 0, "", 0);
+		return;
+	}
+
+	g_test_trap_subprocess(NULL, 0, 0);
+	g_test_trap_assert_failed();
+	g_test_trap_assert_stderr("*CRITICAL*md5_hex_hmac: assertion*failed*");
+}
+
+/* We expect all test cases using this function to fail with
+ * failed assertion */
+static void
+test_md5_hex_hmac_fails(gconstpointer user_data)
+{
+	char outbuf[33];
+	struct td_hmac *data = (struct td_hmac *)user_data;
+
+	if (!g_test_undefined())
+		return;
+
+	if (g_test_subprocess()) {
+		md5_hex_hmac(outbuf,
+				data->data, data->data_len,
+				data->key, data->key_len);
+		return;
+	}
+
+	g_test_trap_subprocess(NULL, 0, 0);
+	g_test_trap_assert_failed();
+	g_test_trap_assert_stderr("*CRITICAL*md5_hex_hmac: assertion*failed*");
+}
+
+static void
+test_md5_hex_hmac(gconstpointer user_data)
+{
+	char outbuf[33];
+	struct td_hmac *data = (struct td_hmac *)user_data;
+
+	md5_hex_hmac(outbuf,
+			data->data, data->data_len,
+			data->key, data->key_len);
+
+	g_assert_cmpint(outbuf[32], ==, '\0');
+	g_assert_cmpstr(outbuf, ==, data->expected_output);
+}
+
+
+int
+main(int argc, char *argv[])
+{
+	g_test_init(&argc, &argv, NULL);
+
+	g_test_add_func("/common/md5/hex_digest/null_input",
+			test_md5_hex_digest_null_input);
+	g_test_add_func("/common/md5/hex_digest/null_output",
+			test_md5_hex_digest_null_output);
+
+	g_test_add_data_func("/common/md5/hex_digest/rfc1321_1",
+			&td_rfc1321_1,
+			test_md5_hex_digest);
+	g_test_add_data_func("/common/md5/hex_digest/rfc1321_2",
+			&td_rfc1321_2,
+			test_md5_hex_digest);
+	g_test_add_data_func("/common/md5/hex_digest/rfc1321_3",
+			&td_rfc1321_3,
+			test_md5_hex_digest);
+	g_test_add_data_func("/common/md5/hex_digest/rfc1321_4",
+			&td_rfc1321_4,
+			test_md5_hex_digest);
+	g_test_add_data_func("/common/md5/hex_digest/rfc1321_5",
+			&td_rfc1321_5,
+			test_md5_hex_digest);
+	g_test_add_data_func("/common/md5/hex_digest/rfc1321_6",
+			&td_rfc1321_6,
+			test_md5_hex_digest);
+	g_test_add_data_func("/common/md5/hex_digest/rfc1321_7",
+			&td_rfc1321_7,
+			test_md5_hex_digest);
+
+	g_test_add_data_func("/common/md5/hex_hmac/null_key",
+			&td_hmac_null_key,
+			test_md5_hex_hmac_fails);
+	g_test_add_data_func("/common/md5/hex_hmac/negative_key_length",
+			&td_hmac_negative_key_length,
+			test_md5_hex_hmac_fails);
+	g_test_add_data_func("/common/md5/hex_hmac/null_data",
+			&td_hmac_null_data,
+			test_md5_hex_hmac_fails);
+	g_test_add_data_func("/common/md5/hex_hmac/negative_data_length",
+			&td_hmac_negative_data_length,
+			test_md5_hex_hmac_fails);
+	g_test_add_func("/common/md5/hex_hmac/null_output",
+			test_md5_hex_hmac_null_output);
+
+	g_test_add_data_func("/common/md5/hex_hmac/rfc2202_1",
+			&td_rfc2202_1,
+			test_md5_hex_hmac);
+	g_test_add_data_func("/common/md5/hex_hmac/rfc2202_2",
+			&td_rfc2202_2,
+			test_md5_hex_hmac);
+	g_test_add_data_func("/common/md5/hex_hmac/rfc2202_3",
+			&td_rfc2202_3,
+			test_md5_hex_hmac);
+	g_test_add_data_func("/common/md5/hex_hmac/rfc2202_4",
+			&td_rfc2202_4,
+			test_md5_hex_hmac);
+	g_test_add_data_func("/common/md5/hex_hmac/rfc2202_5",
+			&td_rfc2202_5,
+			test_md5_hex_hmac);
+	g_test_add_data_func("/common/md5/hex_hmac/rfc2202_6",
+			&td_rfc2202_6,
+			test_md5_hex_hmac);
+	g_test_add_data_func("/common/md5/hex_hmac/rfc2202_7",
+			&td_rfc2202_7,
+			test_md5_hex_hmac);
+
+	return g_test_run();
+}
diff --git a/src/common/tests/mock_prefs_common_get_use_shred.h b/src/common/tests/mock_prefs_common_get_use_shred.h
new file mode 100644
index 0000000..a216cbd
--- /dev/null
+++ b/src/common/tests/mock_prefs_common_get_use_shred.h
@@ -0,0 +1,5 @@
+gboolean prefs_common_get_use_shred(void)
+{
+	return FALSE;
+}
+
diff --git a/src/common/tests/pkcs5_pbkdf2_test.c b/src/common/tests/pkcs5_pbkdf2_test.c
new file mode 100644
index 0000000..3f7a451
--- /dev/null
+++ b/src/common/tests/pkcs5_pbkdf2_test.c
@@ -0,0 +1,121 @@
+#include <glib.h>
+
+#include <common/pkcs5_pbkdf2.h>
+
+struct td {
+	gchar *input;
+	size_t input_length;
+	gchar *salt;
+	size_t salt_length;
+	size_t length;
+	guint rounds;
+	gint expected_return;
+	gchar *expected_output;
+};
+
+/* Test vectors from RFC 6070 */
+struct td td_rfc6070_1 = { "password", 8,
+	"salt", 4,
+	20, 1, 0,
+	"\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9\xb5\x24\xaf\x60\x12\x06\x2f\xe0\x37\xa6" };
+struct td td_rfc6070_2 = { "password", 8,
+	"salt", 4,
+	20, 2, 0,
+	"\xea\x6c\x01\x4d\xc7\x2d\x6f\x8c\xcd\x1e\xd9\x2a\xce\x1d\x41\xf0\xd8\xde\x89\x57" };
+struct td td_rfc6070_3 = { "password", 8,
+	"salt", 4,
+	20, 4096, 0,
+	"\x4b\x00\x79\x01\xb7\x65\x48\x9a\xbe\xad\x49\xd9\x26\xf7\x21\xd0\x65\xa4\x29\xc1" };
+struct td td_rfc6070_4 = { "password", 8,
+	"salt", 4,
+	20, 16777216, 0,
+	"\xee\xfe\x3d\x61\xcd\x4d\xa4\xe4\xe9\x94\x5b\x3d\x6b\xa2\x15\x8c\x26\x34\xe9\x84" };
+struct td td_rfc6070_5 = { "passwordPASSWORDpassword", 24,
+	"saltSALTsaltSALTsaltSALTsaltSALTsalt", 36,
+	25, 4096, 0,
+	"\x3d\x2e\xec\x4f\xe4\x1c\x84\x9b\x80\xc8\xd8\x36\x62\xc0\xe4\x4a\x8b\x29\x1a\x96\x4c\xf2\xf0\x70\x38" };
+struct td td_rfc6070_6 = { "pass\0word", 9,
+	"sa\0lt", 5,
+	16, 4096, 0,
+	"\x56\xfa\x6a\xa7\x55\x48\x09\x9d\xcc\x37\xd7\xf0\x34\x25\xe0\xc3" };
+
+struct td td_zero_rounds = { "abc", 3, "abc", 3, 3, 0, -1, "" };
+struct td td_zero_output_length = { "abc", 3, "abc", 3, 0, 1, -1, NULL };
+struct td td_null_input = { NULL, 10, "", 10, 10, 100, -1, "" };
+struct td td_null_salt = { "", 10, NULL, 10, 10, 100, -1, "" };
+
+static void
+test_pkcs5_pbkdf2(gconstpointer user_data)
+{
+	struct td *data = (struct td *)user_data;
+	guchar *kd = g_malloc0(data->length);
+	gint ret;
+
+	if (data->rounds > 10000 && !g_test_slow()) {
+		gchar *msg = "Time-intensive test, rerun in slow mode to run it.";
+		g_test_skip(msg);
+		g_test_message(msg);
+		return;
+	}
+
+	if (g_test_verbose()) {
+		g_printerr("input '%s' (%ld)\nsalt '%s' (%ld)\nlength %ld\nrounds %d\nexpected_return %d\n",
+				data->input, data->input_length,
+				data->salt, data->salt_length,
+				data->length,
+				data->rounds,
+				data->expected_return);
+	}
+
+	ret = pkcs5_pbkdf2(
+			data->input,
+			data->input_length,
+			data->salt,
+			data->salt_length,
+			kd,
+			data->length,
+			data->rounds);
+
+	g_assert_cmpint(ret, ==, data->expected_return);
+	g_assert_cmpstr(kd, ==, data->expected_output);
+}
+
+static void
+test_pkcs5_pbkdf2_null_output_buffer(void)
+{
+	gint ret = pkcs5_pbkdf2("abc", 3, "abc", 3, NULL, 10, 1);
+
+	g_assert_cmpint(ret, ==, -1);
+}
+
+int
+main(int argc, char *argv[])
+{
+	g_test_init(&argc, &argv, NULL);
+
+	g_test_add_data_func("/common/pkcs5_pbkdf2/zero_rounds",
+			&td_zero_rounds, test_pkcs5_pbkdf2);
+	g_test_add_data_func("/common/pkcs5_pbkdf2/zero_output_length",
+			&td_zero_output_length, test_pkcs5_pbkdf2);
+	g_test_add_data_func("/common/pkcs5_pbkdf2/null_salt",
+			&td_null_salt, test_pkcs5_pbkdf2);
+	g_test_add_data_func("/common/pkcs5_pbkdf2/null_input",
+			&td_null_input, test_pkcs5_pbkdf2);
+	g_test_add_func("/common/pkcs5_pbkdf2/null_output_buffer",
+			test_pkcs5_pbkdf2_null_output_buffer);
+
+	g_test_add_data_func("/common/pkcs5_pbkdf2/rfc6070_1",
+			&td_rfc6070_1, test_pkcs5_pbkdf2);
+	g_test_add_data_func("/common/pkcs5_pbkdf2/rfc6070_2",
+			&td_rfc6070_2, test_pkcs5_pbkdf2);
+	g_test_add_data_func("/common/pkcs5_pbkdf2/rfc6070_3",
+			&td_rfc6070_3, test_pkcs5_pbkdf2);
+	g_test_add_data_func("/common/pkcs5_pbkdf2/rfc6070_4",
+			&td_rfc6070_4, test_pkcs5_pbkdf2);
+	g_test_add_data_func("/common/pkcs5_pbkdf2/rfc6070_5",
+			&td_rfc6070_5, test_pkcs5_pbkdf2);
+	g_test_add_data_func("/common/pkcs5_pbkdf2/rfc6070_6",
+			&td_rfc6070_6, test_pkcs5_pbkdf2);
+
+	return g_test_run();
+}
diff --git a/src/common/tests/xml_test.c b/src/common/tests/xml_test.c
new file mode 100644
index 0000000..1e58d8d
--- /dev/null
+++ b/src/common/tests/xml_test.c
@@ -0,0 +1,39 @@
+#include <glib.h>
+
+#include "xml.h"
+
+#include "mock_prefs_common_get_use_shred.h"
+
+#define DATADIR "data/"
+
+static void
+test_xml_open_file_missing(void)
+{
+	XMLFile *xf = xml_open_file(DATADIR "missing.xml");
+	g_assert_null(xf);
+}
+
+static void
+test_xml_open_file_empty(void)
+{
+	XMLFile *xf = xml_open_file(DATADIR "empty.xml");
+	g_assert_nonnull(xf);
+	g_assert_nonnull(xf->buf);
+	g_assert_nonnull(xf->bufp);
+	g_assert_null(xf->dtd);
+	g_assert_null(xf->encoding);
+	g_assert_null(xf->tag_stack);
+	g_assert_cmpint(xf->level, ==, 0);
+	g_assert_false(xf->is_empty_element);
+}
+
+int
+main(int argc, char *argv[])
+{
+	g_test_init(&argc, &argv, NULL);
+
+	g_test_add_func("/common/xml_open_file_missing", test_xml_open_file_missing);
+	g_test_add_func("/common/xml_open_file_empty", test_xml_open_file_empty);
+
+	return g_test_run();
+}
diff --git a/src/etpan/Makefile.am b/src/etpan/Makefile.am
index 111d8d1..2a6e093 100644
--- a/src/etpan/Makefile.am
+++ b/src/etpan/Makefile.am
@@ -35,3 +35,5 @@ libclawsetpan_la_LIBADD = \
 	$(GTK_LIBS) \
 	$(LIBETPAN_LIBS) \
 	$(ENCHANT_LIBS)
+
+.PHONY: test
diff --git a/src/gtk/Makefile.am b/src/gtk/Makefile.am
index bee0378..94985ab 100644
--- a/src/gtk/Makefile.am
+++ b/src/gtk/Makefile.am
@@ -101,3 +101,5 @@ claws-marshal.h: claws-marshal.list
 
 claws-marshal.c: claws-marshal.list
 	$(GLIB_GENMARSHAL) $< --body --prefix=claws_marshal > $@
+
+.PHONY: test
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 28abfdb..1f88956 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -3,6 +3,8 @@
 # terms of the General Public License version 3 (or later).
 # See COPYING file for license details.
 
+include $(top_srcdir)/tests.mk
+
 SUBDIRS = \
 	acpi_notifier \
 	address_keeper \
@@ -34,3 +36,5 @@ SUBDIRS = \
 	spam_report \
 	tnef_parse \
 	vcalendar
+
+.PHONY: test
diff --git a/src/plugins/acpi_notifier/Makefile.am b/src/plugins/acpi_notifier/Makefile.am
index 2ae194c..cc794db 100644
--- a/src/plugins/acpi_notifier/Makefile.am
+++ b/src/plugins/acpi_notifier/Makefile.am
@@ -26,3 +26,5 @@ acpi_notifier_la_CPPFLAGS = \
 	-I$(top_srcdir)/src/gtk \
 	$(GLIB_CFLAGS) \
 	$(GTK_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/address_keeper/Makefile.am b/src/plugins/address_keeper/Makefile.am
index 4a49ae1..2388f77 100644
--- a/src/plugins/address_keeper/Makefile.am
+++ b/src/plugins/address_keeper/Makefile.am
@@ -78,3 +78,5 @@ address_keeper_la_SOURCES = \
 	address_keeper.c address_keeper.h \
 	address_keeper_prefs.c address_keeper_prefs.h
 
+
+.PHONY: test
diff --git a/src/plugins/archive/Makefile.am b/src/plugins/archive/Makefile.am
index c3cb051..5ca136d 100644
--- a/src/plugins/archive/Makefile.am
+++ b/src/plugins/archive/Makefile.am
@@ -36,3 +36,5 @@ archive_la_CPPFLAGS = \
 	$(GTK_CFLAGS) \
 	$(ENCHANT_CFLAGS) \
 	$(LIBARCHIVE_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/att_remover/Makefile.am b/src/plugins/att_remover/Makefile.am
index 543b5bc..a0f8b92 100644
--- a/src/plugins/att_remover/Makefile.am
+++ b/src/plugins/att_remover/Makefile.am
@@ -76,3 +76,5 @@ att_remover_la_CPPFLAGS = \
 	$(GLIB_CFLAGS) \
 	$(GTK_CFLAGS) \
 	$(ENCHANT_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/attachwarner/Makefile.am b/src/plugins/attachwarner/Makefile.am
index 146180b..6315e91 100644
--- a/src/plugins/attachwarner/Makefile.am
+++ b/src/plugins/attachwarner/Makefile.am
@@ -78,3 +78,5 @@ attachwarner_la_SOURCES = \
 	attachwarner.c attachwarner.h \
 	attachwarner_prefs.c attachwarner_prefs.h
 
+
+.PHONY: test
diff --git a/src/plugins/bogofilter/Makefile.am b/src/plugins/bogofilter/Makefile.am
index acb5f4e..b8b6cdc 100644
--- a/src/plugins/bogofilter/Makefile.am
+++ b/src/plugins/bogofilter/Makefile.am
@@ -32,3 +32,5 @@ bogofilter_la_CPPFLAGS = \
 	$(ENCHANT_CFLAGS) \
 	$(GLIB_CFLAGS) \
 	$(GTK_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/bsfilter/Makefile.am b/src/plugins/bsfilter/Makefile.am
index 72bee25..8b5d70b 100644
--- a/src/plugins/bsfilter/Makefile.am
+++ b/src/plugins/bsfilter/Makefile.am
@@ -78,3 +78,5 @@ bsfilter_la_SOURCES = \
 	bsfilter.c bsfilter.h \
 	bsfilter_gtk.c
 
+
+.PHONY: test
diff --git a/src/plugins/clamd/Makefile.am b/src/plugins/clamd/Makefile.am
index a66e992..2e29e49 100644
--- a/src/plugins/clamd/Makefile.am
+++ b/src/plugins/clamd/Makefile.am
@@ -32,3 +32,5 @@ clamd_la_CPPFLAGS = \
 	$(GLIB_CFLAGS) \
 	$(GTK_CFLAGS) \
 	$(ENCHANT_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/clamd/libclamd/Makefile.am b/src/plugins/clamd/libclamd/Makefile.am
index a71ac3e..12adb34 100644
--- a/src/plugins/clamd/libclamd/Makefile.am
+++ b/src/plugins/clamd/libclamd/Makefile.am
@@ -26,3 +26,5 @@ noinst_HEADERS = clamd-plugin.h
 libclamd_plugin_la_LIBADD = \
 	@GLIB_LIBS@ \
 	@GTK_LIBS@
+
+.PHONY: test
diff --git a/src/plugins/demo/Makefile.am b/src/plugins/demo/Makefile.am
index 8c2d43a..7593ceb 100644
--- a/src/plugins/demo/Makefile.am
+++ b/src/plugins/demo/Makefile.am
@@ -29,3 +29,5 @@ demo_la_CPPFLAGS = \
 	-I$(top_builddir)/src/common \
 	-I$(top_srcdir)/src/common \
 	$(GLIB_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/dillo/Makefile.am b/src/plugins/dillo/Makefile.am
index 5c15449..9be3c1f 100644
--- a/src/plugins/dillo/Makefile.am
+++ b/src/plugins/dillo/Makefile.am
@@ -34,3 +34,5 @@ dillo_la_CPPFLAGS = \
 	$(GLIB_CFLAGS) \
 	$(GTK_CFLAGS) \
 	$(ENCHANT_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/fancy/Makefile.am b/src/plugins/fancy/Makefile.am
index bfd1dd0..d436861 100644
--- a/src/plugins/fancy/Makefile.am
+++ b/src/plugins/fancy/Makefile.am
@@ -85,3 +85,5 @@ fancy_la_CPPFLAGS = \
 	$(WEBKIT_CFLAGS) \
 	$(LIBSOUP_GNOME_CFLAGS) \
 	$(CURL_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/fetchinfo/Makefile.am b/src/plugins/fetchinfo/Makefile.am
index ca84f48..338fe0a 100644
--- a/src/plugins/fetchinfo/Makefile.am
+++ b/src/plugins/fetchinfo/Makefile.am
@@ -76,3 +76,5 @@ fetchinfo_la_CPPFLAGS = \
 	$(GTK_CFLAGS)
 
 EXTRA_DIST = claws.def plugin.def version.rc
+
+.PHONY: test
diff --git a/src/plugins/gdata/Makefile.am b/src/plugins/gdata/Makefile.am
index 84ba0ee..39db98c 100644
--- a/src/plugins/gdata/Makefile.am
+++ b/src/plugins/gdata/Makefile.am
@@ -31,3 +31,5 @@ gdata_la_CPPFLAGS = \
 	$(GTK_CFLAGS) \
 	$(ENCHANT_CFLAGS) \
 	$(GDATA_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/libravatar/Makefile.am b/src/plugins/libravatar/Makefile.am
index ac0f35c..c494b03 100644
--- a/src/plugins/libravatar/Makefile.am
+++ b/src/plugins/libravatar/Makefile.am
@@ -84,3 +84,5 @@ libravatar_la_SOURCES = \
 	libravatar_missing.c libravatar_missing.h \
 	libravatar_federation.c libravatar_federation.h
 
+
+.PHONY: test
diff --git a/src/plugins/mailmbox/Makefile.am b/src/plugins/mailmbox/Makefile.am
index 1eceab5..dffee3a 100644
--- a/src/plugins/mailmbox/Makefile.am
+++ b/src/plugins/mailmbox/Makefile.am
@@ -88,3 +88,5 @@ mailmbox_la_CPPFLAGS = \
 	$(GLIB_CFLAGS) \
 	$(GTK_CFLAGS) \
 	$(ENCHANT_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/managesieve/Makefile.am b/src/plugins/managesieve/Makefile.am
index 8a9da5d..fe4cb7d 100644
--- a/src/plugins/managesieve/Makefile.am
+++ b/src/plugins/managesieve/Makefile.am
@@ -83,3 +83,5 @@ managesieve_la_SOURCES = \
 	sieve_manager.c sieve_manager.h \
 	sieve_editor.c sieve_editor.h
 
+
+.PHONY: test
diff --git a/src/plugins/newmail/Makefile.am b/src/plugins/newmail/Makefile.am
index 286d0b1..33801fb 100644
--- a/src/plugins/newmail/Makefile.am
+++ b/src/plugins/newmail/Makefile.am
@@ -22,3 +22,5 @@ newmail_la_CPPFLAGS = \
 	-I$(top_srcdir)/src/gtk \
         $(GLIB_CFLAGS) \
 	$(GTK_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/notification/Makefile.am b/src/plugins/notification/Makefile.am
index 35c2f1c..9d29d32 100644
--- a/src/plugins/notification/Makefile.am
+++ b/src/plugins/notification/Makefile.am
@@ -109,3 +109,5 @@ notification_la_CPPFLAGS = \
 
 clean-local:
 	rm -f libclaws.a
+
+.PHONY: test
diff --git a/src/plugins/notification/gtkhotkey/Makefile.am b/src/plugins/notification/gtkhotkey/Makefile.am
index 96181d1..3975852 100644
--- a/src/plugins/notification/gtkhotkey/Makefile.am
+++ b/src/plugins/notification/gtkhotkey/Makefile.am
@@ -31,3 +31,5 @@ libcmnpgtkhotkey_la_CPPFLAGS = \
 	$(GLIB_CFLAGS) \
 	$(GTK_CFLAGS) \
 	$(CM_NP_HOTKEY_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/pdf_viewer/Makefile.am b/src/plugins/pdf_viewer/Makefile.am
index 25cabc5..c790e94 100644
--- a/src/plugins/pdf_viewer/Makefile.am
+++ b/src/plugins/pdf_viewer/Makefile.am
@@ -27,3 +27,5 @@ pdf_viewer_la_CPPFLAGS = \
 	$(GTK_CFLAGS) \
 	$(ENCHANT_CFLAGS) \
 	$(POPPLER_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/perl/Makefile.am b/src/plugins/perl/Makefile.am
index 3df58c3..1c7bca7 100644
--- a/src/plugins/perl/Makefile.am
+++ b/src/plugins/perl/Makefile.am
@@ -34,3 +34,5 @@ perl_la_CPPFLAGS = \
 
 EXTRA_DIST = cm_perl.pod
 
+
+.PHONY: test
diff --git a/src/plugins/perl/tools/Makefile.am b/src/plugins/perl/tools/Makefile.am
index 9744b77..65f12c0 100644
--- a/src/plugins/perl/tools/Makefile.am
+++ b/src/plugins/perl/tools/Makefile.am
@@ -30,3 +30,5 @@ distclean-local:
 	rm -f $$file; \
 	done; \
 	fi
+
+.PHONY: test
diff --git a/src/plugins/pgpcore/Makefile.am b/src/plugins/pgpcore/Makefile.am
index 5eb32fb..c19ebcf 100644
--- a/src/plugins/pgpcore/Makefile.am
+++ b/src/plugins/pgpcore/Makefile.am
@@ -95,3 +95,5 @@ pgpcore_la_CPPFLAGS = \
 clean-local:
 	rm -f libclaws.a
 
+
+.PHONY: test
diff --git a/src/plugins/pgpinline/Makefile.am b/src/plugins/pgpinline/Makefile.am
index e4ea69c..01931ea 100644
--- a/src/plugins/pgpinline/Makefile.am
+++ b/src/plugins/pgpinline/Makefile.am
@@ -85,3 +85,5 @@ pgpinline_la_CPPFLAGS = \
 
 clean-local:
 	rm -f libclaws.a
+
+.PHONY: test
diff --git a/src/plugins/pgpmime/Makefile.am b/src/plugins/pgpmime/Makefile.am
index 952ce56..167894f 100644
--- a/src/plugins/pgpmime/Makefile.am
+++ b/src/plugins/pgpmime/Makefile.am
@@ -86,3 +86,5 @@ pgpmime_la_CPPFLAGS = \
 
 clean-local:
 	rm -f libclaws.a
+
+.PHONY: test
diff --git a/src/plugins/python/Makefile.am b/src/plugins/python/Makefile.am
index fe7592e..36ca7c4 100644
--- a/src/plugins/python/Makefile.am
+++ b/src/plugins/python/Makefile.am
@@ -55,3 +55,5 @@ python_la_CPPFLAGS = \
 	-DPYTHON_SHARED_LIB="\"$(PYTHON_SHARED_LIB)\"" \
 	-DENABLE_PYTHON \
 	-fno-strict-aliasing
+
+.PHONY: test
diff --git a/src/plugins/python/examples/Makefile.am b/src/plugins/python/examples/Makefile.am
index 5787a2c..cbd3c14 100644
--- a/src/plugins/python/examples/Makefile.am
+++ b/src/plugins/python/examples/Makefile.am
@@ -13,3 +13,5 @@ EXTRA_DIST = \
 	main/Open-Tomboy-Notes \
 	main/Print-action-names-to-stdout \
 	main/Recusively-mark-messages-as-read
+
+.PHONY: test
diff --git a/src/plugins/rssyl/Makefile.am b/src/plugins/rssyl/Makefile.am
index 29209b2..995624c 100644
--- a/src/plugins/rssyl/Makefile.am
+++ b/src/plugins/rssyl/Makefile.am
@@ -4,6 +4,10 @@
 # See COPYING file for license details.
 
 SUBDIRS = libfeed
+if BUILD_TESTS
+include $(top_srcdir)/tests.mk
+SUBDIRS += . tests
+endif
 
 EXTRA_DIST = claws.def plugin.def version.rc
 
diff --git a/src/plugins/rssyl/libfeed/Makefile.am b/src/plugins/rssyl/libfeed/Makefile.am
index 456e253..4ba2a16 100644
--- a/src/plugins/rssyl/libfeed/Makefile.am
+++ b/src/plugins/rssyl/libfeed/Makefile.am
@@ -1,5 +1,11 @@
 if BUILD_RSSYL_PLUGIN
 noinst_LTLIBRARIES = libfeed.la
+
+if BUILD_TESTS
+include $(top_srcdir)/tests.mk
+SUBDIRS = . tests
+endif
+
 endif
 
 libfeed_la_CPPFLAGS = \
diff --git a/src/plugins/rssyl/libfeed/tests/Makefile.am b/src/plugins/rssyl/libfeed/tests/Makefile.am
new file mode 100644
index 0000000..67e1f32
--- /dev/null
+++ b/src/plugins/rssyl/libfeed/tests/Makefile.am
@@ -0,0 +1,22 @@
+include $(top_srcdir)/tests.mk
+
+common_ldadd = \
+	$(GLIB_LIBS) \
+	$(EXPAT_LIBS) \
+	$(CURL_LIBS)
+
+AM_CPPFLAGS = \
+	$(GLIB_CFLAGS) \
+	-I..
+
+TEST_PROGS += date_test
+date_test_SOURCES = date_test.c
+date_test_LDADD = $(common_ldadd) ../libfeed_la-date.o
+
+TEST_PROGS += feed_test
+feed_test_SOURCES = feed_test.c
+feed_test_LDADD = $(common_ldadd) ../libfeed.la
+
+noinst_PROGRAMS = $(TEST_PROGS)
+
+.PHONY: test
diff --git a/src/plugins/rssyl/libfeed/tests/date_test.c b/src/plugins/rssyl/libfeed/tests/date_test.c
new file mode 100644
index 0000000..cb08224
--- /dev/null
+++ b/src/plugins/rssyl/libfeed/tests/date_test.c
@@ -0,0 +1,34 @@
+#include <glib.h>
+
+#include "date.h"
+
+
+static void
+test_createRFC822Date (void)
+{
+	gchar *buf;
+	time_t t = 0;
+
+	buf = createRFC822Date(&t);
+	if (g_test_verbose())
+		g_printerr("time_t %ld => '%s'\n", t, buf);
+	g_assert_cmpstr(buf, ==, "Thu,  1 Jan 1970 00:00:00 GMT");
+	g_free(buf);
+
+	t = 1534240471;
+	buf = createRFC822Date(&t);
+	if (g_test_verbose())
+		g_printerr("time_t %ld => '%s'\n", t, buf);
+	g_assert_cmpstr(buf, ==, "Tue, 14 Aug 2018 09:54:31 GMT");
+	g_free(buf);
+}
+
+int
+main (int argc, char *argv[])
+{
+	g_test_init(&argc, &argv, NULL);
+
+	g_test_add_func("/rssyl/libfeed/createRFC822Date", test_createRFC822Date);
+
+	return g_test_run();
+}
diff --git a/src/plugins/rssyl/libfeed/tests/feed_test.c b/src/plugins/rssyl/libfeed/tests/feed_test.c
new file mode 100644
index 0000000..514d19a
--- /dev/null
+++ b/src/plugins/rssyl/libfeed/tests/feed_test.c
@@ -0,0 +1,30 @@
+#include <glib.h>
+
+#include "feed.h"
+
+#include "mock_procheader_date_parse.h"
+
+#define FEED_URL "http://example.com/feed.xml"
+
+static void
+test_Feed_create(void)
+{
+	Feed *feed = feed_new(FEED_URL);
+
+	g_assert_nonnull(feed);
+	g_assert_cmpstr(feed->url, ==, FEED_URL);
+	g_assert_true(feed->is_valid);
+	g_assert_true(feed->ssl_verify_peer);
+
+	feed_free(feed);
+}
+
+int
+main(int argc, char *argv[])
+{
+	g_test_init(&argc, &argv, NULL);
+
+	g_test_add_func("/rssyl/libfeed/Feed_create", test_Feed_create);
+
+	return g_test_run();
+}
diff --git a/src/plugins/rssyl/libfeed/tests/mock_procheader_date_parse.h b/src/plugins/rssyl/libfeed/tests/mock_procheader_date_parse.h
new file mode 100644
index 0000000..37b2182
--- /dev/null
+++ b/src/plugins/rssyl/libfeed/tests/mock_procheader_date_parse.h
@@ -0,0 +1,7 @@
+time_t
+procheader_date_parse (gchar *dest,
+		const gchar *src,
+		gint len)
+{
+	return 1;
+}
diff --git a/src/plugins/rssyl/strutils.h b/src/plugins/rssyl/strutils.h
index 2976e6f..853d118 100644
--- a/src/plugins/rssyl/strutils.h
+++ b/src/plugins/rssyl/strutils.h
@@ -1,6 +1,8 @@
 #ifndef __STRUTILS_H
 #define __STRUTILS_H
 
+#include <glib.h>
+
 gchar *rssyl_strreplace(gchar *source, gchar *pattern,
 		gchar *replacement);
 
diff --git a/src/plugins/rssyl/tests/Makefile.am b/src/plugins/rssyl/tests/Makefile.am
new file mode 100644
index 0000000..351000a
--- /dev/null
+++ b/src/plugins/rssyl/tests/Makefile.am
@@ -0,0 +1,17 @@
+include $(top_srcdir)/tests.mk
+
+common_ldadd = \
+	$(GLIB_LIBS)
+
+AM_CPPFLAGS = \
+	$(GLIB_CFLAGS) \
+	-I.. \
+	-I$(top_srcdir)/src
+
+TEST_PROGS += strutils_test
+strutils_test_SOURCES = strutils_test.c
+strutils_test_LDADD = $(common_ldadd) ../rssyl_la-strutils.o
+
+noinst_PROGRAMS = $(TEST_PROGS)
+
+.PHONY: test
diff --git a/src/plugins/rssyl/tests/strutils_test.c b/src/plugins/rssyl/tests/strutils_test.c
new file mode 100644
index 0000000..b3c976b
--- /dev/null
+++ b/src/plugins/rssyl/tests/strutils_test.c
@@ -0,0 +1,53 @@
+#include "strutils.h"
+
+/* It's safe to mock this out here, we are interested in
+ * rssyl_strreplace(), which doesn't use the real function. */
+gchar *entity_decode(gchar *str)
+{
+	return g_strdup("mocked_entity_decode");
+}
+
+struct test {
+	gchar *string;
+	gchar *pattern;
+	gchar *replacement;
+	gchar *result;
+};
+
+static void
+test_strreplace(void)
+{
+	gint i;
+	static struct test strings[] = {
+		{ "simplestring", "foo", "bar", "simplestring" },
+		{ "foobarzot", "foo", "", "barzot" },
+		{ NULL, NULL }
+	};
+
+	for (i = 0; strings[i].string != NULL; i++) {
+		gchar *result = rssyl_strreplace(
+				strings[i].string,
+				strings[i].pattern,
+				strings[i].replacement);
+
+		if (g_test_verbose()) {
+			g_printerr("string '%s', pattern '%s', replacement '%s' => result '%s'\n",
+					strings[i].string,
+					strings[i].pattern,
+					strings[i].replacement,
+					result);
+		}
+		g_assert_cmpstr(result, ==, strings[i].result);
+		g_free(result);
+	}
+}
+
+int
+main (int argc, char *argv[])
+{
+	g_test_init(&argc, &argv, NULL);
+
+	g_test_add_func("/rssyl/strreplace", test_strreplace);
+
+	return g_test_run();
+}
diff --git a/src/plugins/smime/Makefile.am b/src/plugins/smime/Makefile.am
index c431c76..d394233 100644
--- a/src/plugins/smime/Makefile.am
+++ b/src/plugins/smime/Makefile.am
@@ -87,3 +87,5 @@ smime_la_CPPFLAGS = \
 
 clean-local:
 	rm -f libclaws.a
+
+.PHONY: test
diff --git a/src/plugins/spam_report/Makefile.am b/src/plugins/spam_report/Makefile.am
index 5a077dd..e382b1f 100644
--- a/src/plugins/spam_report/Makefile.am
+++ b/src/plugins/spam_report/Makefile.am
@@ -80,3 +80,5 @@ spamreport_la_CPPFLAGS = \
 	$(CURL_CFLAGS) \
 	$(GTK_CFLAGS) \
 	$(ENCHANT_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/spamassassin/Makefile.am b/src/plugins/spamassassin/Makefile.am
index 98e3518..7e1eb2a 100644
--- a/src/plugins/spamassassin/Makefile.am
+++ b/src/plugins/spamassassin/Makefile.am
@@ -38,3 +38,5 @@ spamassassin_la_CPPFLAGS = \
 	$(SPAMASSASSIN_CFLAGS)
 
 EXTRA_DIST = README NOTICE
+
+.PHONY: test
diff --git a/src/plugins/tnef_parse/Makefile.am b/src/plugins/tnef_parse/Makefile.am
index 3dfe9c8..2ef53a8 100644
--- a/src/plugins/tnef_parse/Makefile.am
+++ b/src/plugins/tnef_parse/Makefile.am
@@ -79,3 +79,5 @@ tnef_parse_la_CPPFLAGS = \
 	$(GLIB_CFLAGS) \
 	$(GTK_CFLAGS) \
 	$(YTNEF_CFLAGS)
+
+.PHONY: test
diff --git a/src/plugins/vcalendar/Makefile.am b/src/plugins/vcalendar/Makefile.am
index c0381e7..8bceff9 100644
--- a/src/plugins/vcalendar/Makefile.am
+++ b/src/plugins/vcalendar/Makefile.am
@@ -92,3 +92,5 @@ vcalendar_la_CPPFLAGS = \
 
 clean-local:
 	rm -f libclaws.a
+
+.PHONY: test
diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
new file mode 100644
index 0000000..b0a256e
--- /dev/null
+++ b/src/tests/Makefile.am
@@ -0,0 +1,17 @@
+include $(top_srcdir)/tests.mk
+
+common_ldadd = \
+	$(GLIB_LIBS)
+
+AM_CPPFLAGS = \
+	$(GLIB_CFLAGS) \
+	-I$(top_srcdir)/src \
+	-I$(top_srcdir)/src/common
+
+TEST_PROGS += entity_test
+entity_test_SOURCES = entity_test.c
+entity_test_LDADD = $(common_ldadd) ../entity.o
+
+noinst_PROGRAMS = $(TEST_PROGS)
+
+.PHONY: test
diff --git a/src/tests/entity_test.c b/src/tests/entity_test.c
new file mode 100644
index 0000000..86816ea
--- /dev/null
+++ b/src/tests/entity_test.c
@@ -0,0 +1,40 @@
+#include <glib.h>
+#include "mock_debug_print.h"
+
+#include "entity.h"
+
+static void
+test_entity(void)
+{
+	gchar *result;
+
+	result = entity_decode(NULL);
+	g_assert_null(result);
+
+	result = entity_decode("foo");
+	g_assert_null(result);
+
+	result = entity_decode("Á");
+	g_assert_nonnull(result);
+	if (g_test_verbose())
+		g_printerr("result '%s'\n", result);
+	g_assert_cmpstr(result, ==, "Á");
+	g_free(result);
+
+	result = entity_decode("{");
+	g_assert_nonnull(result);
+	if (g_test_verbose())
+		g_printerr("result '%s'\n", result);
+	g_assert_cmpstr(result, ==, "{");
+	g_free(result);
+}
+
+int
+main(int argc, char *argv[])
+{
+	g_test_init(&argc, &argv, NULL);
+
+	g_test_add_func("/core/entity", test_entity);
+
+	return g_test_run();
+}
diff --git a/src/tests/mock_debug_print.h b/src/tests/mock_debug_print.h
new file mode 100644
index 0000000..d9e8f69
--- /dev/null
+++ b/src/tests/mock_debug_print.h
@@ -0,0 +1,2 @@
+void debug_print_real (const gchar *format, ...) { return; }
+const char *debug_srcname(const char *file) { return NULL; }
diff --git a/tests.mk b/tests.mk
new file mode 100644
index 0000000..aa5a281
--- /dev/null
+++ b/tests.mk
@@ -0,0 +1,67 @@
+GTESTER        = gtester
+GTESTER_REPORT = gtester-report
+
+# initialize variables for unconditional += appending
+TEST_PROGS =
+
+### testing rules
+
+# test: run all tests in cwd and subdirs
+test: test-cwd test-recurse
+# test-cwd: run tests in cwd
+test-cwd: ${TEST_PROGS}
+	@[ -z "$(TEST_PROGS)" ] || { set -e; $(TESTS_ENVIRONMENT) ${GTESTER} --verbose ${TEST_PROGS}; }
+
+# test-recurse: run tests in subdirs
+test-recurse:
+	@ for subdir in $(SUBDIRS) ; do \
+	    test "$$subdir" = "." \
+			-o "$$subdir" = "config" \
+			-o "$$subdir" = "doc" \
+			-o "$$subdir" = "manual" \
+			-o "$$subdir" = "m4" \
+			-o "$$subdir" = "po" \
+			-o "$$subdir" = "tools" \
+			|| \
+	    ( cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) test ) || exit $? ; \
+	  done
+# test-report: run tests in subdirs and generate report
+# perf-report: run tests in subdirs with -m perf and generate report
+# full-report: like test-report: with -m perf and -m slow
+test-report perf-report full-report:	${TEST_PROGS}
+	@ ignore_logdir=true ; \
+	  if test -z "$$GTESTER_LOGDIR" ; then \
+	    GTESTER_LOGDIR=`mktemp -d "\`pwd\`/.testlogs-XXXXXX"`; export GTESTER_LOGDIR ; \
+	    ignore_logdir=false ; \
+	  fi ; \
+	  for subdir in $(SUBDIRS) ; do \
+	    test "$$subdir" = "." -o "$$subdir" = "po" -o "$$subdir" = "po-properties" || \
+	    ( cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $@ ) || exit $? ; \
+	  done ; \
+	  test -z "${TEST_PROGS}" || { \
+	    case $@ in \
+	    test-report) test_options="-k";; \
+	    perf-report) test_options="-k -m=perf";; \
+	    full-report) test_options="-k -m=perf -m=slow";; \
+	    esac ; \
+	    set -e; \
+	    if test -z "$$GTESTER_LOGDIR" ; then \
+	      ${GTESTER} --verbose $$test_options -o test-report.xml ${TEST_PROGS} ; \
+	    elif test -n "${TEST_PROGS}" ; then \
+	      ${GTESTER} --verbose $$test_options -o `mktemp "$$GTESTER_LOGDIR/log-XXXXXX"` ${TEST_PROGS} ; \
+	    fi ; \
+	  }; \
+	  $$ignore_logdir || { \
+	    echo '<?xml version="1.0"?>' > $@.xml ; \
+	    echo '<report-collection>'  >> $@.xml ; \
+	    for lf in `ls -L "$$GTESTER_LOGDIR"/.` ; do \
+	      sed '1,1s/^<?xml\b[^>?]*?>//' <"$$GTESTER_LOGDIR"/"$$lf" >> $@.xml ; \
+	    done ; \
+	    echo >> $@.xml ; \
+	    echo '</report-collection>' >> $@.xml ; \
+	    rm -rf "$$GTESTER_LOGDIR"/ ; \
+	    ${GTESTER_REPORT} --version 2>/dev/null 1>&2 ; test "$$?" != 0 || ${GTESTER_REPORT} $@.xml >$@.html ; \
+	  }
+.PHONY: test test-cwd test-recurse test-report perf-report full-report
+# run make test-cwd as part of make check
+check-local: test-cwd
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 98d8c50..d6c9d21 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -81,3 +81,5 @@ install-data-local:
 	mkdir -p ${pkgdatadir}
 	cp ${top_srcdir}/tools/ca-certificates.crt ${pkgdatadir}/
 endif
+
+.PHONY: test

commit 9b08d34901af73d99ff3f792df7e598465050710
Author: Andrej Kacian <ticho at claws-mail.org>
Date:   Fri Aug 31 13:43:59 2018 +0200

    md5.c doesn't need to include entire utils.h.

diff --git a/src/common/md5.c b/src/common/md5.c
index 03fbedc..611b9ea 100644
--- a/src/common/md5.c
+++ b/src/common/md5.c
@@ -37,9 +37,12 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
 
 #include "md5.h"
-#include "utils.h"
 
 /****************
  * Rotate a 32 bit integer by n bytes

commit 67bf3b862690c0ee9184e86a478bb1604228860b
Author: Andrej Kacian <ticho at claws-mail.org>
Date:   Fri Aug 31 13:39:04 2018 +0200

    Moved codeconv.[ch] and unmime.[ch] to common/ subdir.
    
    That's where they belong. This also clears up a few ugly
    cases of other files in common including "../codeconv.h".

diff --git a/src/Makefile.am b/src/Makefile.am
index 1fb6dcd..30e85a4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -137,7 +137,6 @@ claws_mail_SOURCES = \
 	alertpanel.c \
 	autofaces.c \
 	avatars.c \
-	codeconv.c \
 	compose.c \
 	crash.c \
 	customheader.c \
@@ -146,7 +145,7 @@ claws_mail_SOURCES = \
 	enriched.c \
 	entity.c \
 	export.c \
-        file_checker.c \
+	file_checker.c \
 	filtering.c \
 	folder.c \
 	folder_item_prefs.c \
@@ -236,7 +235,6 @@ claws_mail_SOURCES = \
 	textview.c \
 	toolbar.c \
 	undo.c \
-	unmime.c \
 	uri_opener.c \
 	wizard.c \
 	$(abook_source)
@@ -257,7 +255,6 @@ claws_mailinclude_HEADERS = \
 	alertpanel.h \
 	autofaces.h \
 	avatars.h \
-	codeconv.h \
 	compose.h \
 	crash.h \
 	customheader.h \
@@ -358,7 +355,6 @@ claws_mailinclude_HEADERS = \
 	textview.h \
 	toolbar.h \
 	undo.h \
-	unmime.h \
 	uri_opener.h \
 	viewtypes.h \
 	wizard.h \
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index f9ad434..56b6cdb 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -19,6 +19,7 @@ arch_header =
 endif
 
 libclawscommon_la_SOURCES = $(arch_sources) \
+	codeconv.c \
 	hooks.c \
 	log.c \
 	md5.c \
@@ -43,10 +44,12 @@ libclawscommon_la_SOURCES = $(arch_sources) \
 	uuencode.c \
 	xml.c \
 	xmlprops.c \
-	pkcs5_pbkdf2.c
+	pkcs5_pbkdf2.c \
+	unmime.c
 
 clawscommonincludedir = $(pkgincludedir)/common
 clawscommoninclude_HEADERS = $(arch_headers) \
+	codeconv.h \
 	defs.h \
 	hooks.h \
 	log.h \
@@ -75,7 +78,8 @@ clawscommoninclude_HEADERS = $(arch_headers) \
 	version.h \
 	xml.h \
 	xmlprops.h \
-	pkcs5_pbkdf2.h
+	pkcs5_pbkdf2.h \
+	unmime.h
 
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/intl \
diff --git a/src/codeconv.c b/src/common/codeconv.c
similarity index 100%
rename from src/codeconv.c
rename to src/common/codeconv.c
diff --git a/src/codeconv.h b/src/common/codeconv.h
similarity index 100%
rename from src/codeconv.h
rename to src/common/codeconv.h
diff --git a/src/common/template.c b/src/common/template.c
index 9e9e364..9d53d88 100644
--- a/src/common/template.c
+++ b/src/common/template.c
@@ -28,7 +28,7 @@
 
 #include "utils.h"
 #include "template.h"
-#include "../codeconv.h"
+#include "codeconv.h"
 
 static GSList *template_list;
 
diff --git a/src/unmime.c b/src/common/unmime.c
similarity index 100%
rename from src/unmime.c
rename to src/common/unmime.c
diff --git a/src/unmime.h b/src/common/unmime.h
similarity index 100%
rename from src/unmime.h
rename to src/common/unmime.h
diff --git a/src/common/utils.c b/src/common/utils.c
index 0a7f421..bf20ec3 100644
--- a/src/common/utils.c
+++ b/src/common/utils.c
@@ -83,7 +83,7 @@
 
 #include "utils.h"
 #include "socket.h"
-#include "../codeconv.h"
+#include "codeconv.h"
 #include "tlds.h"
 
 #define BUFFSIZE	8192
diff --git a/src/common/xml.c b/src/common/xml.c
index 4868d98..4127fd0 100644
--- a/src/common/xml.c
+++ b/src/common/xml.c
@@ -24,8 +24,7 @@
 
 #include "xml.h"
 #include "utils.h"
-/* UGLY! */
-#include "../codeconv.h"
+#include "codeconv.h"
 
 #define SPARSE_MEMORY
 /* if this is defined all attr.names and tag.names are stored
diff --git a/src/plugins/rssyl/libfeed/parser_opml.c b/src/plugins/rssyl/libfeed/parser_opml.c
index 09e34aa..dc31980 100644
--- a/src/plugins/rssyl/libfeed/parser_opml.c
+++ b/src/plugins/rssyl/libfeed/parser_opml.c
@@ -23,7 +23,7 @@
 #include <string.h>
 #include <ctype.h>
 
-#include <codeconv.h>
+#include <common/codeconv.h>
 
 #include "feed.h"
 

commit c76dd4709f160b719d3b96c9e3ecca943a9fd975
Author: Andrej Kacian <ticho at claws-mail.org>
Date:   Fri Aug 31 13:29:48 2018 +0200

    Decouple codeconv.c from prefs_common.

diff --git a/src/codeconv.c b/src/codeconv.c
index 0865f2c..9b59e7d 100644
--- a/src/codeconv.c
+++ b/src/codeconv.c
@@ -39,7 +39,6 @@
 #include "unmime.h"
 #include "quoted-printable.h"
 #include "utils.h"
-#include "prefs_common.h"
 
 /* For unknown reasons the inconv.m4 macro undefs that macro if no
    const is needed.  This would break the code below so we define it. */
@@ -145,11 +144,23 @@ static gint conv_anytodisp(gchar *outbuf, gint outlen, const gchar *inbuf);
 static gint conv_ustodisp(gchar *outbuf, gint outlen, const gchar *inbuf);
 static gint conv_noconv(gchar *outbuf, gint outlen, const gchar *inbuf);
 
-static gboolean strict_mode = FALSE;
+static gboolean codeconv_strict_mode = FALSE;
+static gboolean codeconv_allow_jisx0201_kana = FALSE;
+static gboolean codeconv_broken_are_utf8 = FALSE;
 
 void codeconv_set_strict(gboolean mode)
 {
-	strict_mode = mode;
+	codeconv_strict_mode = mode;
+}
+
+void codeconv_set_allow_jisx0201_kana(gboolean allow)
+{
+	codeconv_allow_jisx0201_kana = allow;
+}
+
+void codeconv_set_broken_are_utf8(gboolean are)
+{
+	codeconv_broken_are_utf8 = are;
 }
 
 static gint conv_jistoeuc(gchar *outbuf, gint outlen, const gchar *inbuf)
@@ -329,7 +340,7 @@ static gint conv_euctojis(gchar *outbuf, gint outlen, const gchar *inbuf)
 			}
 		} else if (iseuchwkana1(*in)) {
 			if (iseuchwkana2(*(in + 1))) {
-				if (prefs_common.allow_jisx0201_kana) {
+				if (codeconv_allow_jisx0201_kana) {
 					HW_IN();
 					in++;
 					*out++ = *in++ & 0x7f;
@@ -835,7 +846,7 @@ gchar *conv_codeset_strdup(const gchar *inbuf,
 
 	if (!strcmp2(src_code, dest_code)) {
 		CharSet dest_charset = conv_get_charset_from_str(dest_code);
-		if (strict_mode && dest_charset == C_UTF_8) {
+		if (codeconv_strict_mode && dest_charset == C_UTF_8) {
 			/* ensure valid UTF-8 if target is UTF-8 */
 			if (!g_utf8_validate(inbuf, -1, NULL)) {
 				return NULL;
@@ -847,14 +858,16 @@ gchar *conv_codeset_strdup(const gchar *inbuf,
 
 	src_code = conv_get_fallback_for_private_encoding(src_code);
 	conv_func = conv_get_code_conv_func(src_code, dest_code);
-	if (conv_func == conv_ustodisp && strict_mode && !is_ascii_str(inbuf))
+	if (conv_func == conv_ustodisp
+			&& codeconv_strict_mode
+			&& !is_ascii_str(inbuf))
 		return NULL;
 
 	if (conv_func != conv_noconv) {
 		len = (strlen(inbuf) + 1) * 3;
 		buf = g_malloc(len);
 
-		if (conv_func(buf, len, inbuf) == 0 || !strict_mode)
+		if (conv_func(buf, len, inbuf) == 0 || !codeconv_strict_mode)
 			return g_realloc(buf, strlen(buf) + 1);
 		else {
 			g_free(buf);
@@ -1024,7 +1037,7 @@ gchar *conv_iconv_strdup_with_cd(const gchar *inbuf, iconv_t cd)
 	while ((n_conv = iconv(cd, (ICONV_CONST gchar **)&inbuf_p, &in_left,
 			       &outbuf_p, &out_left)) == (size_t)-1) {
 		if (EILSEQ == errno) {
-			if (strict_mode) {
+			if (codeconv_strict_mode) {
 				g_free(outbuf);
 				return NULL;
 			}
@@ -1442,7 +1455,7 @@ static CharSet conv_get_locale_charset_no_utf8(void)
 	const gchar *p;
 	gint i;
 
-	if (prefs_common.broken_are_utf8) {
+	if (codeconv_broken_are_utf8) {
 		cur_charset = C_UTF_8;
 		return cur_charset;
 	}
@@ -1768,7 +1781,7 @@ void conv_encode_header_full(gchar *dest, gint len, const gchar *src,
 				out_str = conv_codeset_strdup
 					(part_str, cur_encoding, out_encoding);
 				if (!out_str) {
-					if (strict_mode) {
+					if (codeconv_strict_mode) {
 						*dest = '\0';
 						return;
 					} else {
diff --git a/src/codeconv.h b/src/codeconv.h
index 4109a13..2704985 100644
--- a/src/codeconv.h
+++ b/src/codeconv.h
@@ -218,5 +218,9 @@ void conv_encode_header_full		(gchar		*dest,
 
 gchar *conv_filename_from_utf8		(const gchar	*utf8_file);
 gchar *conv_filename_to_utf8		(const gchar	*fs_file);
+
 void codeconv_set_strict		(gboolean	 mode);
+void codeconv_set_allow_jisx0201_kana	(gboolean	 allow);
+void codeconv_set_broken_are_utf8	(gboolean	 are);
+
 #endif /* __CODECONV_H__ */
diff --git a/src/main.c b/src/main.c
index 1c7345e..ce6de6a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1273,6 +1273,9 @@ int main(int argc, char *argv[])
 	prefs_spelling_init();
 #endif
 
+	codeconv_set_allow_jisx0201_kana(prefs_common.allow_jisx0201_kana);
+	codeconv_set_broken_are_utf8(prefs_common.broken_are_utf8);
+
 #ifdef G_OS_WIN32
 	if(prefs_common.gtk_theme && strcmp(prefs_common.gtk_theme, DEFAULT_W32_GTK_THEME))
 		gtk_settings_set_string_property(gtk_settings_get_default(),

commit ab7e2b272a7c5017296571c38cf0c263989a35ab
Author: Andrej Kacian <ticho at claws-mail.org>
Date:   Fri Aug 31 13:28:16 2018 +0200

    Add parameter sanity checks to md5_hex_digest() and md5_hex_hmac().

diff --git a/src/common/md5.c b/src/common/md5.c
index 9da14ea..03fbedc 100644
--- a/src/common/md5.c
+++ b/src/common/md5.c
@@ -384,6 +384,8 @@ md5_hex_digest_file(char *hexdigest, const unsigned char *file)
 void
 md5_hex_digest(char *hexdigest, const unsigned char *s)
 {
+	g_return_if_fail(hexdigest != NULL);
+	g_return_if_fail(s != NULL);
 	md5_hex_digest_binary(hexdigest, s, strlen(s));
 }
 
@@ -469,6 +471,12 @@ md5_hex_hmac(char *hexdigest,
 	unsigned char digest[16];
 	int i;
 
+	g_return_if_fail(key != NULL);
+	g_return_if_fail(key_len >= 0);
+	g_return_if_fail(text != NULL);
+	g_return_if_fail(text_len >= 0);
+	g_return_if_fail(hexdigest != NULL);
+
 	md5_hmac(digest, text, text_len, key, key_len);
 	for (i = 0; i < 16; i++)
 		sprintf(hexdigest + 2 * i, "%02x", digest[i]);

commit 592f6d132518eb0609953a178adffd20a9151d1b
Author: Olivier Brunel <jjk at jjacky.com>
Date:   Wed Dec 27 21:59:40 2017 +0100

    Preserve flags & tags when re-editing a message
    
    When re-editing a message, let's preserve its flags (color labels, etc)
    and tags. Can be especially useful for those who use such things on queued
    messages, and find themselves re-editing messages afterwards but before
    actually sending them.

diff --git a/src/compose.c b/src/compose.c
index a58f487..0904c35 100644
--- a/src/compose.c
+++ b/src/compose.c
@@ -2383,6 +2383,7 @@ Compose *compose_reedit(MsgInfo *msginfo, gboolean batch)
 	}
 
 	compose->targetinfo = procmsg_msginfo_copy(msginfo);
+	compose->targetinfo->tags = g_slist_copy(msginfo->tags);
 
 	compose_extract_original_charset(compose);
 
@@ -6320,6 +6321,20 @@ static ComposeQueueResult compose_queue_sub(Compose *compose, gint *msgnum, Fold
 	} else
 		*msgpath = tmp;
 
+	if (compose->mode == COMPOSE_REEDIT && compose->targetinfo) {
+		MsgInfo *mi = folder_item_get_msginfo(queue, num);
+		if (mi) {
+			procmsg_msginfo_change_flags(mi,
+				compose->targetinfo->flags.perm_flags,
+				compose->targetinfo->flags.tmp_flags & ~(MSG_COPY | MSG_MOVE | MSG_MOVE_DONE),
+				0, 0);
+
+			g_slist_free(mi->tags);
+			mi->tags = g_slist_copy(compose->targetinfo->tags);
+			procmsg_msginfo_free(&mi);
+		}
+	}
+
 	if (compose->mode == COMPOSE_REEDIT && remove_reedit_target) {
 		compose_remove_reedit_target(compose, FALSE);
 	}

commit 892aff4b19956a75c05b4a7373d2e1edfcfc01fe
Author: Olivier Brunel <jjk at jjacky.com>
Date:   Wed Dec 27 21:53:17 2017 +0100

    action: Keep selection set afterwards
    
    Upon running (filtering) actions, the current selection was lost (due to
    refreshing the current folder); Let's restore it.

diff --git a/src/action.c b/src/action.c
index c6dd10f..af62f37 100644
--- a/src/action.c
+++ b/src/action.c
@@ -627,6 +627,7 @@ static void mainwin_actions_execute(MainWindow *mainwin, guint action_nb,
 
 	msg_list = summary_get_selected_msg_list(mainwin->summaryview);
 	message_actions_execute(mainwin->messageview, action_nb, msg_list);
+	summary_select_by_msg_list(mainwin->summaryview, msg_list);
 	g_slist_free(msg_list);
 }
 

commit ff4c2884e57ce8edb5634db9cf61d76c2198247f
Author: Olivier Brunel <jjk at jjacky.com>
Date:   Wed Aug 2 20:48:58 2017 +0200

    Speed-up searches in References via "x"
    
    Since commit 5c9f9e47 (in 2001!) the header "References" is actually
    cached in MsgInfo, so searching it can be substantially faster if "x"
    expands to 'references' instead of 'header "References"', much like with
    'i' (messageid) or 'I' (inreplyto).

diff --git a/src/advsearch.c b/src/advsearch.c
index ecd3acd..ccfad6c 100644
--- a/src/advsearch.c
+++ b/src/advsearch.c
@@ -186,7 +186,7 @@ gchar *advsearch_expand_search_string(const gchar *search_string)
 		{ "tg", "tag",				1,	TRUE,	TRUE  },
 		{ "T",	"marked",			0,	FALSE,	FALSE },
 		{ "U",	"unread",			0,	FALSE,	FALSE },
-		{ "x",	"header \"References\"",	1,	TRUE,	TRUE  },
+		{ "x",	"references",			1,	TRUE,	TRUE  },
 		{ "X",  "test",				1,	FALSE,  FALSE },
 		{ "y",	"header \"X-Label\"",		1,	TRUE,	TRUE  },
 		{ "&",	"&",				0,	FALSE,	FALSE },

commit 92c7a4301377ba64de781d41e08127e5b8d3a778
Author: wwp <subscript at free.fr>
Date:   Thu Aug 30 08:29:30 2018 +0200

    Fix wrong logics leading to writing possibly broken config file,
    patch by Olivier Brunel.

diff --git a/src/common/prefs.c b/src/common/prefs.c
index d621a7a..23bcc22 100644
--- a/src/common/prefs.c
+++ b/src/common/prefs.c
@@ -278,7 +278,7 @@ gint prefs_set_block_label(PrefFile *pfile, const gchar *label)
 {
 	gchar *block_label;
 	gchar buf[BUFFSIZE];
-	
+
 	block_label = g_strdup_printf("[%s]", label);
 	if (!pfile->writing) {
 		while (fgets(buf, sizeof(buf), pfile->fp) != NULL) {
@@ -296,7 +296,7 @@ gint prefs_set_block_label(PrefFile *pfile, const gchar *label)
 
 			while (fgets(buf, sizeof(buf), pfile->orig_fp) != NULL) {
 				gint val;
-				
+
 				val = strncmp(buf, block_label, strlen(block_label));
 				if (val == 0) {
 					debug_print("Found %s\n", block_label);
@@ -312,20 +312,20 @@ gint prefs_set_block_label(PrefFile *pfile, const gchar *label)
 					}
 				}
 			}
-			
+
 			if (!block_matched) {
 				fclose(pfile->orig_fp);
 				pfile->orig_fp = NULL;
 			}
-			
-			if (fputs(block_label, pfile->fp) == EOF ||
-			    fputc('\n', pfile->fp) == EOF) {
-				g_warning("failed to write configuration to file");
-				prefs_file_close_revert(pfile);
-				g_free(block_label);
-						
-				return -1;
-			}
+		}
+
+		if (fputs(block_label, pfile->fp) == EOF ||
+			fputc('\n', pfile->fp) == EOF) {
+			g_warning("failed to write configuration to file");
+			prefs_file_close_revert(pfile);
+			g_free(block_label);
+
+			return -1;
 		}
 	}
 

commit a0a7b52b6eb1a13f6fa332498d48681feb94096e
Author: Ricardo Mones <ricardo at mones.org>
Date:   Tue Aug 28 12:54:43 2018 +0200

    Restore Fancy entry in README, still in tarball ;)
    
    Thanks Woody for noticing.

diff --git a/README b/README
index a80505c..6ec822d 100644
--- a/README
+++ b/README
@@ -130,6 +130,13 @@ All plugin preferences can be found under
     view and to render the HTML safely. If required, remote content
     can be also retrieved.
 
+  o Fancy
+    Renders HTML mails and HTML parts of multipart messages using the
+    GTK+ port of the WebKit library. External content is blocked by
+    default (including images) to avoid remote tracking, but can be
+    enabled either globally or just on the displayed message. The GTK+
+    WebKit is available from http://trac.webkit.org/wiki/WebKitGTK/.
+
   o Fetchinfo
     Modifies downloaded messages and inserts special headers containing 
     some download information: UIDL, Claws Mail account name, POP server, 

commit b4d2f3de0144c634b78e65465dd06589a91e5516
Author: Paul <paul at claws-mail.org>
Date:   Mon Aug 27 18:42:44 2018 +0100

    fix lintian autotools-pkg-config-macro-not-cross-compilation-safe warning
    
    see
    https://lintian.debian.org/tags/autotools-pkg-config-macro-not-cross-compilation-safe.html

diff --git a/configure.ac b/configure.ac
index 55cbec9..05dc923 100644
--- a/configure.ac
+++ b/configure.ac
@@ -65,10 +65,7 @@ AC_SUBST(GIT_VERSION)
 AC_CHECK_PROG(HAVE_GTK_ICON_CACHE, gtk-update-icon-cache, yes, no)
 AM_CONDITIONAL(UPDATE_GTK_ICON_CACHE, test x"$HAVE_GTK_ICON_CACHE" = xyes)
 
-AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
-if test x$PKG_CONFIG = xno ; then
-  AC_MSG_ERROR([*** pkg-config not found. See http://www.freedesktop.org/software/pkgconfig/])
-fi
+PKG_PROG_PKG_CONFIG
 
 dnl libtool versioning
 LT_RELEASE=$MAJOR_VERSION.$MINOR_VERSION
@@ -423,7 +420,7 @@ 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)
 
-GLIB_GENMARSHAL=`pkg-config --variable=glib_genmarshal glib-2.0`
+GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0`
 AC_SUBST(GLIB_GENMARSHAL)
 
 AC_SUBST(GLIB_CFLAGS)

commit 9b183f5b1138280863bb21c89c4813a1886d2872
Author: Ricardo Mones <ricardo at mones.org>
Date:   Mon Aug 27 18:43:08 2018 +0200

    Update plugins in README

diff --git a/README b/README
index 78b794a..a80505c 100644
--- a/README
+++ b/README
@@ -2,9 +2,9 @@ Claws Mail - a GTK+ based, lightweight, and fast e-mail client
 
 ---------------------------------------------------------------------
 
-   Copyright (C) 1999-2017 The Claws Mail Team and Hiroyuki Yamamoto
+   Copyright (C) 1999-2018 The Claws Mail Team and Hiroyuki Yamamoto
    <hiro-y at kcn.ne.jp>
-   
+
 
    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
@@ -123,19 +123,19 @@ All plugin preferences can be found under
     daemon, so it has to be previously configured to allow this. 
     Clam AntiVirus is available from http://www.clamav.net/.
 
+  o Dillo
+    Uses the Dillo browser (http://www.dillo.org) to render HTML mails
+    and HTML parts of multipart messages. Dillo is started with
+    special options to embed its window inside Claws Mail's message
+    view and to render the HTML safely. If required, remote content
+    can be also retrieved.
+
   o Fetchinfo
     Modifies downloaded messages and inserts special headers containing 
     some download information: UIDL, Claws Mail account name, POP server, 
     user ID and retrieval time. These headers can be used later for more 
     elaborate filtering or processing rules.
 
-  o Fancy
-    Renders HTML mails and HTML parts of multipart messages using the GTK+ 
-    port of the WebKit library. External content is blocked by default 
-    (including images) to avoid remote tracking, but can be enabled either 
-    globally or just on the displayed message.
-    GTK+ WebKit is available from http://trac.webkit.org/wiki/WebKitGTK/.
-
   o GData
     Includes your Gmail account contacts in the list generated for 
     Tab-address completion on compose window, using the GData library.

commit 83362ed4242d1fff927fb0cecf6bd2f22fde9e77
Author: wwp <subscript at free.fr>
Date:   Sun Aug 26 18:01:02 2018 +0200

    Fix wrong test leading to dead code (and dead func), CID 1438531.

diff --git a/src/codeconv.c b/src/codeconv.c
index b200f35..0865f2c 100644
--- a/src/codeconv.c
+++ b/src/codeconv.c
@@ -1884,7 +1884,7 @@ gchar *conv_filename_to_utf8(const gchar *fs_file)
 	gchar *utf8_file = NULL;
 	GError *error = NULL;
 
-	cm_return_val_if_fail(utf8_file != NULL, NULL);
+	cm_return_val_if_fail(fs_file != NULL, NULL);
 
 	utf8_file = g_filename_to_utf8(fs_file, -1, NULL, NULL, &error);
 	if (error) {

commit 566182e3904ae4c37cf609d7f2d391ac40a86787
Author: Paul <paul at claws-mail.org>
Date:   Sun Aug 26 14:36:51 2018 +0100

    always show the full version on the mainwindow regardless of --enable-maintainer-mode

diff --git a/src/common/version.h.in b/src/common/version.h.in
index c441b6f..8b6a0e5 100644
--- a/src/common/version.h.in
+++ b/src/common/version.h.in
@@ -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-2018 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
@@ -28,13 +28,7 @@
 #define PACKAGE			"@PACKAGE@"
 #define PACKAGE_FRIENDLY	"Claws Mail"
 #define VERSION			"@VERSION@"
-#define RELEASE_VERSION		"@MAJOR_VERSION at .@MINOR_VERSION at .@MICRO_VERSION@"
 #define PROG_VERSION		PACKAGE_FRIENDLY" "VERSION
-#ifdef USE_MAINTAINER_MODE
-#define PROG_VERSION_FRIENDLY	PROG_VERSION
-#else
-#define PROG_VERSION_FRIENDLY	PACKAGE_FRIENDLY" "RELEASE_VERSION
-#endif
 #define VERSION_NUMERIC		MAKE_NUMERIC_VERSION(@MAJOR_VERSION@, @MINOR_VERSION@, \
 						     @MICRO_VERSION@, @EXTRA_VERSION@)
 #define VERSION_GIT_FULL	"@GIT_VERSION@"
diff --git a/src/mainwindow.c b/src/mainwindow.c
index ef8a280..775eafc 100644
--- a/src/mainwindow.c
+++ b/src/mainwindow.c
@@ -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-2018 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
@@ -1445,7 +1445,7 @@ MainWindow *main_window_create()
 
 	/* main window */
 	window = GTK_WIDGET(gtkut_window_new(GTK_WINDOW_TOPLEVEL, "mainwindow"));
-	gtk_window_set_title(GTK_WINDOW(window), PROG_VERSION_FRIENDLY);
+	gtk_window_set_title(GTK_WINDOW(window), PROG_VERSION);
 	gtk_window_set_resizable(GTK_WINDOW(window), TRUE);
 #ifdef GENERIC_UMPC
 	prefs_common.layout_mode = SMALL_LAYOUT;
@@ -2626,9 +2626,9 @@ static void main_window_show_cur_account(MainWindow *mainwin)
 			   : _("none"));
 
 	if (cur_account)
-		buf = g_strdup_printf("%s - %s", ac_name, PROG_VERSION_FRIENDLY);
+		buf = g_strdup_printf("%s - %s", ac_name, PROG_VERSION);
 	else
-		buf = g_strdup(PROG_VERSION_FRIENDLY);
+		buf = g_strdup(PROG_VERSION);
 	gtk_window_set_title(GTK_WINDOW(mainwin->window), buf);
 	g_free(buf);
 

commit 55724482001168c38b98c338aa6ec32da346a2a0
Author: Paul <paul at claws-mail.org>
Date:   Sun Aug 26 12:21:52 2018 +0100

    for release 3.17.1

diff --git a/NEWS b/NEWS
index 05ff6b2..232559c 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,14 @@
 Changes of the  Claws Mail GTK2 branch
 
+* 3.17.1
+--------
+
+* bug fixes:
+	o bug 4072, 'Crash when clicking 'reply' or 'reply with
+	  quote''
+	o Account signature: Warn and fail rather than crashing when
+	  format string is faulty.
+
 * 3.17.0
 --------
 
diff --git a/README b/README
index 153538b..78b794a 100644
--- a/README
+++ b/README
@@ -660,6 +660,7 @@ http://www.thewildbeast.co.uk/claws-mail/bugzilla/index.cgi
 
 GTK 2 Version
 -------------
+2018-08-26	3.17.1
 2018-08-15	3.17.0
 2017-12-17	3.16.0
 2017-08-29	3.15.1
diff --git a/RELEASE_NOTES b/RELEASE_NOTES
index a976714..bc983e8 100644
--- a/RELEASE_NOTES
+++ b/RELEASE_NOTES
@@ -1,4 +1,4 @@
-15th August 2018                                    Claws Mail 3.17.0
+26th August 2018                                    Claws Mail 3.17.1
 
 		    CLAWS MAIL  RELEASE NOTES
                     http://www.claws-mail.org
@@ -6,143 +6,14 @@
 Claws Mail is a GTK+ based, user-friendly, lightweight, and fast 
 email client.
 
-New in this release:
-~~~~~~~~~~~~~~~~~~~~
-
-* the minimum GLib requirement is now 2.28.
-
-* the mimimum GTK+2 requirement is now  2.24.
-
-* nettle is now required, following removal of libcrypt from glibc.
-
-* explicit use of --disable-gnutls is now required if gnuTLS support
-  is not required.
-
-* SOCKS proxy support has been added.
-  Global settings can be found on the Mail Handling/Proxy page.
-  This can be overridden by Account settings on the new Proxy page.
-
-* Accounts can now have their own auto-check intervals, or follow the
-  global interval.
-
-* in the options for 'default selection when entering a folder',
-  'first [...]' has been renamed to 'oldest [...]', and
-  'newest [...]' items have been added.
-
-* Message List: when changing sort key by clicking column header,
-  the sort direction is now preserved
-
-* Message View: keypress handling for scrolling, (PgUp/Down, Space,
-  Backspace), has been improved.
-
-* the Network Log now displays output from LDAP operations.
-
-* "Go to last error" has been added to the Log Window context menu.
-
-* Filtering/Processing: "mark_as_spam" is no longer a final action,
-  since it does not move the marked message.
-
-* Filtering/Processing: Resent-From and Resent-To have been added in
-  Any/All header(s) (in Address Book) matcher rules.
-
-* when a Return-Receipt request is received by an unknown address,
-  the user is now required to choose which Account to send it from.
-
-* Colour Labels: confirmation is asked for when clearing or
-  overriding existing colour labels.
-
-* Address Book: basic contact merging has been added.
-
-* NetworkManager support: ported from libnm-util/libnm-glib to libnm.
-
-* Dillo plugin: this HTML rendering plugin is now once again
-  available.
-
-* RSSyl plugin: the modified time is no longer considered when
-  matching deleted items.
-
-* RSSyl plugin: Handle 404 and other fetch failures better.
-
-* Attachment Remover plugin: the user is now notified about what has
-  been done when processing multiple selections.
-
-* SpamAssassin plugin: added support for compression (the server must
-  have compression enabled, and the local spamc too).
-
-* SpamAssassin plugin: disabled SSLv3.
-
-* when using the hidden preference, hide_timezone, the time in the
-  Date header is converted to UTC.
-
-* various other UI improvements.
-
-* many behind-the-scenes improvements.
-
-* updated translations: Brazilian Portuguese, Catalan, Czech, Danish,
-	Dutch, Finnish, French, German, Hungarian, Norwegian Bokmål,
-	Romanian, Russian, Slovak, Spanish, Swedish, Traditional
-	Chinese, Turkish.
+This is a bug-fix release:
+~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 * bug fixes:
-	o bug 3754, 'interactive auth dialogs pops endlessly'
-	o bug 3919, 'manual filtering does not move spam'
-	o bug 3936, 'LDAP StartTLS does not work for addressbooks'
-	o bug 3947, 'Build break with --disable-libsm
-	             --enable-crash-dialog'
-	o bug 3957, 'Claws-Mail 64bit crashes when saving a draft'
-	o bug 3960, 'Sends unencrypted emails when encryption fails'
-	o bug 3971, 'Deleted rss feed item reappears as unread on
-		     feed refreshing'
-	o bug 3973, ''select all' in summaryview does not
-		     automatically focus the summaryview'
-	o bug 3978, '"From" column displays both name and email
-		     address for Outbox'
-	o bug 3984, 'Copy-paste in find/filter field works
-		     incorrectly'
-	o bug 3985, 'an empty progress bar remains after POP mail 
-		     check completes'
-	o bug 3986, 'IMAP quick search using non-ASCII characters
-		     creates an infinite loop'
-	o bug 3993, 'Claws Mail connects to IMAP server when it
-		     should not'
-	o bug 4014, '"Work offline" doesn't seem to affect RSS'
-	o bug 4022, 'Closing "Account Preferences" window opens "Edit
-	 	     Accounts" window if "Edit Accounts" window has
-	 	     been opened before at least once'
-	o bug 4023, 'Fix some small issues'
-	o bug 4033, 'Claws Mail crashes [malloc(): memory corruption]
-		     while trying to save account password greater
-		     than 136 chars'
-	o bug 4056, 'Impossible to disable overriding of offline
-		     mode'
-	o bug 4058, '# in extended search description window should
-		     not be translated'
-	o bug 4068, 'Claws Mail hangs when getting news from a
-		     certain feed'
-	o actionsrc was not updated after mailbox name change
-	o two crashes caused by bad GtkListStore management in
-	  editaddress.c
-	o wrong malloc of clamd_socket struct, (CID 1220477)
-	o vCalendar: possible access to uninitilized folder pointer
-	  (CID 1402515)
-	o vCalendar: mismatch and unneeded display of unavailable
-	  folder class in warning (CID 1434197)
-	o vCalendar: Skip whitespace chars at the beginning of ics
-	  stream
-	o buffer overrun, always writing at buffer size + 1. (CID
-	  1434188)
-	o wrong use of pointer-to-array as an array CID 1434191)
-	o sensitivity of few preferences widgets of the SA plug-in
-	o compilation using --enable-generic-umpc
-	o crash in quicksearch keypress handling
-	o quoting in reply to format=flowed message
-	o HTML <hX> header handling
-	o 'sort_type' is lost when changing 'sort_key' from
-	  /View/sort the bug was apparent with a descending sort
-	o Return-Receipts: MDN mail-accountname leak
-	o auth retry in Managesieve - wrong state variable was being
-	  set
-	o memory leaks
+	o bug 4072, 'Crash when clicking 'reply' or 'reply with
+	  quote''
+	o Account signature: Warn and fail rather than crashing when
+	  format string is faulty.
 
 For further details of the numbered bugs and RFEs listed above
 see https://www.claws-mail.org/bug/[BUG NUMBER]

-----------------------------------------------------------------------


hooks/post-receive
-- 
Claws Mail


More information about the Commits mailing list