diff -Nru geary-0.12.2/CMakeLists.txt geary-0.12.4/CMakeLists.txt --- geary-0.12.2/CMakeLists.txt 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/CMakeLists.txt 2018-08-29 13:57:20.000000000 +0000 @@ -19,7 +19,7 @@ # set(GETTEXT_PACKAGE "geary") set(RELEASE_NAME "Lightweight email client for GNOME.") -set(VERSION "0.12.2") +set(VERSION "0.12.4") set(VERSION_INFO "Release") set(LANGUAGE_SUPPORT_DIRECTORY ${CMAKE_INSTALL_PREFIX}/share/locale) diff -Nru geary-0.12.2/debian/changelog geary-0.12.4/debian/changelog --- geary-0.12.2/debian/changelog 2018-05-13 17:17:50.000000000 +0000 +++ geary-0.12.4/debian/changelog 2018-09-15 15:03:58.000000000 +0000 @@ -1,3 +1,18 @@ +geary (0.12.4-2) unstable; urgency=medium + + * Cherry-pick 3 patches to fix build with webkit2gtk 2.22 + * Bump minimum libwebkit2gtk-4.0-dev to 2.22 + + -- Jeremy Bicha Sat, 15 Sep 2018 11:03:58 -0400 + +geary (0.12.4-1) unstable; urgency=medium + + * New upstream release (Closes: #904387, #907942) + * Opt in to Ubuntu language packs (LP: #1779574) + * Bump Standards-Version to 4.2.1 + + -- Jeremy Bicha Tue, 04 Sep 2018 21:42:43 -0400 + geary (0.12.2-2) unstable; urgency=medium * Adjust ugly hack to use linux-firmware-free instead of openrc diff -Nru geary-0.12.2/debian/control geary-0.12.4/debian/control --- geary-0.12.2/debian/control 2018-05-13 17:17:50.000000000 +0000 +++ geary-0.12.4/debian/control 2018-09-15 15:03:58.000000000 +0000 @@ -6,7 +6,7 @@ Section: mail Priority: optional Maintainer: Debian GNOME Maintainers -Uploaders: Jeremy Bicha , Vincent Cheng +Uploaders: Jeremy Bicha Build-Depends: cmake (>= 2.8.0), debhelper (>= 11), desktop-file-utils, @@ -26,10 +26,11 @@ libnotify-dev (>= 0.7.5), libsecret-1-dev (>= 0.11), libsqlite3-dev (>= 3.7.4), - libwebkit2gtk-4.0-dev (>= 2.10), + libwebkit2gtk-4.0-dev (>= 2.22), libxml2-dev (>= 2.7.8), valac (>= 0.22.1) -Standards-Version: 4.1.4 +Standards-Version: 4.2.1 +X-Ubuntu-Use-Langpack: yes Homepage: https://wiki.gnome.org/Apps/Geary Vcs-Git: https://salsa.debian.org/gnome-team/geary.git Vcs-Browser: https://salsa.debian.org/gnome-team/geary diff -Nru geary-0.12.2/debian/control.in geary-0.12.4/debian/control.in --- geary-0.12.2/debian/control.in 2018-05-13 17:17:50.000000000 +0000 +++ geary-0.12.4/debian/control.in 2018-09-15 15:03:58.000000000 +0000 @@ -22,10 +22,11 @@ libnotify-dev (>= 0.7.5), libsecret-1-dev (>= 0.11), libsqlite3-dev (>= 3.7.4), - libwebkit2gtk-4.0-dev (>= 2.10), + libwebkit2gtk-4.0-dev (>= 2.22), libxml2-dev (>= 2.7.8), valac (>= 0.22.1) -Standards-Version: 4.1.4 +Standards-Version: 4.2.1 +X-Ubuntu-Use-Langpack: yes Homepage: https://wiki.gnome.org/Apps/Geary Vcs-Git: https://salsa.debian.org/gnome-team/geary.git Vcs-Browser: https://salsa.debian.org/gnome-team/geary diff -Nru geary-0.12.2/debian/gbp.conf geary-0.12.4/debian/gbp.conf --- geary-0.12.2/debian/gbp.conf 2018-05-13 17:17:50.000000000 +0000 +++ geary-0.12.4/debian/gbp.conf 2018-09-15 15:03:58.000000000 +0000 @@ -3,3 +3,12 @@ debian-branch = debian/master upstream-branch = upstream/latest upstream-vcs-tag = geary-%(version)s + +[buildpackage] +sign-tags = True + +[import-orig] +postimport = dch -v%(version)s New upstream release; git add debian/changelog; debcommit + +[pq] +patch-numbers = False diff -Nru geary-0.12.2/debian/patches/Adjust-to-upstream-javascriptcore-4.0-bindings.patch geary-0.12.4/debian/patches/Adjust-to-upstream-javascriptcore-4.0-bindings.patch --- geary-0.12.2/debian/patches/Adjust-to-upstream-javascriptcore-4.0-bindings.patch 1970-01-01 00:00:00.000000000 +0000 +++ geary-0.12.4/debian/patches/Adjust-to-upstream-javascriptcore-4.0-bindings.patch 2018-09-15 15:03:58.000000000 +0000 @@ -0,0 +1,184 @@ +From: Rico Tzschichholz +Date: Mon, 23 Apr 2018 19:56:18 +0200 +Subject: Adjust to upstream javascriptcore-4.0 bindings + +--- + .../conversation-viewer/conversation-web-view.vala | 2 +- + src/client/util/util-webkit.vala | 10 ++++---- + src/client/web-process/web-process-extension.vala | 17 +++++------- + src/engine/util/util-js.vala | 30 +++++++++++++++------- + 4 files changed, 33 insertions(+), 26 deletions(-) + +diff --git a/src/client/conversation-viewer/conversation-web-view.vala b/src/client/conversation-viewer/conversation-web-view.vala +index 3d2ac5f..ef69f44 100644 +--- a/src/client/conversation-viewer/conversation-web-view.vala ++++ b/src/client/conversation-viewer/conversation-web-view.vala +@@ -183,7 +183,7 @@ public class ConversationWebView : ClientWebView { + + private void on_deceptive_link_clicked(WebKit.JavascriptResult result) { + try { +- JS.GlobalContext context = result.get_global_context(); ++ unowned JS.GlobalContext context = result.get_global_context(); + JS.Object details = WebKitUtil.to_object(result); + + uint reason = (uint) Geary.JS.to_number( +diff --git a/src/client/util/util-webkit.vala b/src/client/util/util-webkit.vala +index 319e28a..cba9eaf 100644 +--- a/src/client/util/util-webkit.vala ++++ b/src/client/util/util-webkit.vala +@@ -18,8 +18,8 @@ namespace WebKitUtil { + */ + public bool to_bool(WebKit.JavascriptResult result) + throws Geary.JS.Error { +- JS.GlobalContext context = result.get_global_context(); +- JS.Value value = result.get_value(); ++ unowned JS.GlobalContext context = result.get_global_context(); ++ unowned JS.Value value = result.get_value(); + if (!value.is_boolean(context)) { + throw new Geary.JS.Error.TYPE("Result is not a JS Boolean object"); + } +@@ -59,12 +59,12 @@ namespace WebKitUtil { + */ + public string as_string(WebKit.JavascriptResult result) + throws Geary.JS.Error { +- JS.GlobalContext context = result.get_global_context(); +- JS.Value js_str_value = result.get_value(); ++ unowned JS.GlobalContext context = result.get_global_context(); ++ unowned JS.Value js_str_value = result.get_value(); + JS.Value? err = null; + JS.String js_str = js_str_value.to_string_copy(context, out err); + Geary.JS.check_exception(context, err); +- return Geary.JS.to_string_released(js_str); ++ return Geary.JS.to_string_released((owned) js_str); + } + + /** +diff --git a/src/client/web-process/web-process-extension.vala b/src/client/web-process/web-process-extension.vala +index ee89139..1f478a6 100644 +--- a/src/client/web-process/web-process-extension.vala ++++ b/src/client/web-process/web-process-extension.vala +@@ -87,10 +87,9 @@ public class GearyWebExtension : Object { + bool should_load = false; + WebKit.Frame frame = page.get_main_frame(); + // Explicit cast fixes build on s390x/ppc64. Bug 783882 +- JS.GlobalContext context = (JS.GlobalContext) +- frame.get_javascript_global_context(); ++ unowned JS.GlobalContext context = frame.get_javascript_global_context(); + try { +- JS.Value ret = execute_script( ++ unowned JS.Value ret = execute_script( + context, "geary.allowRemoteImages", int.parse("__LINE__") + ); + should_load = ret.to_boolean(context); +@@ -106,8 +105,7 @@ public class GearyWebExtension : Object { + private void remote_image_load_blocked(WebKit.WebPage page) { + WebKit.Frame frame = page.get_main_frame(); + // Explicit cast fixes build on s390x/ppc64. Bug 783882 +- JS.GlobalContext context = (JS.GlobalContext) +- frame.get_javascript_global_context(); ++ unowned JS.GlobalContext context = frame.get_javascript_global_context(); + try { + execute_script( + context, "geary.remoteImageLoadBlocked();", int.parse("__LINE__") +@@ -123,8 +121,7 @@ public class GearyWebExtension : Object { + private void selection_changed(WebKit.WebPage page) { + WebKit.Frame frame = page.get_main_frame(); + // Explicit cast fixes build on s390x/ppc64. Bug 783882 +- JS.GlobalContext context = (JS.GlobalContext) +- frame.get_javascript_global_context(); ++ unowned JS.GlobalContext context = frame.get_javascript_global_context(); + try { + execute_script( + context, "geary.selectionChanged();", int.parse("__LINE__") +@@ -136,20 +133,18 @@ public class GearyWebExtension : Object { + + // Return type is nullable as a workaround for Bug 778046, it will + // never actually be null. +- private JS.Value? execute_script(JS.Context context, string script, int line) ++ private unowned JS.Value? execute_script(JS.Context context, string script, int line) + throws Geary.JS.Error { + JS.String js_script = new JS.String.create_with_utf8_cstring(script); + JS.String js_source = new JS.String.create_with_utf8_cstring("__FILE__"); + JS.Value? err = null; + try { +- JS.Value ret = context.evaluate_script( ++ unowned JS.Value ret = context.evaluate_script( + js_script, null, js_source, line, out err + ); + Geary.JS.check_exception(context, err); + return ret; + } finally { +- js_script.release(); +- js_source.release(); + } + } + +diff --git a/src/engine/util/util-js.vala b/src/engine/util/util-js.vala +index 4d22429..ea955e9 100644 +--- a/src/engine/util/util-js.vala ++++ b/src/engine/util/util-js.vala +@@ -10,6 +10,16 @@ + */ + namespace Geary.JS { + ++#if !VALA_0_42 ++ // Workaround broken version of this in the vala bindings. See Bug ++ // 788113. ++ [CCode (cname = "JSStringGetUTF8CString")] ++ private extern size_t js_string_get_utf8_cstring( ++ global::JS.String js, ++ [CCode (array_length_type = "gsize")] char[] buffer ++ ); ++#endif ++ + /** + * Errors produced by functions in {@link Geary.JS}. + */ +@@ -72,7 +82,7 @@ namespace Geary.JS { + global::JS.String js_str = value.to_string_copy(context, out err); + Geary.JS.check_exception(context, err); + +- return Geary.JS.to_string_released(js_str); ++ return Geary.JS.to_string_released((owned) js_str); + } + + /** +@@ -101,12 +111,15 @@ namespace Geary.JS { + /** + * Returns a JSC {@link JS.String} as a Vala {@link string}. + */ +- public inline string to_string_released(global::JS.String js) { +- int len = js.get_maximum_utf8_cstring_size(); +- string str = string.nfill(len, 0); +- js.get_utf8_cstring(str, len); +- js.release(); +- return str; ++ public inline string to_string_released(owned global::JS.String js) { ++ size_t len = js.get_maximum_utf8_cstring_size(); ++ uint8[] str = new uint8[len]; ++#if VALA_0_42 ++ js.get_utf8_cstring(str); ++#else ++ js_string_get_utf8_cstring(js, (char[]) str); ++#endif ++ return (string) str; + } + + /** +@@ -128,7 +141,6 @@ namespace Geary.JS { + try { + Geary.JS.check_exception(context, err); + } finally { +- js_name.release(); + } + return prop; + } +@@ -157,7 +169,7 @@ namespace Geary.JS { + + throw new Error.EXCEPTION( + "JS exception thrown [%s]: %s" +- .printf(err_type.to_string(), to_string_released(err_str)) ++ .printf(err_type.to_string(), to_string_released((owned) err_str)) + ); + } + } diff -Nru geary-0.12.2/debian/patches/bindings-Drop-custom-javascriptcore-4.0-and-webkit2gtk-4..patch geary-0.12.4/debian/patches/bindings-Drop-custom-javascriptcore-4.0-and-webkit2gtk-4..patch --- geary-0.12.2/debian/patches/bindings-Drop-custom-javascriptcore-4.0-and-webkit2gtk-4..patch 1970-01-01 00:00:00.000000000 +0000 +++ geary-0.12.4/debian/patches/bindings-Drop-custom-javascriptcore-4.0-and-webkit2gtk-4..patch 2018-09-15 15:03:58.000000000 +0000 @@ -0,0 +1,327 @@ +From: Rico Tzschichholz +Date: Thu, 22 Jun 2017 15:01:19 +0200 +Subject: bindings: Drop custom javascriptcore-4.0 and webkit2gtk-4.0 vapi + +--- + bindings/metadata/Soup-2.4.metadata | 3 - + bindings/metadata/WebKit2-4.0.metadata | 15 -- + .../metadata/WebKit2WebExtension-4.0-custom.vala | 5 - + bindings/metadata/WebKit2WebExtension-4.0.metadata | 9 -- + bindings/vapi/javascriptcore-4.0.vapi | 155 --------------------- + src/CMakeLists.txt | 39 +----- + test/CMakeLists.txt | 2 +- + 7 files changed, 4 insertions(+), 224 deletions(-) + delete mode 100644 bindings/metadata/Soup-2.4.metadata + delete mode 100644 bindings/metadata/WebKit2-4.0.metadata + delete mode 100644 bindings/metadata/WebKit2WebExtension-4.0-custom.vala + delete mode 100644 bindings/metadata/WebKit2WebExtension-4.0.metadata + delete mode 100644 bindings/vapi/javascriptcore-4.0.vapi + +diff --git a/bindings/metadata/Soup-2.4.metadata b/bindings/metadata/Soup-2.4.metadata +deleted file mode 100644 +index f3e72e8..0000000 +--- a/bindings/metadata/Soup-2.4.metadata ++++ /dev/null +@@ -1,3 +0,0 @@ +-AuthDomain.accepts skip +-AuthDomain.challenge skip +- +diff --git a/bindings/metadata/WebKit2-4.0.metadata b/bindings/metadata/WebKit2-4.0.metadata +deleted file mode 100644 +index 3e3044f..0000000 +--- a/bindings/metadata/WebKit2-4.0.metadata ++++ /dev/null +@@ -1,15 +0,0 @@ +- +-JavascriptResult +- .get_global_context nullable=false unowned=true +- .get_value nullable=false unowned=true +- +-//Forward upstream +-Download +- .failed#signal.error type="WebKit.DownloadError" +-PrintOperation +- .failed#signal.error type="WebKit.PrintError" +-WebResource +- .failed#signal.error type="GLib.Error" +-WebView +- .load_failed#signal.error type="GLib.Error" +- .show_option_menu#signal skip +diff --git a/bindings/metadata/WebKit2WebExtension-4.0-custom.vala b/bindings/metadata/WebKit2WebExtension-4.0-custom.vala +deleted file mode 100644 +index a994a77..0000000 +--- a/bindings/metadata/WebKit2WebExtension-4.0-custom.vala ++++ /dev/null +@@ -1,5 +0,0 @@ +-namespace WebKit { +- namespace DOM { +- public delegate void EventTargetFunc (WebKit.DOM.EventTarget target, WebKit.DOM.Event event); +- } +-} +diff --git a/bindings/metadata/WebKit2WebExtension-4.0.metadata b/bindings/metadata/WebKit2WebExtension-4.0.metadata +deleted file mode 100644 +index c496dba..0000000 +--- a/bindings/metadata/WebKit2WebExtension-4.0.metadata ++++ /dev/null +@@ -1,9 +0,0 @@ +-DOM* parent="WebKit.DOM" name="DOM(.+)" +- +-DOMEventTarget.add_event_listener skip +-_ContextMenu skip +-_ContextMenuItem skip +- +-Frame.get_javascript_* nullable=false unowned=true +- +-DOMEventTarget.add_event_listener_with_closure.handler type="owned WebKit.DOM.EventTargetFunc" +diff --git a/bindings/vapi/javascriptcore-4.0.vapi b/bindings/vapi/javascriptcore-4.0.vapi +deleted file mode 100644 +index d152ce2..0000000 +--- a/bindings/vapi/javascriptcore-4.0.vapi ++++ /dev/null +@@ -1,155 +0,0 @@ +-/* +- * Copyright 2017 Michael Gratton +- * +- * This software is licensed under the GNU Lesser General Public License +- * (version 2.1 or later). See the COPYING file in this distribution. +- */ +- +-[CCode (cprefix = "JS", +- gir_namespace = "JavaScriptCore", +- gir_version = "4.0", +- lower_case_cprefix = "JS_", +- cheader_filename = "JavaScriptCore/JavaScript.h")] +-namespace JS { +- +- [CCode (cname = "JSContextRef")] +- [SimpleType] +- public struct Context { +- +- [CCode (cname = "JSEvaluateScript")] +- public Value evaluate_script(String script, +- Object? thisObject, +- String? sourceURL, +- int startingLineNumber, +- out Value? exception); +- +- [CCode (cname = "JSCheckScriptSyntax")] +- public Value check_script_syntax(String script, +- String? sourceURL, +- int startingLineNumber, +- out Value? exception); +- +- } +- +- [CCode (cname = "JSGlobalContextRef")] +- [SimpleType] +- public struct GlobalContext : Context { +- +- [CCode (cname = "JSGlobalContextRetain")] +- public bool retain(); +- +- [CCode (cname = "JSGlobalContextRelease")] +- public bool release(); +- +- } +- +- [CCode (cname = "JSType", has_type_id = false)] +- public enum Type { +- +- [CCode (cname = "kJSTypeUndefined")] +- UNDEFINED, +- +- [CCode (cname = "kJSTypeNull")] +- NULL, +- +- [CCode (cname = "kJSTypeBoolean")] +- BOOLEAN, +- +- [CCode (cname = "kJSTypeNumber")] +- NUMBER, +- +- [CCode (cname = "kJSTypeString")] +- STRING, +- +- [CCode (cname = "kJSTypeObject")] +- OBJECT +- } +- +- [CCode (cname = "JSObjectRef")] +- [SimpleType] +- public struct Object { +- +- [CCode (cname = "JSObjectMakeFunction")] +- public Object.make_function(String? name, +- [CCode (array_length_pos=1.5)] +- String[]? parameterNames, +- String body, +- String? sourceURL, +- int startingLineNumber, +- out Value? exception); +- +- [CCode (cname = "JSObjectCallAsFunction", instance_pos = 1.1)] +- public Value call_as_function(Context ctx, +- Object? thisObject, +- [CCode (array_length_pos=2.5)] +- Value[]? arguments, +- out Value? exception); +- +- [CCode (cname = "JSObjectHasProperty", instance_pos = 1.1)] +- public bool has_property(Context ctx, String property_name); +- +- [CCode (cname = "JSObjectGetProperty", instance_pos = 1.1)] +- public Value get_property(Context ctx, +- String property_name, +- out Value? exception); +- +- } +- +- [CCode (cname = "JSValueRef")] +- [SimpleType] +- public struct Value { +- +- [CCode (cname = "JSValueGetType", instance_pos = 1.1)] +- public Type get_type(Context context); +- +- [CCode (cname = "JSValueIsBoolean", instance_pos = 1.1)] +- public bool is_boolean(Context ctx); +- +- [CCode (cname = "JSValueIsNumber", instance_pos = 1.1)] +- public bool is_number(Context ctx); +- +- [CCode (cname = "JSValueIsObject", instance_pos = 1.1)] +- public bool is_object(Context ctx); +- +- [CCode (cname = "JSValueIsString", instance_pos = 1.1)] +- public bool is_string(Context ctx); +- +- [CCode (cname = "JSValueToBoolean", instance_pos = 1.1)] +- public bool to_boolean(Context ctx); +- +- [CCode (cname = "JSValueToNumber", instance_pos = 1.1)] +- public double to_number(Context ctx, out Value exception); +- +- [CCode (cname = "JSValueToObject", instance_pos = 1.1)] +- public Object to_object(Context ctx, out Value exception); +- +- [CCode (cname = "JSValueToStringCopy", instance_pos = 1.1)] +- public String to_string_copy(Context ctx, out Value exception); +- +- } +- +- [CCode (cname = "JSStringRef")] +- [SimpleType] +- public struct String { +- +- [CCode (cname = "JSStringCreateWithUTF8CString")] +- public String.create_with_utf8_cstring(string str); +- +- [CCode (cname = "JSStringGetLength")] +- public int String.get_length(); +- +- [CCode (cname = "JSStringGetMaximumUTF8CStringSize")] +- public int String.get_maximum_utf8_cstring_size(); +- +- [CCode (cname = "JSStringGetUTF8CString")] +- public void String.get_utf8_cstring(string* buffer, int bufferSize); +- +- [CCode (cname = "JSStringRetain")] +- public void String.retain(); +- +- [CCode (cname = "JSStringRelease")] +- public void String.release(); +- +- } +- +-} +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index bce938d..6793129 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -525,7 +525,7 @@ set(ENGINE_PACKAGES + gio-2.0 + glib-2.0 + gmime-2.6 +- javascriptcore-4.0 ++ javascriptcoregtk-4.0 + libxml-2.0 + posix + sqlite3 +@@ -550,7 +550,7 @@ set(WEB_PROCESS_PACKAGES + geary-engine + gee-0.8 + gtk+-3.0 +- javascriptcore-4.0 ++ javascriptcoregtk-4.0 + libsoup-2.4 + webkit2gtk-web-extension-4.0 + ) +@@ -617,7 +617,6 @@ add_definitions(${CFLAGS}) + set(VALAC_OPTIONS + --vapidir=${CMAKE_BINARY_DIR}/src + --vapidir=${CMAKE_SOURCE_DIR}/bindings/vapi +- --metadatadir=${CMAKE_SOURCE_DIR}/bindings/metadata + --target-glib=${TARGET_GLIB} + --thread + --debug +@@ -649,38 +648,6 @@ set_property( + ) + target_link_libraries(geary-engine m ${DEPS_LIBRARIES} sqlite3-unicodesn) + +-# WebKit2GTK VAPI generation +-################################################# +-add_custom_target(webkit2gtk-vapi +- DEPENDS +- "${CMAKE_BINARY_DIR}/src/webkit2gtk-4.0.vapi" +- "${CMAKE_BINARY_DIR}/src/webkit2gtk-web-extension-4.0.vapi" +- "${CMAKE_SOURCE_DIR}/bindings/vapi/javascriptcore-4.0.vapi" +-) +-add_custom_command( +- OUTPUT +- ${CMAKE_BINARY_DIR}/src/webkit2gtk-4.0.vapi +- DEPENDS +- "${CMAKE_SOURCE_DIR}/bindings/metadata/WebKit2-4.0.metadata" +- "${CMAKE_SOURCE_DIR}/bindings/vapi/javascriptcore-4.0.vapi" +- WORKING_DIRECTORY +- "${CMAKE_SOURCE_DIR}/bindings/metadata" +- COMMAND +- vapigen --library=webkit2gtk-4.0 --pkg gtk+-3.0 --pkg libsoup-2.4 --pkg javascriptcore-4.0 --vapidir=${CMAKE_SOURCE_DIR}/bindings/vapi --metadatadir=${CMAKE_SOURCE_DIR}/bindings/metadata --directory=${CMAKE_BINARY_DIR}/src `${PKG_CONFIG_EXECUTABLE} --variable=girdir gobject-introspection-1.0`/WebKit2-4.0.gir +-) +-add_custom_command( +- OUTPUT +- "${CMAKE_BINARY_DIR}/src/webkit2gtk-web-extension-4.0.vapi" +- DEPENDS +- "${CMAKE_SOURCE_DIR}/bindings/metadata/WebKit2WebExtension-4.0.metadata" +- "${CMAKE_SOURCE_DIR}/bindings/metadata/WebKit2WebExtension-4.0-custom.vala" +- "${CMAKE_SOURCE_DIR}/bindings/vapi/javascriptcore-4.0.vapi" +- WORKING_DIRECTORY +- "${CMAKE_SOURCE_DIR}/bindings/metadata" +- COMMAND +- vapigen --library=webkit2gtk-web-extension-4.0 --pkg gtk+-3.0 --pkg libsoup-2.4 --pkg javascriptcore-4.0 --vapidir=${CMAKE_SOURCE_DIR}/bindings/vapi --metadatadir=${CMAKE_SOURCE_DIR}/bindings/metadata --directory=${CMAKE_BINARY_DIR}/src `${PKG_CONFIG_EXECUTABLE} --variable=girdir gobject-introspection-1.0`/WebKit2WebExtension-4.0.gir WebKit2WebExtension-4.0-custom.vala +-) +- + # Client library (static lib used for building client and unit tests) + ################################################# + +@@ -697,7 +664,7 @@ OPTIONS + ) + + add_library(geary-client STATIC ${CLIENT_VALA_C}) +-add_dependencies(geary-client resource_copy webkit2gtk-vapi) ++add_dependencies(geary-client resource_copy) + target_link_libraries(geary-client m ${DEPS_LIBRARIES} geary-engine) + + # Main client application binary +diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt +index f2d3866..6524cfb 100644 +--- a/test/CMakeLists.txt ++++ b/test/CMakeLists.txt +@@ -58,7 +58,7 @@ set(TEST_PACKAGES + glib-2.0 + gmime-2.6 + gtk+-3.0 +- javascriptcore-4.0 ++ javascriptcoregtk-4.0 + libsoup-2.4 + webkit2gtk-4.0 + ) diff -Nru geary-0.12.2/debian/patches/Clean-up-JS-util-API-courtesy-the-new-bindings.patch geary-0.12.4/debian/patches/Clean-up-JS-util-API-courtesy-the-new-bindings.patch --- geary-0.12.2/debian/patches/Clean-up-JS-util-API-courtesy-the-new-bindings.patch 1970-01-01 00:00:00.000000000 +0000 +++ geary-0.12.4/debian/patches/Clean-up-JS-util-API-courtesy-the-new-bindings.patch 2018-09-15 15:03:58.000000000 +0000 @@ -0,0 +1,66 @@ +From: Michael James Gratton +Date: Sun, 20 May 2018 19:07:56 +1000 +Subject: Clean up JS util API courtesy the new bindings. + +--- + src/client/util/util-webkit.vala | 2 +- + src/engine/util/util-js.vala | 12 +++++------- + 2 files changed, 6 insertions(+), 8 deletions(-) + +diff --git a/src/client/util/util-webkit.vala b/src/client/util/util-webkit.vala +index cba9eaf..45a27c4 100644 +--- a/src/client/util/util-webkit.vala ++++ b/src/client/util/util-webkit.vala +@@ -64,7 +64,7 @@ namespace WebKitUtil { + JS.Value? err = null; + JS.String js_str = js_str_value.to_string_copy(context, out err); + Geary.JS.check_exception(context, err); +- return Geary.JS.to_string_released((owned) js_str); ++ return Geary.JS.to_native_string(js_str); + } + + /** +diff --git a/src/engine/util/util-js.vala b/src/engine/util/util-js.vala +index ea955e9..a98d798 100644 +--- a/src/engine/util/util-js.vala ++++ b/src/engine/util/util-js.vala +@@ -82,7 +82,7 @@ namespace Geary.JS { + global::JS.String js_str = value.to_string_copy(context, out err); + Geary.JS.check_exception(context, err); + +- return Geary.JS.to_string_released((owned) js_str); ++ return to_native_string(js_str); + } + + /** +@@ -111,7 +111,7 @@ namespace Geary.JS { + /** + * Returns a JSC {@link JS.String} as a Vala {@link string}. + */ +- public inline string to_string_released(owned global::JS.String js) { ++ public inline string to_native_string(global::JS.String js) { + size_t len = js.get_maximum_utf8_cstring_size(); + uint8[] str = new uint8[len]; + #if VALA_0_42 +@@ -138,10 +138,8 @@ namespace Geary.JS { + global::JS.String js_name = new global::JS.String.create_with_utf8_cstring(name); + global::JS.Value? err = null; + global::JS.Value prop = object.get_property(context, js_name, out err); +- try { +- Geary.JS.check_exception(context, err); +- } finally { +- } ++ Geary.JS.check_exception(context, err); ++ + return prop; + } + +@@ -169,7 +167,7 @@ namespace Geary.JS { + + throw new Error.EXCEPTION( + "JS exception thrown [%s]: %s" +- .printf(err_type.to_string(), to_string_released((owned) err_str)) ++ .printf(err_type.to_string(), to_native_string(err_str)) + ); + } + } diff -Nru geary-0.12.2/debian/patches/series geary-0.12.4/debian/patches/series --- geary-0.12.2/debian/patches/series 2018-05-13 17:17:50.000000000 +0000 +++ geary-0.12.4/debian/patches/series 2018-09-15 15:03:58.000000000 +0000 @@ -0,0 +1,3 @@ +bindings-Drop-custom-javascriptcore-4.0-and-webkit2gtk-4..patch +Adjust-to-upstream-javascriptcore-4.0-bindings.patch +Clean-up-JS-util-API-courtesy-the-new-bindings.patch diff -Nru geary-0.12.2/desktop/org.gnome.Geary.appdata.xml.in geary-0.12.4/desktop/org.gnome.Geary.appdata.xml.in --- geary-0.12.2/desktop/org.gnome.Geary.appdata.xml.in 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/desktop/org.gnome.Geary.appdata.xml.in 2018-08-29 13:57:20.000000000 +0000 @@ -77,6 +77,34 @@ geary + + +

Bug fixes included in this release:

+
    +
  • Fix handling folder names with IMAP reserved characters, such as backslashes. Issue #40
  • +
  • Fix dialog windows not focused after being first shown. Issue #43
  • +
  • Actually include the fix for "Move to folder" selection bug. Issue #24
  • +
  • Fix build under vala >= 0.41. Issue #86
  • +
  • Fixes for miscellaneous crashers
  • +
+
+
+ + + +

Bug fixes included in this release:

+
    +
  • Not syncing mail using Turkish locale. Bug 795906
  • +
  • Fix crash saving an attachment with unknown content type
  • +
  • Fix crash in secret_collection_get_locked. Bug 795328
  • +
  • "Move to folder" selection bug. Issue #24
  • +
  • Subfolders with special folders not displayed in + list. Issue #11
  • +
  • Add OARS metadata for Flathub
  • +
+
+
+

Bug fixes included in this release:

@@ -165,4 +193,33 @@
+ + none + none + none + none + none + none + none + none + none + none + none + none + none + none + none + none + none + none + none + none + intense + none + none + none + intense + none + none + diff -Nru geary-0.12.2/.gitlab-ci.yml geary-0.12.4/.gitlab-ci.yml --- geary-0.12.2/.gitlab-ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ geary-0.12.4/.gitlab-ci.yml 2018-08-29 13:57:20.000000000 +0000 @@ -0,0 +1,110 @@ +# +# Geary CI config. +# + +stages: + - build + +variables: + BUILD_DIR: build + CONFIG_CMD: ./configure + BUILD_CMD: make + TEST_CMD: xvfb-run make test + INSTALL_CMD: make install + FEDORA_BUILD_DEPS: gcc make + FEDORA_DEPS: vala gobject-introspection-devel intltool cmake + desktop-file-utils gnome-doc-utils libcanberra-devel + libgee-devel glib2-devel gmime-devel gtk3-devel + libnotify-devel sqlite-devel webkitgtk4-devel + libsecret-devel libxml2-devel vala-tools gcr-devel + enchant-devel + FEDORA_TEST_DEPS: Xvfb + DEBIAN_DEPS: valac libgirepository1.0-dev intltool cmake + desktop-file-utils gnome-doc-utils libcanberra-dev + libgee-0.8-dev libglib2.0-dev libgmime-2.6-dev + libgtk-3-dev libsecret-1-dev libxml2-dev libnotify-dev + libsqlite3-dev libwebkit2gtk-4.0-dev libgcr-3-dev + libenchant-dev + DEBIAN_TEST_DEPS: xauth xvfb + UBUNTU_DEPS: $DEBIAN_DEPS libunity-dev libmessaging-menu-dev + UBUNTU_TEST_DEPS: xauth xvfb + +# +# Stages +# + +fedora: + stage: build + image: fedora:latest + before_script: + - dnf update -y --nogpgcheck + - dnf install -y --nogpgcheck $FEDORA_BUILD_DEPS $FEDORA_DEPS $FEDORA_TEST_DEPS + script: + - $CONFIG_CMD + - $BUILD_CMD + - $TEST_CMD + - $INSTALL_CMD + +debian: + stage: build + image: debian:stable + before_script: + - apt-get update + - apt-get install -q -y --no-install-recommends $DEBIAN_DEPS $DEBIAN_TEST_DEPS + script: + - $CONFIG_CMD + - $BUILD_CMD + - $TEST_CMD + - $INSTALL_CMD + +ubuntu: + stage: build + image: ubuntu:xenial + before_script: + - apt-get update + - apt-get install -q -y --no-install-recommends $UBUNTU_DEPS $UBUNTU_TEST_DEPS + script: + - $CONFIG_CMD + - $BUILD_CMD + - $TEST_CMD + - $INSTALL_CMD + +deb-package: + stage: build + image: ubuntu:xenial + before_script: + - apt-get update + - apt-get install -q -y --no-install-recommends packaging-dev $UBUNTU_DEPS + script: + - dpkg-buildpackage -b -us -uc + +flatpak-package: + image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:3.28 + stage: build + + variables: + GIT_SUBMODULE_STRATEGY: normal + FLATPAK_ARTIFACT: geary-git.flatpak + + script: + - flatpak-builder flatpak-build org.gnome.Geary.json + - flatpak build-export flatpak-repo flatpak-build --update-appstream + - flatpak build-bundle flatpak-repo $FLATPAK_ARTIFACT + --runtime-repo=https://sdk.gnome.org/gnome-nightly.flatpakrepo + org.gnome.Geary + + artifacts: + paths: + - $FLATPAK_ARTIFACT + expire_in: 2 days + + cache: + # JOB_NAME - Each job will have it's own cache + # COMMIT_REF_SLUG = Lowercase name of the branch + # ^ Keep diffrerent caches for each branch + key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG" + paths: + # Cache .flatpak-builder + - .flatpak-builder/cache/ + - .flatpak-builder/downloads/ + - .flatpak-builder/git/ diff -Nru geary-0.12.2/NEWS geary-0.12.4/NEWS --- geary-0.12.2/NEWS 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/NEWS 2018-08-29 13:57:20.000000000 +0000 @@ -1,3 +1,31 @@ +Version 0.12.4 +~~~~~~~~~~~~~~ +Released: 2018-08-29 + +Bug fixes included in this release: + * Fix handling folder names with IMAP reserved characters, such as + backslashes. Issue #40 + * Fix dialog windows not focused after being first shown. Issue #43 + * Actually include the fix for "Move to folder" selection bug. Issue #24 + * Fix build under vala >= 0.41. Issue #86 + * Fixes for miscellaneous crashers + +Version 0.12.3 +~~~~~~~~~~~~~~ +Released: 2018-07-14 + +Bug fixes included in this release: + * Not syncing mail using Turkish locale. Bug 795906 + * Fix crash saving an attachment with unknown content type + * Fix crash in secret_collection_get_locked. Bug 795328 + * "Move to folder" selection bug. Issue #24 + * Subfolders with special folders not displayed in list. Issue #11 + * Add OARS metadata for Flathub + +Thanks to all who contributed code fixes and enhancements to this +release: + * Nick Richards + Version 0.12.2 ~~~~~~~~~~~~~~ Released: 2018-04-24 diff -Nru geary-0.12.2/org.gnome.Geary.json geary-0.12.4/org.gnome.Geary.json --- geary-0.12.2/org.gnome.Geary.json 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/org.gnome.Geary.json 2018-08-29 13:57:20.000000000 +0000 @@ -1,6 +1,7 @@ /* flatpak-builder config for Geary. */ { "app-id": "org.gnome.Geary", + "branch": "geary-0.12", "runtime": "org.gnome.Platform", "runtime-version": "3.28", "sdk": "org.gnome.Sdk", @@ -78,7 +79,7 @@ "sources": [ { "type": "git", - "url": "https://git.gnome.org/browse/libgee", + "url": "https://gitlab.gnome.org/GNOME/libgee.git", "tag": "0.20.0" } ] @@ -88,7 +89,7 @@ "sources": [ { "type": "git", - "url": "https://git.gnome.org/browse/gmime", + "url": "https://github.com/jstedfast/gmime.git", "branch": "gmime-2-6" } ] @@ -98,7 +99,7 @@ "sources": [ { "type": "git", - "url": "https://git.gnome.org/browse/geary", + "url": "https://gitlab.gnome.org/GNOME/geary.git", "branch": "geary-0.12" } ] diff -Nru geary-0.12.2/po/POTFILES.in geary-0.12.4/po/POTFILES.in --- geary-0.12.2/po/POTFILES.in 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/po/POTFILES.in 2018-08-29 13:57:20.000000000 +0000 @@ -269,7 +269,6 @@ src/engine/imap/message/imap-flag.vala src/engine/imap/message/imap-flags.vala src/engine/imap/message/imap-internal-date.vala -src/engine/imap/message/imap-mailbox-parameter.vala src/engine/imap/message/imap-mailbox-specifier.vala src/engine/imap/message/imap-message-data.vala src/engine/imap/message/imap-message-flag.vala diff -Nru geary-0.12.2/src/client/application/geary-application.vala geary-0.12.4/src/client/application/geary-application.vala --- geary-0.12.2/src/client/application/geary-application.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/client/application/geary-application.vala 2018-08-29 13:57:20.000000000 +0000 @@ -234,8 +234,11 @@ // Use present_with_time and a synthesised time so the present // actually works, as a work around for Bug 766284 // . + // Subtract 10ms from the current time to avoid the main + // window stealing the focus when presented just before + // showing a dialog (issue #43). this.controller.main_window.present_with_time( - (uint32) (get_monotonic_time() / 1000) + (uint32) (get_monotonic_time() / 1000) - 10 ); return true; diff -Nru geary-0.12.2/src/client/application/geary-controller.vala geary-0.12.4/src/client/application/geary-controller.vala --- geary-0.12.2/src/client/application/geary-controller.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/client/application/geary-controller.vala 2018-08-29 13:57:20.000000000 +0000 @@ -1606,12 +1606,23 @@ ); } - private void on_special_folder_type_changed(Geary.Folder folder, Geary.SpecialFolderType old_type, - Geary.SpecialFolderType new_type) { + private void on_special_folder_type_changed(Geary.Folder folder, + Geary.SpecialFolderType old_type, + Geary.SpecialFolderType new_type) { main_window.folder_list.remove_folder(folder); main_window.folder_list.add_folder(folder); + // Since removing the folder will also remove its children, we + // need to check for any and re-add them. See isssue #11. + try { + foreach (Geary.Folder child in + folder.account.list_matching_folders(folder.path)) { + main_window.folder_list.add_folder(child); + } + } catch (Error err) { + // Oh well + } } - + private void on_engine_opened() { // Locate the first account so we can select its inbox when available. try { diff -Nru geary-0.12.2/src/client/application/main.vala geary-0.12.4/src/client/application/main.vala --- geary-0.12.2/src/client/application/main.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/client/application/main.vala 2018-08-29 13:57:20.000000000 +0000 @@ -17,7 +17,7 @@ // // Packages can disable this fix with the --disable-poodle-ssl3 configure option. #if !DISABLE_POODLE - Environment.set_variable("G_TLS_GNUTLS_PRIORITY", "NORMAL:%COMPAT:%LATEST_RECORD_VERSION:!VERS-SSL3.0", false); + Environment.set_variable("G_TLS_GNUTLS_PRIORITY", "NORMAL:%COMPAT:!VERS-SSL3.0", false); #endif // Disable WebKit2 accelerated compositing here while we can't diff -Nru geary-0.12.2/src/client/application/secret-mediator.vala geary-0.12.4/src/client/application/secret-mediator.vala --- geary-0.12.2/src/client/application/secret-mediator.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/client/application/secret-mediator.vala 2018-08-29 13:57:20.000000000 +0000 @@ -157,13 +157,19 @@ Secret.Service service = yield Secret.Service.get( Secret.ServiceFlags.OPEN_SESSION, cancellable ); - Secret.Collection collection = yield Secret.Collection.for_alias( + Secret.Collection? collection = yield Secret.Collection.for_alias( service, Secret.COLLECTION_DEFAULT, Secret.CollectionFlags.NONE, cancellable ); - if (collection.get_locked()) { + + // For custom desktop setups, it is possible that the current + // session has a service responding on DBus but no password + // keyring. There's no much we can do in this case except just + // check for the collection being null so we don't crash. See + // Bug 795328. + if (collection != null && collection.get_locked()) { List to_lock = new List(); to_lock.append(collection); List unlocked; diff -Nru geary-0.12.2/src/client/components/folder-popover.vala geary-0.12.4/src/client/components/folder-popover.vala --- geary-0.12.2/src/client/components/folder-popover.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/client/components/folder-popover.vala 2018-08-29 13:57:20.000000000 +0000 @@ -107,6 +107,9 @@ [GtkCallback] private void on_search_entry_search_changed() { invalidate_filter(); + if (this.search_entry.get_text() != "") { + this.list_box.unselect_all(); + } } private void invalidate_filter() { diff -Nru geary-0.12.2/src/client/composer/composer-widget.vala geary-0.12.4/src/client/composer/composer-widget.vala --- geary-0.12.2/src/client/composer/composer-widget.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/client/composer/composer-widget.vala 2018-08-29 13:57:20.000000000 +0000 @@ -1150,9 +1150,10 @@ private void on_detach() { if (this.state == ComposerState.DETACHED) return; - Gtk.Widget? focus = this.container.top_window.get_focus(); + + Gtk.Widget? focused_widget = this.container.top_window.get_focus(); this.container.remove_composer(); - ComposerWindow window = new ComposerWindow(this); + ComposerWindow new_window = new ComposerWindow(this); // Workaround a GTK+ crasher, Bug 771812. When the composer is // re-parented, its menu_button's popover keeps a reference to @@ -1168,11 +1169,19 @@ this.state = ComposerWidget.ComposerState.DETACHED; this.header.detached(); update_composer_view(); - if (focus != null && focus.parent.visible) { - ComposerWindow focus_win = focus.get_toplevel() as ComposerWindow; - if (focus_win != null && focus_win == window) - focus.grab_focus(); - } else { + + // If the previously focused widget is in the new composer + // window then focus that, else focus something useful. + bool refocus = true; + if (focused_widget != null) { + ComposerWindow? focused_window = + focused_widget.get_toplevel() as ComposerWindow; + if (new_window == focused_window) { + focused_widget.grab_focus(); + refocus = false; + } + } + if (refocus) { set_focus(); } } diff -Nru geary-0.12.2/src/client/conversation-viewer/conversation-web-view.vala geary-0.12.4/src/client/conversation-viewer/conversation-web-view.vala --- geary-0.12.2/src/client/conversation-viewer/conversation-web-view.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/client/conversation-viewer/conversation-web-view.vala 2018-08-29 13:57:20.000000000 +0000 @@ -15,7 +15,7 @@ // Key codes we don't forward on to the super class on key press // since we want to override them elsewhere, especially // ConversationListBox. - private const int[] BLACKLISTED_KEY_CODES = { + private const uint[] BLACKLISTED_KEY_CODES = { Gdk.Key.space, Gdk.Key.KP_Space, Gdk.Key.Up, diff -Nru geary-0.12.2/src/client/dialogs/attachment-dialog.vala geary-0.12.4/src/client/dialogs/attachment-dialog.vala --- geary-0.12.2/src/client/dialogs/attachment-dialog.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/client/dialogs/attachment-dialog.vala 2018-08-29 13:57:20.000000000 +0000 @@ -60,7 +60,12 @@ public int run() { int response = this.chooser.run(); if (response == Gtk.ResponseType.ACCEPT) { - this.config.attachments_dir = this.chooser.get_current_folder(); + // Current folder can be null, e.g. if selecting an + // attachment from Recent Files + string? current_folder = this.chooser.get_current_folder(); + if (!Geary.String.is_empty(current_folder)) { + this.config.attachments_dir = current_folder; + } } return response; } diff -Nru geary-0.12.2/src/CMakeLists.txt geary-0.12.4/src/CMakeLists.txt --- geary-0.12.2/src/CMakeLists.txt 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/CMakeLists.txt 2018-08-29 13:57:20.000000000 +0000 @@ -124,7 +124,6 @@ engine/imap/message/imap-flags.vala engine/imap/message/imap-internal-date.vala engine/imap/message/imap-mailbox-specifier.vala -engine/imap/message/imap-mailbox-parameter.vala engine/imap/message/imap-message-data.vala engine/imap/message/imap-message-flag.vala engine/imap/message/imap-message-flags.vala diff -Nru geary-0.12.2/src/engine/api/geary-account-information.vala geary-0.12.4/src/engine/api/geary-account-information.vala --- geary-0.12.2/src/engine/api/geary-account-information.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/engine/api/geary-account-information.vala 2018-08-29 13:57:20.000000000 +0000 @@ -138,7 +138,6 @@ // being saved. get { return (allow_save_sent_mail() ? _save_sent_mail : true); } set { _save_sent_mail = value; } - default = true; } // Order for display purposes. diff -Nru geary-0.12.2/src/engine/api/geary-attachment.vala geary-0.12.4/src/engine/api/geary-attachment.vala --- geary-0.12.2/src/engine/api/geary-attachment.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/engine/api/geary-attachment.vala 2018-08-29 13:57:20.000000000 +0000 @@ -155,7 +155,7 @@ } } string? ext = mime_type.get_file_name_extension(); - if (!file_name.has_suffix(ext)) { + if (ext != null && !file_name.has_suffix(ext)) { file_name = file_name + (ext ?? ""); } } diff -Nru geary-0.12.2/src/engine/imap/message/imap-data-format.vala geary-0.12.4/src/engine/imap/message/imap-data-format.vala --- geary-0.12.2/src/engine/imap/message/imap-data-format.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/engine/imap/message/imap-data-format.vala 2018-08-29 13:57:20.000000000 +0000 @@ -7,7 +7,10 @@ namespace Geary.Imap.DataFormat { private const char[] ATOM_SPECIALS = { - '(', ')', '{', ' ', '%', '*', '"' + '(', ')', '{', ' ', // CTL chars are handled by is_special_char + '%', '*', // list-wildcards + '"', '\\', // quoted-specials + ']' // resp-specials }; private const char[] TAG_SPECIALS = { @@ -21,11 +24,14 @@ } private bool is_special_char(char ch, char[] ar, string? exceptions) { - if (ch > 0x7F || ch.iscntrl()) + // Check for CTL chars + if (ch <= 0x1F || ch >= 0x7F) { return true; + } - if (ch in ar) - return (exceptions != null) ? exceptions.index_of_char(ch) < 0 : true; + if (ch in ar) { + return (exceptions != null) ? Ascii.index_of(exceptions, ch) < 0 : true; + } return false; } diff -Nru geary-0.12.2/src/engine/imap/message/imap-fetch-body-data-specifier.vala geary-0.12.4/src/engine/imap/message/imap-fetch-body-data-specifier.vala --- geary-0.12.2/src/engine/imap/message/imap-fetch-body-data-specifier.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/engine/imap/message/imap-fetch-body-data-specifier.vala 2018-08-29 13:57:20.000000000 +0000 @@ -73,15 +73,15 @@ assert_not_reached(); } } - + public static SectionPart deserialize(string value) throws ImapError { if (String.is_empty(value)) return NONE; - - switch (value.down()) { + + switch (Ascii.strdown(value)) { case "header": return HEADER; - + case "header.fields": return HEADER_FIELDS; @@ -178,25 +178,23 @@ this.subset_start = subset_start; this.subset_count = subset_count; this.is_peek = is_peek; - + if (field_names != null && field_names.length > 0) { - this.field_names = new Gee.TreeSet((s1, s2) => { - return GLib.strcmp(s1, s2); - }); + this.field_names = new Gee.TreeSet(Ascii.strcmp); foreach (string field_name in field_names) { - string converted = field_name.strip().down(); - + string converted = Ascii.strdown(field_name.strip()); + if (!String.is_empty(converted)) this.field_names.add(converted); } } else { this.field_names = null; } - + // see equal_to() for why the response version is used hashable = serialize_response(); } - + /** * Returns the {@link FetchBodyDataSpecifier} in a string ready for a {@link Command}. * diff -Nru geary-0.12.2/src/engine/imap/message/imap-flag.vala geary-0.12.4/src/engine/imap/message/imap-flag.vala --- geary-0.12.2/src/engine/imap/message/imap-flag.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/engine/imap/message/imap-flag.vala 2018-08-29 13:57:20.000000000 +0000 @@ -15,11 +15,16 @@ public abstract class Geary.Imap.Flag : BaseObject, Gee.Hashable { public string value { get; private set; } - - public Flag(string value) { - this.value = value; + + /** + * Constructs a new flag. + * + * The given keyword must be an IMAP atom. + */ + public Flag(string name) { + this.value = name; } - + public bool is_system() { return value[0] == '\\'; } @@ -31,14 +36,14 @@ public bool equal_to(Geary.Imap.Flag flag) { return (flag == this) ? true : flag.equals_string(value); } - + /** * Returns the {@link Flag} as an appropriate {@link Parameter}. */ public StringParameter to_parameter() throws ImapError { - return StringParameter.get_best_for(value); + return new UnquotedStringParameter(value); } - + public uint hash() { return Ascii.stri_hash(value); } diff -Nru geary-0.12.2/src/engine/imap/message/imap-internal-date.vala geary-0.12.4/src/engine/imap/message/imap-internal-date.vala --- geary-0.12.2/src/engine/imap/message/imap-internal-date.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/engine/imap/message/imap-internal-date.vala 2018-08-29 13:57:20.000000000 +0000 @@ -64,18 +64,18 @@ || year < 1970) { throw new ImapError.PARSE_ERROR("Invalid INTERNALDATE \"%s\": bad numerical range", internaldate); } - + // check month (this catches localization problems) int month = -1; - string mon_down = ((string) mon).down(); + string mon_down = Ascii.strdown(((string) mon)); for (int ctr = 0; ctr < EN_US_MON_DOWN.length; ctr++) { if (mon_down == EN_US_MON_DOWN[ctr]) { month = ctr; - + break; } } - + if (month < 0) throw new ImapError.PARSE_ERROR("Invalid INTERNALDATE \"%s\": bad month", internaldate); diff -Nru geary-0.12.2/src/engine/imap/message/imap-mailbox-parameter.vala geary-0.12.4/src/engine/imap/message/imap-mailbox-parameter.vala --- geary-0.12.2/src/engine/imap/message/imap-mailbox-parameter.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/engine/imap/message/imap-mailbox-parameter.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -/* Copyright 2016 Software Freedom Conservancy Inc. - * - * This software is licensed under the GNU Lesser General Public License - * (version 2.1 or later). See the COPYING file in this distribution. - */ - -/** - * A {@link StringParameter} that holds a mailbox reference (can be wildcarded). - * - * Used to juggle between our internal UTF-8 representation of mailboxes and IMAP's - * odd "modified UTF-7" representation. The value is stored in IMAP's encoded - * format since that's how it comes across the wire. - */ - -public class Geary.Imap.MailboxParameter : StringParameter { - public MailboxParameter(string mailbox) { - base (utf8_to_imap_utf7(mailbox)); - } - - public MailboxParameter.from_string_parameter(StringParameter string_parameter) { - base (string_parameter.ascii); - } - - private static string utf8_to_imap_utf7(string utf8) { - try { - return Geary.ImapUtf7.utf8_to_imap_utf7(utf8); - } catch (ConvertError e) { - debug("Error encoding mailbox name '%s': %s", utf8, e.message); - return utf8; - } - } - - private static string imap_utf7_to_utf8(string imap_utf7) { - try { - return Geary.ImapUtf7.imap_utf7_to_utf8(imap_utf7); - } catch (ConvertError e) { - debug("Invalid mailbox name '%s': %s", imap_utf7, e.message); - return imap_utf7; - } - } - - public string decode() { - return imap_utf7_to_utf8(ascii); - } - - /** - * {@inheritDoc} - */ - public override void serialize(Serializer ser, Tag tag) throws Error { - serialize_string(ser); - } - - /** - * {@inheritDoc} - */ - public override string to_string() { - return ascii; - } -} - diff -Nru geary-0.12.2/src/engine/imap/message/imap-mailbox-specifier.vala geary-0.12.4/src/engine/imap/message/imap-mailbox-specifier.vala --- geary-0.12.2/src/engine/imap/message/imap-mailbox-specifier.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/engine/imap/message/imap-mailbox-specifier.vala 2018-08-29 13:57:20.000000000 +0000 @@ -43,15 +43,37 @@ * See [[http://tools.ietf.org/html/rfc3501#section-5.1]] */ public bool is_inbox { get; private set; } - + + /** + * Constructs a new specifier from a UTF-8 name. + */ public MailboxSpecifier(string name) { init(name); } - - public MailboxSpecifier.from_parameter(MailboxParameter param) { - init(param.decode()); + + /** + * Constructs a new specifier from a IMAP modified-UTF-7 string. + * + * If a modified-UTF-7 decoding error occurs, the parameter will + * assumed to be UTF-8, repaired, and used instead. + */ + public MailboxSpecifier.from_parameter(StringParameter param) { + string? name = null; + try { + name = Geary.ImapUtf7.imap_utf7_to_utf8(param.ascii); + } catch (ConvertError err) { + // Could no decode the name as IMAP modified UTF7, so per + // https://imapwiki.org/ClientImplementation/MailboxList + // assume UTF8. + debug( + "Error decoding mailbox name, assuming UTF-8: %s", err.message + ); + name = param.ascii; + } + + init(name); } - + /** * Returns true if the {@link Geary.FolderPath} points to the IMAP Inbox. */ @@ -72,7 +94,7 @@ public static bool is_inbox_name(string name) { return Ascii.stri_equal(name, CANONICAL_INBOX_NAME); } - + /** * Returns true if the string is the ''canonical'' name of the IMAP Inbox. * @@ -85,9 +107,9 @@ * @see is_inbox_name */ public static bool is_canonical_inbox_name(string name) { - return (name == CANONICAL_INBOX_NAME); + return Ascii.str_equal(name, CANONICAL_INBOX_NAME); } - + /** * Converts a generic {@link FolderPath} into an IMAP mailbox specifier. */ @@ -167,35 +189,42 @@ return !String.is_empty(basename) ? basename : name; } - + public Parameter to_parameter() { - return new MailboxParameter(name); + string encoded= Geary.ImapUtf7.utf8_to_imap_utf7(this.name); + Parameter? param = null; + try { + param = StringParameter.get_best_for(encoded); + } catch (ImapError err) { + param = new LiteralParameter(new Geary.Memory.StringBuffer(encoded)); + } + return param; } - + public uint hash() { return is_inbox ? Ascii.stri_hash(name) : Ascii.str_hash(name); } - + public bool equal_to(MailboxSpecifier other) { if (this == other) return true; - + if (is_inbox) return Ascii.stri_equal(name, other.name); - - return (name == other.name); + + return Ascii.str_equal(name, other.name); } - + public int compare_to(MailboxSpecifier other) { if (this == other) return 0; - + if (is_inbox && other.is_inbox) return 0; - - return GLib.strcmp(name, other.name); + + return Ascii.strcmp(name, other.name); } - + public string to_string() { return name; } diff -Nru geary-0.12.2/src/engine/imap/parameter/imap-string-parameter.vala geary-0.12.4/src/engine/imap/parameter/imap-string-parameter.vala --- geary-0.12.2/src/engine/imap/parameter/imap-string-parameter.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/engine/imap/parameter/imap-string-parameter.vala 2018-08-29 13:57:20.000000000 +0000 @@ -134,35 +134,35 @@ public bool is_empty() { return String.is_empty(ascii); } - + /** * Case-sensitive comparison. */ public bool equals_cs(string value) { - return (ascii == value); + return Ascii.str_equal(ascii, value); } - + /** * Case-insensitive comparison. */ public bool equals_ci(string value) { return Ascii.stri_equal(ascii, value); } - + /** * Returns the string lowercased. */ public string as_lower() { - return ascii.down(); + return Ascii.strdown(ascii); } - + /** * Returns the string uppercased. */ public string as_upper() { - return ascii.up(); + return Ascii.strup(ascii); } - + /** * Converts the {@link ascii} to a signed 32-bit integer, clamped between clamp_min and * clamp_max. diff -Nru geary-0.12.2/src/engine/imap/response/imap-mailbox-information.vala geary-0.12.4/src/engine/imap/response/imap-mailbox-information.vala --- geary-0.12.2/src/engine/imap/response/imap-mailbox-information.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/engine/imap/response/imap-mailbox-information.vala 2018-08-29 13:57:20.000000000 +0000 @@ -71,19 +71,21 @@ // decode everything MailboxAttributes attributes = new MailboxAttributes(attrlist); StringParameter? delim = server_data.get_as_nullable_string(3); - MailboxParameter mailbox = new MailboxParameter.from_string_parameter( - server_data.get_as_string(4)); - - // Set \Inbox to standard path - if (canonical_inbox && Geary.Imap.MailboxAttribute.SPECIAL_FOLDER_INBOX in attributes) { - return new MailboxInformation(MailboxSpecifier.inbox, - (delim != null) ? delim.nullable_ascii : null, attributes); - } else { - return new MailboxInformation(new MailboxSpecifier.from_parameter(mailbox), - (delim != null) ? delim.nullable_ascii : null, attributes); - } + StringParameter mailbox = server_data.get_as_string(4); + + // If special-use flag \Inbox is set just use the canonical + // Inbox name, otherwise decode it + MailboxSpecifier? specifier = + (canonical_inbox && + Geary.Imap.MailboxAttribute.SPECIAL_FOLDER_INBOX in attributes) + ? MailboxSpecifier.inbox + : new MailboxSpecifier.from_parameter(mailbox); + + return new MailboxInformation( + specifier, (delim != null) ? delim.nullable_ascii : null, attributes + ); } - + /** * The {@link Geary.FolderPath} for the {@link mailbox}. * diff -Nru geary-0.12.2/src/engine/imap/response/imap-response-code-type.vala geary-0.12.4/src/engine/imap/response/imap-response-code-type.vala --- geary-0.12.2/src/engine/imap/response/imap-response-code-type.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/engine/imap/response/imap-response-code-type.vala 2018-08-29 13:57:20.000000000 +0000 @@ -64,17 +64,17 @@ public ResponseCodeType.from_parameter(StringParameter stringp) throws ImapError { init(stringp.ascii); } - + private void init(string ascii) throws ImapError { // note that is_quoting_required() also catches empty strings (as they require quoting) if (DataFormat.is_quoting_required(ascii) != DataFormat.Quoting.OPTIONAL) throw new ImapError.INVALID("\"%s\" cannot be represented as a ResponseCodeType", ascii); - + // store lowercased so it's easily compared with const strings above original = ascii; - value = ascii.down(); + value = Ascii.strdown(ascii); } - + public bool is_value(string str) { return Ascii.stri_equal(value, str); } diff -Nru geary-0.12.2/src/engine/imap/response/imap-status-data.vala geary-0.12.4/src/engine/imap/response/imap-status-data.vala --- geary-0.12.2/src/engine/imap/response/imap-status-data.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/engine/imap/response/imap-status-data.vala 2018-08-29 13:57:20.000000000 +0000 @@ -74,10 +74,9 @@ throw new ImapError.PARSE_ERROR("Bad STATUS command name in response \"%s\"", server_data.to_string()); } - - MailboxParameter mailbox_param = new MailboxParameter.from_string_parameter( - server_data.get_as_string(2)); - + + StringParameter mailbox_param = server_data.get_as_string(2); + int messages = UNSET; int recent = UNSET; UID? uid_next = null; diff -Nru geary-0.12.2/src/engine/imap-db/imap-db-folder.vala geary-0.12.4/src/engine/imap-db/imap-db-folder.vala --- geary-0.12.2/src/engine/imap-db/imap-db-folder.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/engine/imap-db/imap-db-folder.vala 2018-08-29 13:57:20.000000000 +0000 @@ -1919,25 +1919,27 @@ MessageRow row = do_fetch_message_row(cx, location.message_id, Geary.Email.Field.FLAGS, out pre_fields, cancellable); post_fields = pre_fields; - - // compare flags for (a) any change at all and (b) unread changes + + // Only update if changed Geary.Email row_email = row.to_email(location.email_id); - - if (row_email.email_flags != null && row_email.email_flags.equal_to(email.email_flags)) - return; - - if (row_email.email_flags.is_unread() != email.email_flags.is_unread()) - unread_count_change += email.email_flags.is_unread() ? 1 : -1; - - // write them out to the message row - Gee.Map map = new Gee.HashMap(); - map.set((ImapDB.EmailIdentifier) email.id, email.email_flags); - - do_set_email_flags(cx, map, cancellable); - post_fields |= Geary.Email.Field.FLAGS; + if (row_email.email_flags == null || + !row_email.email_flags.equal_to(email.email_flags)) { + + // Check for unread count changes + if (row_email.email_flags != null && + row_email.email_flags.is_unread() != email.email_flags.is_unread()) { + unread_count_change += email.email_flags.is_unread() ? 1 : -1; + } + + Gee.Map map = + new Gee.HashMap(); + map.set((ImapDB.EmailIdentifier) email.id, email.email_flags); + do_set_email_flags(cx, map, cancellable); + + post_fields |= Geary.Email.Field.FLAGS; + } } - + private void do_merge_email(Db.Connection cx, LocationIdentifier location, Geary.Email email, out Geary.Email.Field pre_fields, out Geary.Email.Field post_fields, out Gee.Collection updated_contacts, ref int unread_count_change, diff -Nru geary-0.12.2/src/engine/mime/mime-content-parameters.vala geary-0.12.4/src/engine/mime/mime-content-parameters.vala --- geary-0.12.2/src/engine/mime/mime-content-parameters.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/engine/mime/mime-content-parameters.vala 2018-08-29 13:57:20.000000000 +0000 @@ -78,7 +78,7 @@ return (stored != null) ? Ascii.stri_equal(stored, value) : false; } - + /** * Returns true if the attribute has the supplied value (case-sensitive comparison). * @@ -86,10 +86,10 @@ */ public bool has_value_cs(string attribute, string value) { string? stored = params.get(attribute); - - return (stored != null) ? (stored == value) : false; + + return (stored != null) ? Ascii.str_equal(stored, value) : false; } - + /** * Add or replace the parameter. * diff -Nru geary-0.12.2/src/engine/mime/mime-content-type.vala geary-0.12.4/src/engine/mime/mime-content-type.vala --- geary-0.12.2/src/engine/mime/mime-content-type.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/engine/mime/mime-content-type.vala 2018-08-29 13:57:20.000000000 +0000 @@ -79,9 +79,9 @@ int max_len = 4096; // XXX determine actual max needed buffer size using // xdg_mime_get_max_buffer_extents? - uint8[] data = (max_len > buf.size) - ? buf.get_bytes()[0:max_len - 1].get_data() - : buf.get_uint8_array(); + uint8[] data = (buf.size <= max_len) + ? buf.get_uint8_array() + : buf.get_bytes()[0:max_len].get_data(); // XXX might just want to use xdgmime lib directly here to // avoid the intermediate glib_content_type step here? diff -Nru geary-0.12.2/src/engine/mime/mime-disposition-type.vala geary-0.12.4/src/engine/mime/mime-disposition-type.vala --- geary-0.12.2/src/engine/mime/mime-disposition-type.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/engine/mime/mime-disposition-type.vala 2018-08-29 13:57:20.000000000 +0000 @@ -31,24 +31,24 @@ */ public static DispositionType deserialize(string? str, out bool is_unknown) { is_unknown = false; - + if (String.is_empty_or_whitespace(str)) return UNSPECIFIED; - - switch (str.down()) { + + switch (Ascii.strdown(str)) { case "inline": return INLINE; - + case "attachment": return ATTACHMENT; - + default: is_unknown = true; - + return ATTACHMENT; } } - + /** * Returns null if value is {@link UNSPECIFIED} */ diff -Nru geary-0.12.2/src/engine/mime/mime-multipart-subtype.vala geary-0.12.4/src/engine/mime/mime-multipart-subtype.vala --- geary-0.12.2/src/engine/mime/mime-multipart-subtype.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/engine/mime/mime-multipart-subtype.vala 2018-08-29 13:57:20.000000000 +0000 @@ -48,24 +48,24 @@ public static MultipartSubtype from_content_type(ContentType? content_type, out bool is_unknown) { if (content_type == null || !content_type.has_media_type("multipart")) { is_unknown = true; - + return MIXED; } - + is_unknown = false; - switch (content_type.media_subtype.down()) { + switch (Ascii.strdown(content_type.media_subtype)) { case "mixed": return MIXED; - + case "alternative": return ALTERNATIVE; - + case "related": return RELATED; - + default: is_unknown = true; - + return MIXED; } } diff -Nru geary-0.12.2/src/engine/rfc822/rfc822-mailbox-address.vala geary-0.12.4/src/engine/rfc822/rfc822-mailbox-address.vala --- geary-0.12.2/src/engine/rfc822/rfc822-mailbox-address.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/engine/rfc822/rfc822-mailbox-address.vala 2018-08-29 13:57:20.000000000 +0000 @@ -53,7 +53,7 @@ source_route = null; - int atsign = address.index_of_char('@'); + int atsign = Ascii.index_of(address, '@'); if (atsign > 0) { mailbox = address.slice(0, atsign); domain = address.slice(atsign + 1, address.length); @@ -62,7 +62,7 @@ domain = ""; } } - + public MailboxAddress.imap(string? name, string? source_route, string mailbox, string domain) { this.name = (name != null) ? decode_name(name) : null; this.source_route = source_route; diff -Nru geary-0.12.2/src/engine/smtp/smtp-command.vala geary-0.12.4/src/engine/smtp/smtp-command.vala --- geary-0.12.2/src/engine/smtp/smtp-command.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/engine/smtp/smtp-command.vala 2018-08-29 13:57:20.000000000 +0000 @@ -56,36 +56,36 @@ assert_not_reached(); } } - + public static Command deserialize(string str) throws SmtpError { - switch (str.down()) { + switch (Ascii.strdown(str)) { case "helo": return HELO; - + case "ehlo": return EHLO; - + case "quit": return QUIT; - + case "help": return HELP; - + case "noop": return NOOP; - + case "rset": return RSET; - + case "auth": return AUTH; - + case "mail": return MAIL; - + case "rcpt": return RCPT; - + case "data": return DATA; diff -Nru geary-0.12.2/src/engine/smtp/smtp-greeting.vala geary-0.12.4/src/engine/smtp/smtp-greeting.vala --- geary-0.12.2/src/engine/smtp/smtp-greeting.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/engine/smtp/smtp-greeting.vala 2018-08-29 13:57:20.000000000 +0000 @@ -25,21 +25,21 @@ return ""; } } - + public static ServerFlavor deserialize(string str) { - switch (str.up()) { + switch (Ascii.strup(str)) { case "SMTP": return SMTP; - + case "ESMTP": return ESMTP; - + default: return UNSPECIFIED; } } } - + public string? domain { get; private set; default = null; } public ServerFlavor flavor { get; private set; default = ServerFlavor.UNSPECIFIED; } public string? message { get; private set; default = null; } diff -Nru geary-0.12.2/src/engine/util/util-ascii.vala geary-0.12.4/src/engine/util/util-ascii.vala --- geary-0.12.2/src/engine/util/util-ascii.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/engine/util/util-ascii.vala 2018-08-29 13:57:20.000000000 +0000 @@ -4,40 +4,71 @@ * (version 2.1 or later). See the COPYING file in this distribution. */ +// These calls are bound to the string class in Vala 0.26. When that version of Vala is the +// minimum, these can be dropped and Ascii.strup and Ascii.strdown can use the string methods. +extern string g_ascii_strup(string str, ssize_t len = -1); +extern string g_ascii_strdown(string str, ssize_t len = -1); + namespace Geary.Ascii { +public int index_of(string str, char ch) { + char *strptr = str; + int index = 0; + for (;;) { + char strch = *strptr++; + + if (strch == String.EOS) + return -1; + + if (strch == ch) + return index; + + index++; + } +} + public bool get_next_char(string str, ref int index, out char ch) { ch = str[index++]; - + return ch != String.EOS; } -public bool stri_equal(string a, string b) { - // XXX Is this marginally faster than a.down() == b.down() in the - // best case, slower in the worse case, so not worth it? +public inline int strcmp(string a, string b) { + return GLib.strcmp(a, b); +} + +public int stricmp(string a, string b) { char *aptr = a; char *bptr = b; for (;;) { int diff = (int) (*aptr).tolower() - (int) (*bptr).tolower(); if (diff != 0) - return false; - + return diff; + if (*aptr == String.EOS) - return true; - + return 0; + aptr++; bptr++; } } +public inline bool str_equal(string a, string b) { + return a == b; +} + +public inline bool stri_equal(string a, string b) { + return stricmp(a, b) == 0; +} + public bool nullable_stri_equal(string? a, string? b) { if (a == null) return (b == null); - + // a != null, so always false if (b == null) return false; - + return stri_equal(a, b); } @@ -55,6 +86,14 @@ return (str != null) ? stri_hash(str) : 0; } +public string strdown(string str) { + return g_ascii_strdown(str); +} + +public string strup(string str) { + return g_ascii_strup(str); +} + /** * Returns true if the ASCII string contains only whitespace and at least one numeric character. */ diff -Nru geary-0.12.2/src/engine/util/util-imap-utf7.vala geary-0.12.4/src/engine/util/util-imap-utf7.vala --- geary-0.12.2/src/engine/util/util-imap-utf7.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/src/engine/util/util-imap-utf7.vala 2018-08-29 13:57:20.000000000 +0000 @@ -94,7 +94,7 @@ return -1; } -public string utf8_to_imap_utf7(string str) throws ConvertError { +public string utf8_to_imap_utf7(string str) { int p = first_encode_index(str); if (p < 0) { /* no characters that need to be encoded */ diff -Nru geary-0.12.2/test/CMakeLists.txt geary-0.12.4/test/CMakeLists.txt --- geary-0.12.2/test/CMakeLists.txt 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/test/CMakeLists.txt 2018-08-29 13:57:20.000000000 +0000 @@ -8,6 +8,8 @@ engine/api/geary-attachment-test.vala engine/api/geary-engine-test.vala + engine/imap/message/imap-data-format-test.vala + engine/imap/message/imap-mailbox-specifier-test.vala engine/imap/transport/imap-deserializer-test.vala engine/mime-content-type-test.vala engine/rfc822-mailbox-address-test.vala diff -Nru geary-0.12.2/test/engine/api/geary-attachment-test.vala geary-0.12.4/test/engine/api/geary-attachment-test.vala --- geary-0.12.2/test/engine/api/geary-attachment-test.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/test/engine/api/geary-attachment-test.vala 2018-08-29 13:57:20.000000000 +0000 @@ -56,6 +56,8 @@ get_safe_file_name_with_default_content_type); add_test("get_safe_file_name_with_default_content_type_bad_file_name", get_safe_file_name_with_default_content_type_bad_file_name); + add_test("get_safe_file_name_with_unknown_content_type", + get_safe_file_name_with_unknown_content_type); } public override void set_up() { @@ -235,4 +237,24 @@ assert(test.get_safe_file_name.end(async_result()) == RESULT_FILENAME); } + public void get_safe_file_name_with_unknown_content_type() { + const string TEST_FILENAME = "test-filename.unlikely"; + Attachment test = new TestAttachment( + ATTACHMENT_ID, + this.default_type, + CONTENT_ID, + CONTENT_DESC, + content_disposition, + TEST_FILENAME, + File.new_for_path(TEST_FILENAME), + 742 + ); + + test.get_safe_file_name.begin(null, (obj, ret) => { + async_complete(ret); + }); + + assert(TEST_FILENAME == test.get_safe_file_name.end(async_result())); + } + } diff -Nru geary-0.12.2/test/engine/imap/message/imap-data-format-test.vala geary-0.12.4/test/engine/imap/message/imap-data-format-test.vala --- geary-0.12.2/test/engine/imap/message/imap-data-format-test.vala 1970-01-01 00:00:00.000000000 +0000 +++ geary-0.12.4/test/engine/imap/message/imap-data-format-test.vala 2018-08-29 13:57:20.000000000 +0000 @@ -0,0 +1,86 @@ +/* + * Copyright 2018 Michael Gratton + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + +class Geary.Imap.DataFormatTest : Gee.TestCase { + + + public DataFormatTest() { + base("Geary.Imap.DataFormatTest"); + add_test("is_atom_special", is_atom_special); + } + + public void is_atom_special() { + assert_true( + !DataFormat.is_atom_special('a') && !DataFormat.is_atom_special('z') + ); + assert_true( + !DataFormat.is_atom_special('A') && !DataFormat.is_atom_special('Z') + ); + assert_true( + !DataFormat.is_atom_special('0') && !DataFormat.is_atom_special('9') + ); + assert_true( + !DataFormat.is_atom_special('#') && + !DataFormat.is_atom_special('.') && + !DataFormat.is_atom_special('+') && + !DataFormat.is_atom_special('/') && + !DataFormat.is_atom_special('~') && + !DataFormat.is_atom_special(':') + ); + + // atom-specials + assert_true( + DataFormat.is_atom_special('(') + ); + assert_true( + DataFormat.is_atom_special(')') + ); + assert_true( + DataFormat.is_atom_special('{') + ); + assert_true( + DataFormat.is_atom_special(' ') + ); + assert_true( + DataFormat.is_atom_special(0x00) + ); + assert_true( + DataFormat.is_atom_special(0x1F) + ); + assert_true( + DataFormat.is_atom_special(0x7F) + ); + assert_true( + DataFormat.is_atom_special(0x80) + ); + assert_true( + DataFormat.is_atom_special(0xFE) + ); + + // list-wildcards + assert_true( + DataFormat.is_atom_special('%') + ); + assert_true( + DataFormat.is_atom_special('*') + ); + + // quoted-specials + assert_true( + DataFormat.is_atom_special('\"') + ); + assert_true( + DataFormat.is_atom_special('\\') + ); + + // resp-specials + assert_true( + DataFormat.is_atom_special(']') + ); + } + +} diff -Nru geary-0.12.2/test/engine/imap/message/imap-mailbox-specifier-test.vala geary-0.12.4/test/engine/imap/message/imap-mailbox-specifier-test.vala --- geary-0.12.2/test/engine/imap/message/imap-mailbox-specifier-test.vala 1970-01-01 00:00:00.000000000 +0000 +++ geary-0.12.4/test/engine/imap/message/imap-mailbox-specifier-test.vala 2018-08-29 13:57:20.000000000 +0000 @@ -0,0 +1,60 @@ +/* + * Copyright 2018 Michael Gratton + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + +class Geary.Imap.MailboxSpecifierTest : Gee.TestCase { + + + public MailboxSpecifierTest() { + base("Geary.Imap.MailboxSpecifierTest"); + add_test("to_parameter", to_parameter); + add_test("from_parameter", from_parameter); + } + + public void to_parameter() { + assert( + "test" == + new MailboxSpecifier("test").to_parameter().to_string() + ); + assert( + "foo/bar" == + new MailboxSpecifier("foo/bar").to_parameter().to_string() + ); + + // The param won't be quoted or escaped since + // QuotedStringParameter doesn't actually handle that, so just + // check that it is correct type + Parameter quoted = new MailboxSpecifier("""foo\bar""").to_parameter(); + assert(quoted is QuotedStringParameter); + + assert( + "ol&AOk-" == + new MailboxSpecifier("olé").to_parameter().to_string() + ); + } + + public void from_parameter() { + assert( + "test" == + new MailboxSpecifier.from_parameter( + new UnquotedStringParameter("test")).name + ); + + // This won't be quoted or escaped since QuotedStringParameter + // doesn't actually handle that. + assert( + "foo\\bar" == + new MailboxSpecifier.from_parameter( + new QuotedStringParameter("""foo\bar""")).name + ); + assert( + "olé" == + new MailboxSpecifier.from_parameter( + new UnquotedStringParameter("ol&AOk-")).name + ); + } + +} diff -Nru geary-0.12.2/test/engine/imap/transport/imap-deserializer-test.vala geary-0.12.4/test/engine/imap/transport/imap-deserializer-test.vala --- geary-0.12.2/test/engine/imap/transport/imap-deserializer-test.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/test/engine/imap/transport/imap-deserializer-test.vala 2018-08-29 13:57:20.000000000 +0000 @@ -48,8 +48,8 @@ public void test_gmail_greeting() { string greeting = "* OK Gimap ready for requests from 115.187.245.46 c194mb399904375ivc"; - this.stream.add_data(greeting.data); - this.stream.add_data(EOL.data); + this.stream.add_data(greeting.data, g_free); + this.stream.add_data(EOL.data, g_free); this.process.begin(Expect.MESSAGE, (obj, ret) => { async_complete(ret); }); RootParameters? message = this.process.end(async_result()); @@ -59,8 +59,8 @@ public void test_cyrus_2_4_greeting() { string greeting = "* OK [CAPABILITY IMAP4rev1 LITERAL+ ID ENABLE AUTH=PLAIN SASL-IR] mogul Cyrus IMAP v2.4.12-Debian-2.4.12-2 server ready"; - this.stream.add_data(greeting.data); - this.stream.add_data(EOL.data); + this.stream.add_data(greeting.data, g_free); + this.stream.add_data(EOL.data, g_free); this.process.begin(Expect.MESSAGE, (obj, ret) => { async_complete(ret); }); RootParameters? message = this.process.end(async_result()); @@ -71,8 +71,8 @@ public void test_aliyun_greeting() { string greeting = "* OK AliYun IMAP Server Ready(10.147.40.164)"; string parsed = "* OK AliYun IMAP Server Ready (10.147.40.164)"; - this.stream.add_data(greeting.data); - this.stream.add_data(EOL.data); + this.stream.add_data(greeting.data, g_free); + this.stream.add_data(EOL.data, g_free); this.process.begin(Expect.MESSAGE, (obj, ret) => { async_complete(ret); }); RootParameters? message = this.process.end(async_result()); @@ -82,8 +82,8 @@ public void test_invalid_atom_prefix() { string flags = """* OK %atom"""; - this.stream.add_data(flags.data); - this.stream.add_data(EOL.data); + this.stream.add_data(flags.data, g_free); + this.stream.add_data(EOL.data, g_free); this.process.begin(Expect.DESER_FAIL, (obj, ret) => { async_complete(ret); }); this.process.end(async_result()); @@ -91,8 +91,8 @@ public void test_gmail_flags() { string flags = """* FLAGS (\Answered \Flagged \Draft \Deleted \Seen $NotPhishing $Phishing)"""; - this.stream.add_data(flags.data); - this.stream.add_data(EOL.data); + this.stream.add_data(flags.data, g_free); + this.stream.add_data(EOL.data, g_free); this.process.begin(Expect.MESSAGE, (obj, ret) => { async_complete(ret); }); RootParameters? message = this.process.end(async_result()); @@ -102,8 +102,8 @@ public void test_gmail_permanent_flags() { string flags = """* OK [PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen $NotPhishing $Phishing \*)] Flags permitted."""; - this.stream.add_data(flags.data); - this.stream.add_data(EOL.data); + this.stream.add_data(flags.data, g_free); + this.stream.add_data(EOL.data, g_free); this.process.begin(Expect.MESSAGE, (obj, ret) => { async_complete(ret); }); RootParameters? message = this.process.end(async_result()); @@ -113,8 +113,8 @@ public void test_cyrus_flags() { string flags = """* 2934 FETCH (FLAGS (\Answered \Seen $Quuxo::Spam::Trained) UID 3041)"""; - this.stream.add_data(flags.data); - this.stream.add_data(EOL.data); + this.stream.add_data(flags.data, g_free); + this.stream.add_data(EOL.data, g_free); this.process.begin(Expect.MESSAGE, (obj, ret) => { async_complete(ret); }); RootParameters? message = this.process.end(async_result()); @@ -128,8 +128,8 @@ // distinct atom. string flags = """* OK \*atom"""; string expected = """* OK \* atom"""; - this.stream.add_data(flags.data); - this.stream.add_data(EOL.data); + this.stream.add_data(flags.data, g_free); + this.stream.add_data(EOL.data, g_free); this.process.begin(Expect.MESSAGE, (obj, ret) => { async_complete(ret); }); RootParameters? message = this.process.end(async_result()); @@ -139,8 +139,8 @@ public void test_invalid_flag_prefix() { string flags = """* OK \%atom"""; - this.stream.add_data(flags.data); - this.stream.add_data(EOL.data); + this.stream.add_data(flags.data, g_free); + this.stream.add_data(EOL.data, g_free); this.process.begin(Expect.DESER_FAIL, (obj, ret) => { async_complete(ret); }); this.process.end(async_result()); @@ -154,7 +154,7 @@ public void test_bye_eos() { string bye = """* OK bye"""; - this.stream.add_data(bye.data); + this.stream.add_data(bye.data, g_free); bool eos = false; this.deser.eos.connect(() => { eos = true; }); @@ -211,6 +211,12 @@ assert_not_reached(); } + // Process any remaining async tasks the deserializer might + // have left over. + while (this.main_loop.pending()) { + this.main_loop.iteration(true); + } + return message; } diff -Nru geary-0.12.2/test/main.vala geary-0.12.4/test/main.vala --- geary-0.12.2/test/main.vala 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/test/main.vala 2018-08-29 13:57:20.000000000 +0000 @@ -40,7 +40,9 @@ engine.add_suite(new Geary.AttachmentTest().get_suite()); engine.add_suite(new Geary.EngineTest().get_suite()); engine.add_suite(new Geary.HTML.UtilTest().get_suite()); + engine.add_suite(new Geary.Imap.DataFormatTest().get_suite()); engine.add_suite(new Geary.Imap.DeserializerTest().get_suite()); + engine.add_suite(new Geary.Imap.MailboxSpecifierTest().get_suite()); engine.add_suite(new Geary.IdleManagerTest().get_suite()); engine.add_suite(new Geary.Inet.Test().get_suite()); engine.add_suite(new Geary.JS.Test().get_suite()); diff -Nru geary-0.12.2/THANKS geary-0.12.4/THANKS --- geary-0.12.2/THANKS 2018-04-24 00:22:39.000000000 +0000 +++ geary-0.12.4/THANKS 2018-08-29 13:57:20.000000000 +0000 @@ -56,6 +56,7 @@ Mario Sanchez Prada Tiago Quelhas Viko Adi Rahmawan +nick richards ritchiew Leonardo Robol Didier Roche