Compare commits

...

No commits in common. 'c9' and 'i8-beta' have entirely different histories.
c9 ... i8-beta

@ -1 +1 @@
78072b4913ec2158de4aa6f3782891ea4146f3e7 SOURCES/evolution-ews-3.40.4.tar.xz
22caa0a3798f51757f88fd19c9ca74284f62b0d3 SOURCES/evolution-ews-3.28.5.tar.xz

2
.gitignore vendored

@ -1 +1 @@
SOURCES/evolution-ews-3.40.4.tar.xz
SOURCES/evolution-ews-3.28.5.tar.xz

File diff suppressed because it is too large Load Diff

@ -0,0 +1,57 @@
diff -up evolution-ews-3.28.5/src/camel/camel-ews-folder.c.workaround-office365.com-bug evolution-ews-3.28.5/src/camel/camel-ews-folder.c
--- evolution-ews-3.28.5/src/camel/camel-ews-folder.c.workaround-office365.com-bug 2018-07-30 16:01:00.000000000 +0200
+++ evolution-ews-3.28.5/src/camel/camel-ews-folder.c 2023-12-13 13:38:31.707627927 +0100
@@ -355,7 +355,7 @@ ews_get_calendar_mime_part (CamelMimePar
}
static gchar *
-ews_update_mgtrequest_mime_calendar_itemid (const gchar *mime_fname,
+ews_update_mtgrequest_mime_calendar_itemid (const gchar *mime_fname,
const EwsId *calendar_item_id,
gboolean is_calendar_UID,
const EwsId *mail_item_id,
@@ -414,6 +414,35 @@ ews_update_mgtrequest_mime_calendar_item
if (ba && ba->len) {
g_byte_array_append (ba, (guint8 *) "\0", 1);
icalcomp = icalparser_parse_string ((gchar *) ba->data);
+ if (!icalcomp) {
+ const gchar *content = (const gchar *) ba->data;
+ const gchar *begin_vcalendar, *end_vcalendar;
+
+ /* Workaround Office365.com error, which returns invalid iCalendar object (without 'END:VCALENDAR'),
+ in the MimeContent's text/calendar attachments as of 2023-12-12. */
+ begin_vcalendar = camel_strstrcase (content, "BEGIN:VCALENDAR");
+ end_vcalendar = camel_strstrcase (content, "END:VCALENDAR");
+
+ /* If it exists, then it should be alone on a separate line */
+ if (!(begin_vcalendar && (begin_vcalendar == content || begin_vcalendar[-1] == '\n') &&
+ (begin_vcalendar[15 /* strlen ("BEGIN:VCALENDAR") */] == '\r' || begin_vcalendar[15] == '\n')))
+ begin_vcalendar = NULL;
+
+ /* If it exists, then it should be alone on a separate line and not at the very beginning of the mime_content */
+ if (!(end_vcalendar && end_vcalendar > content && end_vcalendar[-1] == '\n' &&
+ (end_vcalendar[13 /* strlen ("END:VCALENDAR") */] == '\r' || end_vcalendar[13] == '\n' || end_vcalendar[13] == '\0')))
+ end_vcalendar = NULL;
+
+ if (begin_vcalendar && !end_vcalendar) {
+ g_byte_array_remove_index (ba, ba->len - 1);
+ #define add_str(_str) g_byte_array_append (ba, (guint8 *) _str, strlen (_str))
+ add_str ("\r\nEND:VCALENDAR\r\n");
+ #undef add_str
+ g_byte_array_append (ba, (guint8 *) "\0", 1);
+
+ icalcomp = icalparser_parse_string ((gchar *) ba->data);
+ }
+ }
}
if (icalcomp) {
icalcomponent *subcomp;
@@ -888,7 +917,7 @@ camel_ews_folder_get_message (CamelFolde
calendar_item_accept_id = e_ews_item_get_id (items->data);
is_calendar_UID = FALSE;
}
- mime_fname_new = ews_update_mgtrequest_mime_calendar_itemid (mime_content, calendar_item_accept_id, is_calendar_UID, e_ews_item_get_id (items->data), error);
+ mime_fname_new = ews_update_mtgrequest_mime_calendar_itemid (mime_content, calendar_item_accept_id, is_calendar_UID, e_ews_item_get_id (items->data), error);
if (mime_fname_new)
mime_content = (const gchar *) mime_fname_new;

@ -0,0 +1,28 @@
diff -up evolution-ews-3.28.5/src/server/e-ews-connection.c.deadlock evolution-ews-3.28.5/src/server/e-ews-connection.c
--- evolution-ews-3.28.5/src/server/e-ews-connection.c.deadlock 2024-02-06 15:56:24.994038118 +0100
+++ evolution-ews-3.28.5/src/server/e-ews-connection.c 2024-02-06 15:57:45.656178096 +0100
@@ -698,22 +698,20 @@ ews_next_request (gpointer _cnc)
/* Add to active job queue */
cnc->priv->active_job_queue = g_slist_append (cnc->priv->active_job_queue, node);
+ QUEUE_UNLOCK (cnc);
+
if (cnc->priv->soup_session) {
SoupMessage *msg = SOUP_MESSAGE (node->msg);
if (!e_ews_connection_utils_prepare_message (cnc, msg, node->cancellable)) {
e_ews_debug_dump_raw_soup_request (msg);
- QUEUE_UNLOCK (cnc);
ews_response_cb (cnc->priv->soup_session, msg, node);
} else {
e_ews_debug_dump_raw_soup_request (msg);
soup_session_queue_message (cnc->priv->soup_session, msg, ews_response_cb, node);
- QUEUE_UNLOCK (cnc);
}
} else {
- QUEUE_UNLOCK (cnc);
-
ews_cancel_request (NULL, node);
}

@ -0,0 +1,783 @@
diff -up evolution-ews-3.28.5/src/configuration/e-mail-config-ews-backend.c.autodiscover-improvements evolution-ews-3.28.5/src/configuration/e-mail-config-ews-backend.c
--- evolution-ews-3.28.5/src/configuration/e-mail-config-ews-backend.c.autodiscover-improvements 2022-05-06 09:52:48.565933224 +0200
+++ evolution-ews-3.28.5/src/configuration/e-mail-config-ews-backend.c 2022-05-06 09:52:48.570933226 +0200
@@ -661,8 +661,10 @@ mail_config_ews_backend_setup_defaults (
camel_ews_settings_set_hosturl (ews_settings, hosturl);
camel_ews_settings_set_email (ews_settings, email_address);
+ /* Prefill email address as the user name, it's needed for office365.com
+ server, but also on-premise servers support it. */
network_settings = CAMEL_NETWORK_SETTINGS (settings);
- camel_network_settings_set_user (network_settings, parts[0]);
+ camel_network_settings_set_user (network_settings, email_address);
g_free (hosturl);
}
diff -up evolution-ews-3.28.5/src/server/e-ews-connection.c.autodiscover-improvements evolution-ews-3.28.5/src/server/e-ews-connection.c
--- evolution-ews-3.28.5/src/server/e-ews-connection.c.autodiscover-improvements 2022-05-06 09:52:48.567933225 +0200
+++ evolution-ews-3.28.5/src/server/e-ews-connection.c 2022-05-06 12:23:47.370716242 +0200
@@ -468,6 +468,38 @@ autodiscover_parse_protocol (xmlNode *no
return FALSE;
}
+static xmlChar *
+autodiscover_get_protocol_type (xmlNode *node)
+{
+ for (node = node->children; node; node = node->next) {
+ if (node->type == XML_ELEMENT_NODE &&
+ !strcmp ((gchar *) node->name, "Type")) {
+ return xmlNodeGetContent (node);
+ }
+ }
+
+ return NULL;
+}
+
+static gchar *
+autodiscover_dup_element_value (xmlNode *node,
+ const gchar *element_name)
+{
+ for (node = node->children; node; node = node->next) {
+ if (node->type == XML_ELEMENT_NODE &&
+ !g_strcmp0 ((gchar *) node->name, element_name)) {
+ xmlChar *str = xmlNodeGetContent (node);
+ gchar *res;
+
+ res = g_strdup ((const gchar *) str);
+ xmlFree (str);
+ return res;
+ }
+ }
+
+ return NULL;
+}
+
static gint
comp_func (gconstpointer a,
gconstpointer b)
@@ -2916,11 +2948,16 @@ e_ews_autodiscover_ws_xml (const gchar *
struct _autodiscover_data {
EEwsConnection *cnc;
xmlOutputBuffer *buf;
- SoupMessage *msgs[5];
+ SoupMessage *msgs[6];
GCancellable *cancellable;
gulong cancel_id;
+ GError *error;
+ gchar *redirect_addr;
+ gchar *redirect_url;
+ gint n_redirects;
+
/* Results */
gchar *as_url;
gchar *oab_url;
@@ -2944,6 +2981,10 @@ autodiscover_data_free (struct _autodisc
its worker thread. */
g_object_unref (ad->cnc);
+ g_clear_error (&ad->error);
+
+ g_free (ad->redirect_addr);
+ g_free (ad->redirect_url);
g_free (ad->as_url);
g_free (ad->oab_url);
@@ -2957,6 +2998,28 @@ autodiscover_cancelled_cb (GCancellable
ews_connection_schedule_abort (cnc);
}
+/* Frees only the content, not the 'urls' structure itself */
+static void
+ews_urls_free_content (EwsUrls *urls)
+{
+ if (!urls)
+ return;
+
+ if (urls->as_url)
+ xmlFree (urls->as_url);
+ urls->as_url = NULL;
+
+ if (urls->oab_url)
+ xmlFree (urls->oab_url);
+ urls->oab_url = NULL;
+}
+
+static gboolean
+e_ews_discover_prepare_messages_and_send (GSimpleAsyncResult *simple,
+ const gchar *email_address,
+ const gchar *override_url,
+ GError **error);
+
/* Called when each soup message completes */
static void
autodiscover_response_cb (SoupSession *session,
@@ -2966,21 +3029,24 @@ autodiscover_response_cb (SoupSession *s
{
GSimpleAsyncResult *simple = data;
struct _autodiscover_data *ad;
- EwsUrls *urls = NULL;
+ EwsUrls exch_urls, expr_urls;
guint status = msg->status_code;
xmlDoc *doc;
xmlNode *node;
+ gchar *str;
gint idx;
- gboolean success = FALSE;
GError *error = NULL;
+ memset (&exch_urls, 0, sizeof (EwsUrls));
+ memset (&expr_urls, 0, sizeof (EwsUrls));
+
ad = g_simple_async_result_get_op_res_gpointer (simple);
- for (idx = 0; idx < 5; idx++) {
+ for (idx = 0; idx < 6; idx++) {
if (ad->msgs[idx] == msg)
break;
}
- if (idx == 5) {
+ if (idx == 6 || (idx == 5 && !ad->msgs[5])) {
/* We already got removed (cancelled). Do nothing */
goto unref;
}
@@ -3048,33 +3114,54 @@ autodiscover_response_cb (SoupSession *s
goto failed;
}
- urls = g_new0 (EwsUrls, 1);
+ str = autodiscover_dup_element_value (node, "RedirectAddr");
+ if (str) {
+ g_free (ad->redirect_addr);
+ ad->redirect_addr = str;
+ }
+
+ str = autodiscover_dup_element_value (node, "RedirectUrl");
+ if (str) {
+ g_free (ad->redirect_url);
+ ad->redirect_url = str;
+ }
+
for (node = node->children; node; node = node->next) {
if (node->type == XML_ELEMENT_NODE &&
!strcmp ((gchar *) node->name, "Protocol")) {
- success = autodiscover_parse_protocol (node, urls);
- /* Since the server may send back multiple <Protocol> nodes
- * don't break unless we found the both URLs.
- */
- if (success)
- break;
+ xmlChar *protocol_type = autodiscover_get_protocol_type (node);
+
+ if (g_strcmp0 ((const gchar *) protocol_type, "EXCH") == 0) {
+ ews_urls_free_content (&exch_urls);
+ autodiscover_parse_protocol (node, &exch_urls);
+ } else if (g_strcmp0 ((const gchar *) protocol_type, "EXPR") == 0) {
+ ews_urls_free_content (&expr_urls);
+ autodiscover_parse_protocol (node, &expr_urls);
+
+ /* EXPR has precedence, thus stop once found both there */
+ if (expr_urls.as_url && expr_urls.oab_url) {
+ xmlFree (protocol_type);
+ break;
+ }
+ }
+
+ if (protocol_type)
+ xmlFree (protocol_type);
}
}
- if (!success) {
- if (urls->as_url != NULL)
- xmlFree (urls->as_url);
- if (urls->oab_url != NULL)
- xmlFree (urls->oab_url);
- g_free (urls);
+ /* Make the <OABUrl> optional */
+ if (!exch_urls.as_url && !expr_urls.as_url) {
+ ews_urls_free_content (&exch_urls);
+ ews_urls_free_content (&expr_urls);
g_set_error (
&error, EWS_CONNECTION_ERROR, -1,
- _("Failed to find <ASUrl> and <OABUrl> in autodiscover response"));
+ _("Failed to find <ASUrl> in autodiscover response"));
goto failed;
}
/* We have a good response; cancel all the others */
- for (idx = 0; idx < 5; idx++) {
+ for (idx = 0; idx < 6; idx++) {
if (ad->msgs[idx]) {
SoupMessage *m = ad->msgs[idx];
ad->msgs[idx] = NULL;
@@ -3082,35 +3169,130 @@ autodiscover_response_cb (SoupSession *s
}
}
- if (urls->as_url != NULL) {
- ad->as_url = g_strdup ((gchar *) urls->as_url);
- xmlFree (urls->as_url);
- }
-
- if (urls->oab_url != NULL) {
- ad->oab_url = g_strdup ((gchar *) urls->oab_url);
- xmlFree (urls->oab_url);
+ if (expr_urls.as_url) {
+ if (ad->as_url)
+ g_free (ad->as_url);
+ ad->as_url = g_strdup ((gchar *) expr_urls.as_url);
+ } else if (exch_urls.as_url) {
+ if (ad->as_url)
+ g_free (ad->as_url);
+ ad->as_url = g_strdup ((gchar *) exch_urls.as_url);
+ }
+
+ if (expr_urls.as_url && expr_urls.oab_url) {
+ if (ad->oab_url)
+ g_free (ad->oab_url);
+ ad->oab_url = g_strdup ((gchar *) expr_urls.oab_url);
+ } else if (!expr_urls.as_url && exch_urls.oab_url) {
+ if (ad->oab_url)
+ g_free (ad->oab_url);
+ ad->oab_url = g_strdup ((gchar *) exch_urls.oab_url);
}
- g_free (urls);
+ ews_urls_free_content (&exch_urls);
+ ews_urls_free_content (&expr_urls);
goto exit;
failed:
- for (idx = 0; idx < 5; idx++) {
+ for (idx = 0; idx < 6; idx++) {
if (ad->msgs[idx]) {
+ /* Preserve any Unauthorized/SSL failed errors */
+ if (!g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_NONE) &&
+ !g_error_matches (ad->error, SOUP_HTTP_ERROR, SOUP_STATUS_UNAUTHORIZED) &&
+ !g_error_matches (ad->error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED) &&
+ (!ad->error ||
+ g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_UNAUTHORIZED) ||
+ g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED) ||
+ g_error_matches (ad->error, SOUP_HTTP_ERROR, SOUP_STATUS_NONE) ||
+ g_error_matches (ad->error, SOUP_HTTP_ERROR, SOUP_STATUS_CANT_RESOLVE) ||
+ g_error_matches (ad->error, SOUP_HTTP_ERROR, SOUP_STATUS_CANT_RESOLVE_PROXY) ||
+ g_error_matches (ad->error, SOUP_HTTP_ERROR, SOUP_STATUS_CANT_CONNECT) ||
+ g_error_matches (ad->error, SOUP_HTTP_ERROR, SOUP_STATUS_CANT_CONNECT_PROXY))) {
+ g_clear_error (&ad->error);
+ ad->error = error;
+ error = NULL;
+ } else {
+ g_clear_error (&error);
+ }
+
/* There's another request outstanding.
* Hope that it has better luck. */
- g_clear_error (&error);
goto unref;
}
}
+ /* Preserve any Unauthorized/SSL failed errors */
+ if (!g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_NONE) &&
+ !g_error_matches (ad->error, SOUP_HTTP_ERROR, SOUP_STATUS_UNAUTHORIZED) &&
+ !g_error_matches (ad->error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED) &&
+ (!ad->error ||
+ g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_UNAUTHORIZED) ||
+ g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED) ||
+ g_error_matches (ad->error, SOUP_HTTP_ERROR, SOUP_STATUS_NONE) ||
+ g_error_matches (ad->error, SOUP_HTTP_ERROR, SOUP_STATUS_CANT_RESOLVE) ||
+ g_error_matches (ad->error, SOUP_HTTP_ERROR, SOUP_STATUS_CANT_RESOLVE_PROXY) ||
+ g_error_matches (ad->error, SOUP_HTTP_ERROR, SOUP_STATUS_CANT_CONNECT) ||
+ g_error_matches (ad->error, SOUP_HTTP_ERROR, SOUP_STATUS_CANT_CONNECT_PROXY))) {
+ g_clear_error (&ad->error);
+ ad->error = error;
+ error = NULL;
+ }
+
+ g_clear_error (&error);
+
+ if (!g_cancellable_is_cancelled (ad->cancellable) &&
+ (!ad->as_url || !ad->oab_url) && ad->n_redirects < 11 &&
+ (ad->redirect_url || ad->redirect_addr) &&
+ !g_error_matches (ad->error, SOUP_HTTP_ERROR, SOUP_STATUS_UNAUTHORIZED) &&
+ !g_error_matches (ad->error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED)) {
+ CamelEwsSettings *settings = NULL;
+ gboolean re_scheduled;
+ const gchar *host_url;
+ gchar *redirect_addr, *redirect_url;
+ GError *local_error;
+
+ redirect_addr = ad->redirect_addr;
+ redirect_url = ad->redirect_url;
+ local_error = ad->error;
+
+ /* To avoid infinite recursion */
+ ad->redirect_addr = NULL;
+ ad->redirect_url = NULL;
+ ad->n_redirects++;
+ ad->error = NULL;
+
+ host_url = redirect_url;
+ settings = e_ews_connection_ref_settings (ad->cnc);
+
+ if (!host_url)
+ host_url = camel_ews_settings_get_hosturl (settings);
+
+ if (redirect_addr && *redirect_addr)
+ camel_network_settings_set_user (CAMEL_NETWORK_SETTINGS (settings), redirect_addr);
+
+ re_scheduled = e_ews_discover_prepare_messages_and_send (simple, redirect_addr, host_url, NULL);
+
+ g_clear_object (&settings);
+
+ g_free (redirect_addr);
+ g_free (redirect_url);
+
+ if (re_scheduled) {
+ g_clear_error (&local_error);
+ goto unref;
+ }
+
+ ad->error = local_error;
+ }
+
/* FIXME: We're actually returning the *last* error here,
* and in some cases (stupid firewalls causing timeouts)
* that's going to be the least interesting one. We probably
* want the *first* error */
- g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_take_error (simple, ad->error);
+
+ ad->error = NULL;
exit:
g_simple_async_result_complete_in_idle (simple);
@@ -3125,7 +3307,10 @@ autodiscover_response_cb (SoupSession *s
e_ews_connection_utils_unref_in_thread (simple);
}
-static void post_restarted (SoupMessage *msg, gpointer data)
+
+static void
+post_restarted (SoupMessage *msg,
+ gpointer data)
{
xmlOutputBuffer *buf = data;
@@ -3151,12 +3336,12 @@ static void post_restarted (SoupMessage
static SoupMessage *
e_ews_get_msg_for_url (EEwsConnection *cnc,
- CamelEwsSettings *settings,
const gchar *url,
xmlOutputBuffer *buf,
GError **error)
{
SoupMessage *msg;
+ CamelEwsSettings *settings;
if (url == NULL) {
g_set_error_literal (
@@ -3178,7 +3363,9 @@ e_ews_get_msg_for_url (EEwsConnection *c
e_ews_message_attach_chunk_allocator (msg);
+ settings = e_ews_connection_ref_settings (cnc);
e_ews_message_set_user_agent_header (msg, settings);
+ g_clear_object (&settings);
if (buf != NULL) {
soup_message_set_request (
@@ -3189,7 +3376,7 @@ e_ews_get_msg_for_url (EEwsConnection *c
#else
buf->buffer->content, buf->buffer->use
#endif
- );
+ );
g_signal_connect (
msg, "restarted",
G_CALLBACK (post_restarted), buf);
@@ -3200,6 +3387,69 @@ e_ews_get_msg_for_url (EEwsConnection *c
return msg;
}
+static void
+autodiscover_srv_record_resolved_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GList *targets, *link;
+ GSimpleAsyncResult *simple = user_data;
+ struct _autodiscover_data *ad;
+ gchar *new_uri = NULL;
+ gboolean success;
+
+ ad = g_simple_async_result_get_op_res_gpointer (simple);
+
+ g_return_if_fail (ad != NULL);
+
+ targets = g_resolver_lookup_service_finish (G_RESOLVER (source), result, NULL);
+
+ success = ad->msgs[5] && targets;
+
+ for (link = targets; link && success; link = g_list_next (link)) {
+ GSrvTarget *target = link->data;
+ const gchar *hostname;
+
+ hostname = g_srv_target_get_hostname (target);
+
+ switch (g_srv_target_get_port (target)) {
+ case 80:
+ link = NULL;
+ new_uri = g_strdup_printf ("http://%s/autodiscover/autodiscover.xml", hostname);
+ break;
+ case 443:
+ link = NULL;
+ new_uri = g_strdup_printf ("https://%s/autodiscover/autodiscover.xml", hostname);
+ break;
+ }
+ }
+
+ g_list_free_full (targets, (GDestroyNotify) g_srv_target_free);
+
+ if (new_uri && success) {
+ SoupURI *suri;
+
+ suri = soup_uri_new (new_uri);
+ if (suri) {
+ soup_message_set_uri (ad->msgs[5], suri);
+ /* The autodiscover_response_cb will free the 'simple' */
+ ews_connection_schedule_queue_message (ad->cnc, ad->msgs[5], autodiscover_response_cb, simple);
+ soup_uri_free (suri);
+ } else {
+ success = FALSE;
+ }
+ } else {
+ success = FALSE;
+ }
+
+ g_free (new_uri);
+
+ if (!success) {
+ /* The callback also frees the 'simple' */
+ autodiscover_response_cb (NULL, ad->msgs[5], simple);
+ }
+}
+
gboolean
e_ews_autodiscover_ws_url_sync (ESource *source,
CamelEwsSettings *settings,
@@ -3232,50 +3482,43 @@ e_ews_autodiscover_ws_url_sync (ESource
return success;
}
-void
-e_ews_autodiscover_ws_url (ESource *source,
- CamelEwsSettings *settings,
- const gchar *email_address,
- const gchar *password,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
+static gboolean
+e_ews_discover_prepare_messages_and_send (GSimpleAsyncResult *simple,
+ const gchar *email_address,
+ const gchar *override_url,
+ GError **error)
{
- GSimpleAsyncResult *simple;
- struct _autodiscover_data *ad;
- xmlOutputBuffer *buf;
- gchar *url1, *url2, *url3, *url4, *url5;
- gchar *domain;
- xmlDoc *doc;
- EEwsConnection *cnc;
SoupURI *soup_uri = NULL;
gboolean use_secure = TRUE;
- const gchar *host_url;
- GError *error = NULL;
+ gboolean is_outlook = FALSE;
+ gchar *url1, *url2, *url3, *url4;
+ const gchar *url5, *domain = NULL;
+ struct _autodiscover_data *ad;
+ GError *local_error = NULL;
- g_return_if_fail (CAMEL_IS_EWS_SETTINGS (settings));
- g_return_if_fail (email_address != NULL);
- g_return_if_fail (password != NULL);
+ ad = g_simple_async_result_get_op_res_gpointer (simple);
+ g_return_val_if_fail (ad != NULL, FALSE);
- simple = g_simple_async_result_new (
- G_OBJECT (settings), callback,
- user_data, e_ews_autodiscover_ws_url);
+ if (email_address) {
+ xmlDoc *doc;
- domain = strchr (email_address, '@');
- if (domain == NULL || *domain == '\0') {
- g_simple_async_result_set_error (
- simple, EWS_CONNECTION_ERROR, -1,
- "%s", _("Email address is missing a domain part"));
- g_simple_async_result_complete_in_idle (simple);
- g_object_unref (simple);
- return;
+ if (ad->buf)
+ xmlOutputBufferClose (ad->buf);
+
+ doc = e_ews_autodiscover_ws_xml (email_address);
+ ad->buf = xmlAllocOutputBuffer (NULL);
+ xmlNodeDumpOutput (ad->buf, doc, xmlDocGetRootElement (doc), 0, 1, NULL);
+ xmlOutputBufferFlush (ad->buf);
+
+ xmlFreeDoc (doc);
+
+ domain = strchr (email_address, '@');
+ if (domain)
+ domain++;
}
- domain++;
- doc = e_ews_autodiscover_ws_xml (email_address);
- buf = xmlAllocOutputBuffer (NULL);
- xmlNodeDumpOutput (buf, doc, xmlDocGetRootElement (doc), 0, 1, NULL);
- xmlOutputBufferFlush (buf);
+ g_return_val_if_fail (ad->buf != NULL, FALSE);
+ g_return_val_if_fail ((domain && *domain) || (override_url && *override_url), FALSE);
url1 = NULL;
url2 = NULL;
@@ -3283,11 +3526,10 @@ e_ews_autodiscover_ws_url (ESource *sour
url4 = NULL;
url5 = NULL;
- host_url = camel_ews_settings_get_hosturl (settings);
- if (host_url != NULL)
- soup_uri = soup_uri_new (host_url);
+ if (override_url)
+ soup_uri = soup_uri_new (override_url);
- if (soup_uri != NULL) {
+ if (soup_uri) {
const gchar *host = soup_uri_get_host (soup_uri);
const gchar *scheme = soup_uri_get_scheme (soup_uri);
@@ -3296,20 +3538,126 @@ e_ews_autodiscover_ws_url (ESource *sour
url1 = g_strdup_printf ("http%s://%s/autodiscover/autodiscover.xml", use_secure ? "s" : "", host);
url2 = g_strdup_printf ("http%s://autodiscover.%s/autodiscover/autodiscover.xml", use_secure ? "s" : "", host);
+ is_outlook = host && g_ascii_strcasecmp (host, "outlook.office365.com") == 0;
+
/* outlook.office365.com has its autodiscovery at outlook.com */
- if (host && g_ascii_strcasecmp (host, "outlook.office365.com") == 0 &&
- domain && g_ascii_strcasecmp (host, "outlook.com") != 0) {
- url5 = g_strdup_printf ("https://outlook.com/autodiscover/autodiscover.xml");
+ if (is_outlook && domain && g_ascii_strcasecmp (domain, "outlook.com") != 0) {
+ url5 = "https://outlook.com/autodiscover/autodiscover.xml";
+ } else if (!is_outlook && domain) {
+ #define ON_MICROSOFT_COM_TEXT "onmicrosoft.com"
+ gint len = strlen (domain);
+ gint onmslen = strlen (ON_MICROSOFT_COM_TEXT);
+
+ if (len >= onmslen) {
+ const gchar *test_domain;
+
+ test_domain = domain + len - onmslen;
+
+ /* onmicrosoft.com addresses might be handled on the outlook.com/office365.com as well */
+ if (g_ascii_strcasecmp (test_domain, ON_MICROSOFT_COM_TEXT) == 0 &&
+ (len == onmslen || (len > onmslen && domain[len - onmslen - 1] == '.')))
+ url5 = "https://outlook.com/autodiscover/autodiscover.xml";
+ }
+ #undef ON_MICROSOFT_COM_TEXT
}
soup_uri_free (soup_uri);
}
- url3 = g_strdup_printf ("http%s://%s/autodiscover/autodiscover.xml", use_secure ? "s" : "", domain);
- url4 = g_strdup_printf ("http%s://autodiscover.%s/autodiscover/autodiscover.xml", use_secure ? "s" : "", domain);
+ is_outlook = is_outlook || (domain && g_ascii_strcasecmp (domain, "outlook.com") == 0);
+
+ if (domain) {
+ url3 = g_strdup_printf ("http%s://%s/autodiscover/autodiscover.xml", use_secure ? "s" : "", domain);
+ url4 = g_strdup_printf ("http%s://autodiscover.%s/autodiscover/autodiscover.xml", use_secure ? "s" : "", domain);
+ }
+
+ /* Passing a NULL URL string returns NULL. */
+ ad->msgs[0] = e_ews_get_msg_for_url (ad->cnc, url1, ad->buf, &local_error);
+ ad->msgs[1] = e_ews_get_msg_for_url (ad->cnc, url2, ad->buf, local_error ? NULL : &local_error);
+ ad->msgs[2] = e_ews_get_msg_for_url (ad->cnc, url3, ad->buf, local_error ? NULL : &local_error);
+ ad->msgs[3] = e_ews_get_msg_for_url (ad->cnc, url4, ad->buf, local_error ? NULL : &local_error);
+ ad->msgs[4] = e_ews_get_msg_for_url (ad->cnc, url5, ad->buf, local_error ? NULL : &local_error);
+
+ if (!is_outlook && domain && *domain && (ad->msgs[0] || ad->msgs[1] || ad->msgs[2] || ad->msgs[3] || ad->msgs[4])) {
+ gchar *tmp;
+
+ tmp = g_strdup_printf ("http%s://%s/", use_secure ? "s" : "", domain);
+
+ /* Fake SoupMessage, for the autodiscovery with SRV record help */
+ ad->msgs[5] = e_ews_get_msg_for_url (ad->cnc, tmp, ad->buf, local_error ? NULL : &local_error);
+
+ if (ad->msgs[5]) {
+ g_resolver_lookup_service_async (g_resolver_get_default (), "autodiscover", "tcp", domain, ad->cancellable,
+ autodiscover_srv_record_resolved_cb, g_object_ref (simple));
+ }
+
+ g_free (tmp);
+ } else {
+ ad->msgs[5] = NULL;
+ }
+
+ if (local_error && (ad->msgs[0] || ad->msgs[1] || ad->msgs[2] || ad->msgs[3] || ad->msgs[4]))
+ g_clear_error (&local_error);
+
+ /* These have to be submitted only after they're both set in ad->msgs[]
+ * or there will be races with fast completion */
+ if (ad->msgs[0] != NULL)
+ ews_connection_schedule_queue_message (ad->cnc, ad->msgs[0], autodiscover_response_cb, g_object_ref (simple));
+ if (ad->msgs[1] != NULL)
+ ews_connection_schedule_queue_message (ad->cnc, ad->msgs[1], autodiscover_response_cb, g_object_ref (simple));
+ if (ad->msgs[2] != NULL)
+ ews_connection_schedule_queue_message (ad->cnc, ad->msgs[2], autodiscover_response_cb, g_object_ref (simple));
+ if (ad->msgs[3] != NULL)
+ ews_connection_schedule_queue_message (ad->cnc, ad->msgs[3], autodiscover_response_cb, g_object_ref (simple));
+ if (ad->msgs[4] != NULL)
+ ews_connection_schedule_queue_message (ad->cnc, ad->msgs[4], autodiscover_response_cb, g_object_ref (simple));
+
+ g_free (url1);
+ g_free (url2);
+ g_free (url3);
+ g_free (url4);
+
+ if (local_error) {
+ g_propagate_error (error, local_error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void
+e_ews_autodiscover_ws_url (ESource *source,
+ CamelEwsSettings *settings,
+ const gchar *email_address,
+ const gchar *password,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ struct _autodiscover_data *ad;
+ const gchar *domain;
+ const gchar *host_url;
+ GError *error = NULL;
+
+ g_return_if_fail (CAMEL_IS_EWS_SETTINGS (settings));
+ g_return_if_fail (email_address != NULL);
+ g_return_if_fail (password != NULL);
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (settings), callback,
+ user_data, e_ews_autodiscover_ws_url);
- cnc = e_ews_connection_new (source, url3, settings);
- e_ews_connection_set_password (cnc, password);
+ domain = strchr (email_address, '@');
+ /* if it's non-NULL, then domain[0] == '@' */
+ if (!domain || !domain[1]) {
+ g_simple_async_result_set_error (
+ simple, EWS_CONNECTION_ERROR, -1,
+ "%s", _("Email address is missing a domain part"));
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+ return;
+ }
/*
* http://msdn.microsoft.com/en-us/library/ee332364.aspx says we are
@@ -3320,48 +3668,25 @@ e_ews_autodiscover_ws_url (ESource *sour
* (successful) one win.
*/
ad = g_slice_new0 (struct _autodiscover_data);
- ad->cnc = cnc; /* takes ownership */
- ad->buf = buf; /* takes ownership */
+ ad->cnc = e_ews_connection_new (source, domain + 1, settings); /* Fake URI, it's not used here */
+ g_object_set (ad->cnc->priv->soup_session, SOUP_SESSION_TIMEOUT, 20, NULL);
+ e_ews_connection_set_password (ad->cnc, password);
if (G_IS_CANCELLABLE (cancellable)) {
ad->cancellable = g_object_ref (cancellable);
ad->cancel_id = g_cancellable_connect (
ad->cancellable,
G_CALLBACK (autodiscover_cancelled_cb),
- g_object_ref (cnc),
+ g_object_ref (ad->cnc),
g_object_unref);
}
g_simple_async_result_set_op_res_gpointer (
simple, ad, (GDestroyNotify) autodiscover_data_free);
- /* Passing a NULL URL string returns NULL. */
- ad->msgs[0] = e_ews_get_msg_for_url (cnc, settings, url1, buf, &error);
- ad->msgs[1] = e_ews_get_msg_for_url (cnc, settings, url2, buf, NULL);
- ad->msgs[2] = e_ews_get_msg_for_url (cnc, settings, url3, buf, NULL);
- ad->msgs[3] = e_ews_get_msg_for_url (cnc, settings, url4, buf, NULL);
- ad->msgs[4] = e_ews_get_msg_for_url (cnc, settings, url5, buf, NULL);
-
- /* These have to be submitted only after they're both set in ad->msgs[]
- * or there will be races with fast completion */
- if (ad->msgs[0] != NULL)
- ews_connection_schedule_queue_message (cnc, ad->msgs[0], autodiscover_response_cb, g_object_ref (simple));
- if (ad->msgs[1] != NULL)
- ews_connection_schedule_queue_message (cnc, ad->msgs[1], autodiscover_response_cb, g_object_ref (simple));
- if (ad->msgs[2] != NULL)
- ews_connection_schedule_queue_message (cnc, ad->msgs[2], autodiscover_response_cb, g_object_ref (simple));
- if (ad->msgs[3] != NULL)
- ews_connection_schedule_queue_message (cnc, ad->msgs[3], autodiscover_response_cb, g_object_ref (simple));
- if (ad->msgs[4] != NULL)
- ews_connection_schedule_queue_message (cnc, ad->msgs[4], autodiscover_response_cb, g_object_ref (simple));
-
- xmlFreeDoc (doc);
- g_free (url1);
- g_free (url2);
- g_free (url3);
- g_free (url4);
+ host_url = camel_ews_settings_get_hosturl (settings);
- if (error && !ad->msgs[0] && !ad->msgs[1] && !ad->msgs[2] && !ad->msgs[3] && !ad->msgs[4]) {
+ if (!e_ews_discover_prepare_messages_and_send (simple, email_address, host_url, &error)) {
g_simple_async_result_take_error (simple, error);
g_simple_async_result_complete_in_idle (simple);
} else {
@@ -3735,7 +4060,7 @@ e_ews_connection_get_oal_list (EEwsConne
g_return_if_fail (E_IS_EWS_CONNECTION (cnc));
- soup_message = e_ews_get_msg_for_url (cnc, cnc->priv->settings, cnc->priv->uri, NULL, &error);
+ soup_message = e_ews_get_msg_for_url (cnc, cnc->priv->uri, NULL, &error);
simple = g_simple_async_result_new (
G_OBJECT (cnc), callback, user_data,
@@ -3856,7 +4181,7 @@ e_ews_connection_get_oal_detail (EEwsCon
g_return_if_fail (E_IS_EWS_CONNECTION (cnc));
- soup_message = e_ews_get_msg_for_url (cnc, cnc->priv->settings, cnc->priv->uri, NULL, &error);
+ soup_message = e_ews_get_msg_for_url (cnc, cnc->priv->uri, NULL, &error);
simple = g_simple_async_result_new (
G_OBJECT (cnc), callback, user_data,
@@ -4073,7 +4398,7 @@ e_ews_connection_download_oal_file (EEws
g_return_if_fail (E_IS_EWS_CONNECTION (cnc));
- soup_message = e_ews_get_msg_for_url (cnc, cnc->priv->settings, cnc->priv->uri, NULL, &error);
+ soup_message = e_ews_get_msg_for_url (cnc, cnc->priv->uri, NULL, &error);
simple = g_simple_async_result_new (
G_OBJECT (cnc), callback, user_data,

@ -0,0 +1,262 @@
diff -up evolution-ews-3.28.5/src/addressbook/CMakeLists.txt.birthday-date evolution-ews-3.28.5/src/addressbook/CMakeLists.txt
--- evolution-ews-3.28.5/src/addressbook/CMakeLists.txt.birthday-date 2018-07-30 16:01:00.000000000 +0200
+++ evolution-ews-3.28.5/src/addressbook/CMakeLists.txt 2019-10-23 14:13:13.158137514 +0200
@@ -45,6 +45,7 @@ target_compile_options(ebookbackendews P
${LIBEBOOK_CFLAGS}
${LIBEDATABOOK_CFLAGS}
${LIBEDATASERVER_CFLAGS}
+ ${LIBICAL_CFLAGS}
${MSPACK_CFLAGS}
${SOUP_CFLAGS}
)
@@ -60,6 +61,7 @@ target_include_directories(ebookbackende
${LIBEBOOK_INCLUDE_DIRS}
${LIBEDATABOOK_INCLUDE_DIRS}
${LIBEDATASERVER_INCLUDE_DIRS}
+ ${LIBICAL_INCLUDE_DIRS}
${MSPACK_INCLUDE_DIRS}
${SOUP_INCLUDE_DIRS}
)
@@ -70,6 +72,7 @@ target_link_libraries(ebookbackendews
${LIBEBOOK_LDFLAGS}
${LIBEDATABOOK_LDFLAGS}
${LIBEDATASERVER_LDFLAGS}
+ ${LIBICAL_LDFLAGS}
${MATH_LDFLAGS}
${MSPACK_LDFLAGS}
${SOUP_LDFLAGS}
diff -up evolution-ews-3.28.5/src/addressbook/e-book-backend-ews.c.birthday-date evolution-ews-3.28.5/src/addressbook/e-book-backend-ews.c
--- evolution-ews-3.28.5/src/addressbook/e-book-backend-ews.c.birthday-date 2019-10-23 14:04:31.100144733 +0200
+++ evolution-ews-3.28.5/src/addressbook/e-book-backend-ews.c 2019-10-23 14:15:41.719135459 +0200
@@ -37,6 +37,8 @@
#include <glib/gstdio.h>
#include <glib/gi18n-lib.h>
+#include <libical/ical.h>
+
#include <libedata-book/libedata-book.h>
#include "server/e-ews-item-change.h"
@@ -268,29 +270,36 @@ ebews_populate_nick_name (EBookBackendEw
}
static void
+ebews_populate_date_value (EBookBackendEws *bbews,
+ EContact *contact,
+ EContactField field,
+ time_t value)
+{
+ if (value > (time_t) 0) {
+ struct icaltimetype itt;
+
+ itt = icaltime_from_timet_with_zone (value, TRUE, icaltimezone_get_utc_timezone ());
+
+ if (icaltime_is_valid_time (itt) && !icaltime_is_null_time (itt)) {
+ EContactDate edate = { 0 };
+
+ edate.year = itt.year;
+ edate.month = itt.month;
+ edate.day = itt.day;
+
+ e_contact_set (contact, field, &edate);
+ }
+ }
+}
+
+static void
ebews_populate_birth_date (EBookBackendEws *bbews,
EContact *contact,
EEwsItem *item,
GCancellable *cancellable,
GError **error)
{
- time_t bdate;
- GDate date;
- EContactDate edate;
-
- bdate = e_ews_item_get_birthday (item);
-
- if (bdate) {
- g_date_clear (&date, 1);
- g_date_set_time_t (&date, bdate);
-
- edate.year = date.year;
- edate.month = date.month;
- edate.day = date.day;
-
- if (g_date_valid (&date))
- e_contact_set (contact, E_CONTACT_BIRTH_DATE, &edate);
- }
+ ebews_populate_date_value (bbews, contact, E_CONTACT_BIRTH_DATE, e_ews_item_get_birthday (item));
}
static void
@@ -300,23 +309,7 @@ ebews_populate_anniversary (EBookBackend
GCancellable *cancellable,
GError **error)
{
- time_t bdate;
- GDate date;
- EContactDate edate;
-
- bdate = e_ews_item_get_wedding_anniversary (item);
-
- if (bdate) {
- g_date_clear (&date, 1);
- g_date_set_time_t (&date, bdate);
-
- edate.year = date.year;
- edate.month = date.month;
- edate.day = date.day;
-
- if (g_date_valid (&date))
- e_contact_set (contact, E_CONTACT_ANNIVERSARY, &edate);
- }
+ ebews_populate_date_value (bbews, contact, E_CONTACT_ANNIVERSARY, e_ews_item_get_wedding_anniversary (item));
}
static EContactPhoto *
@@ -600,34 +593,41 @@ ebews_set_full_name (ESoapMessage *msg,
e_contact_name_free (name);
}
-/* TODO Set birth and anniversary dates */
static void
-ebews_set_birth_date (ESoapMessage *message,
- EContact *contact)
+ebews_set_date_value (ESoapMessage *message,
+ EContact *contact,
+ EContactField field,
+ const gchar *element_name)
{
EContactDate *date;
- gchar *birthday;
+ gchar *value;
- date = e_contact_get (contact, E_CONTACT_BIRTH_DATE);
+ date = e_contact_get (contact, field);
if (!date)
return;
- birthday = g_strdup_printf (
- "%04d-%02d-%02dT00:00:00",
+ value = g_strdup_printf ("%04d-%02d-%02dT00:00:00Z",
date->year, date->month, date->day);
- e_ews_message_write_string_parameter (message, "Birthday", NULL, birthday);
+ e_ews_message_write_string_parameter (message, element_name, NULL, value);
- g_free (birthday);
+ e_contact_date_free (date);
+ g_free (value);
+}
+static void
+ebews_set_birth_date (ESoapMessage *message,
+ EContact *contact)
+{
+ ebews_set_date_value (message, contact, E_CONTACT_BIRTH_DATE, "Birthday");
}
static void
ebews_set_anniversary (ESoapMessage *message,
EContact *contact)
{
-
+ ebews_set_date_value (message, contact, E_CONTACT_ANNIVERSARY, "WeddingAnniversary");
}
static void
@@ -838,30 +838,33 @@ ebews_set_full_name_changes (EBookBacken
}
static void
-ebews_set_birth_date_changes (EBookBackendEws *bbews,
- ESoapMessage *message,
+ebews_set_date_value_changes (ESoapMessage *message,
EContact *new,
EContact *old,
- gchar **out_new_change_key,
- GCancellable *cancellable,
- GError **error)
+ EContactField field,
+ const gchar *element_name)
{
EContactDate *new_date, *old_date;
- gchar *birthday;
if (!message)
return;
- new_date = e_contact_get (new, E_CONTACT_BIRTH_DATE);
- old_date = e_contact_get (old, E_CONTACT_BIRTH_DATE);
+ new_date = e_contact_get (new, field);
+ old_date = e_contact_get (old, field);
if (!e_contact_date_equal (new_date, old_date)) {
- birthday = g_strdup_printf (
- "%04d-%02d-%02dT00:00:00",
- new_date->year, new_date->month, new_date->day);
+ if (new_date) {
+ gchar *value;
+
+ value = g_strdup_printf ("%04d-%02d-%02dT00:00:00Z",
+ new_date->year, new_date->month, new_date->day);
+
+ convert_contact_property_to_updatexml (message, element_name, value, "contacts", NULL, NULL);
- convert_contact_property_to_updatexml (message, "Birthday", birthday, "contacts", NULL, NULL);
- g_free (birthday);
+ g_free (value);
+ } else {
+ e_ews_message_add_delete_item_field (message, element_name, "contacts");
+ }
}
e_contact_date_free (new_date);
@@ -869,6 +872,18 @@ ebews_set_birth_date_changes (EBookBacke
}
static void
+ebews_set_birth_date_changes (EBookBackendEws *bbews,
+ ESoapMessage *message,
+ EContact *new,
+ EContact *old,
+ gchar **out_new_change_key,
+ GCancellable *cancellable,
+ GError **error)
+{
+ ebews_set_date_value_changes (message, new, old, E_CONTACT_BIRTH_DATE, "Birthday");
+}
+
+static void
ebews_set_anniversary_changes (EBookBackendEws *bbews,
ESoapMessage *message,
EContact *new,
@@ -877,7 +892,7 @@ ebews_set_anniversary_changes (EBookBack
GCancellable *cancellable,
GError **error)
{
-
+ ebews_set_date_value_changes (message, new, old, E_CONTACT_ANNIVERSARY, "WeddingAnniversary");
}
static void
@@ -1373,7 +1388,7 @@ static const struct field_element_mappin
{ E_CONTACT_SPOUSE, ELEMENT_TYPE_SIMPLE, "SpouseName", e_ews_item_get_spouse_name},
{ E_CONTACT_FAMILY_NAME, ELEMENT_TYPE_SIMPLE, "Surname", e_ews_item_get_surname},
{ E_CONTACT_GIVEN_NAME, ELEMENT_TYPE_COMPLEX, "GivenName", NULL, ebews_populate_givenname, ebews_set_givenname, ebews_set_givenname_changes},
- { E_CONTACT_BIRTH_DATE, ELEMENT_TYPE_COMPLEX, "WeddingAnniversary", NULL, ebews_populate_anniversary, ebews_set_anniversary, ebews_set_anniversary_changes },
+ { E_CONTACT_ANNIVERSARY, ELEMENT_TYPE_COMPLEX, "WeddingAnniversary", NULL, ebews_populate_anniversary, ebews_set_anniversary, ebews_set_anniversary_changes },
{ E_CONTACT_PHOTO, ELEMENT_TYPE_COMPLEX, "Photo", NULL, ebews_populate_photo, ebews_set_photo, ebews_set_photo_changes },
/* Should take of uid and changekey (REV) */
@@ -3515,6 +3530,7 @@ ebb_ews_get_backend_property (EBookBacke
e_contact_field_name (E_CONTACT_ADDRESS_WORK),
e_contact_field_name (E_CONTACT_ADDRESS_HOME),
e_contact_field_name (E_CONTACT_ADDRESS_OTHER),
+ e_contact_field_name (E_CONTACT_ANNIVERSARY),
e_contact_field_name (E_CONTACT_BIRTH_DATE),
e_contact_field_name (E_CONTACT_NOTE),
e_contact_field_name (E_CONTACT_PHOTO),

@ -0,0 +1,44 @@
diff -up evolution-data-server-3.28.5/cmake/modules/PrintableOptions.cmake.cmake-variable-name-comparison evolution-data-server-3.28.5/cmake/modules/PrintableOptions.cmake
--- evolution-data-server-3.28.5/cmake/modules/PrintableOptions.cmake.cmake-variable-name-comparison 2021-06-16 16:45:58.554763738 +0200
+++ evolution-data-server-3.28.5/cmake/modules/PrintableOptions.cmake 2021-06-16 16:47:13.343021509 +0200
@@ -19,32 +19,32 @@
# prints all the build options previously added with the above functions
macro(add_printable_variable_bare _name)
- if(_name STREQUAL "")
+ if("${_name}" STREQUAL "")
message(FATAL_ERROR "variable name cannot be empty")
- endif(_name STREQUAL "")
+ endif("${_name}" STREQUAL "")
list(APPEND _printable_options ${_name})
endmacro()
macro(add_printable_option _name _description _default_value)
- if(_name STREQUAL "")
+ if("${_name}" STREQUAL "")
message(FATAL_ERROR "option name cannot be empty")
- endif(_name STREQUAL "")
+ endif("${_name}" STREQUAL "")
option(${_name} ${_description} ${_default_value})
add_printable_variable_bare(${_name})
endmacro()
macro(add_printable_variable _name _description _default_value)
- if(_name STREQUAL "")
+ if("${_name}" STREQUAL "")
message(FATAL_ERROR "variable name cannot be empty")
- endif(_name STREQUAL "")
+ endif("${_name}" STREQUAL "")
set(${_name} ${_default_value} CACHE STRING ${_description})
add_printable_variable_bare(${_name})
endmacro()
macro(add_printable_variable_path _name _description _default_value)
- if(_name STREQUAL "")
+ if("${_name}" STREQUAL "")
message(FATAL_ERROR "path variable name cannot be empty")
- endif(_name STREQUAL "")
+ endif("${_name}" STREQUAL "")
set(${_name} ${_default_value} CACHE PATH ${_description})
add_printable_variable_bare(${_name})
endmacro()

@ -0,0 +1,32 @@
diff -up evolution-ews-3.28.5/src/addressbook/e-book-backend-ews.c.contact-country-forgotten evolution-ews-3.28.5/src/addressbook/e-book-backend-ews.c
--- evolution-ews-3.28.5/src/addressbook/e-book-backend-ews.c.contact-country-forgotten 2018-07-30 16:01:00.000000000 +0200
+++ evolution-ews-3.28.5/src/addressbook/e-book-backend-ews.c 2018-09-27 18:31:47.485039155 +0200
@@ -700,6 +700,7 @@ add_physical_address (ESoapMessage *msg,
e_ews_message_write_string_parameter (msg, "Street", NULL, contact_addr->street);
e_ews_message_write_string_parameter (msg, "City", NULL, contact_addr->locality);
e_ews_message_write_string_parameter (msg, "State", NULL, contact_addr->region);
+ e_ews_message_write_string_parameter (msg, "CountryOrRegion", NULL, contact_addr->country);
e_ews_message_write_string_parameter (msg, "PostalCode", NULL, contact_addr->code);
e_soap_message_end_element (msg);
@@ -1191,6 +1192,8 @@ compare_address (ESoapMessage *message,
convert_indexed_contact_property_to_updatexml_physical_address (message, "PhysicalAddress", "City", new_address->locality, "contacts", "PhysicalAddresses", key);
if (set || g_strcmp0 (new_address->region, old_address->region) != 0)
convert_indexed_contact_property_to_updatexml_physical_address (message, "PhysicalAddress", "State", new_address->region, "contacts", "PhysicalAddresses", key);
+ if (set || g_strcmp0 (new_address->country, old_address->country) != 0)
+ convert_indexed_contact_property_to_updatexml_physical_address (message, "PhysicalAddress", "CountryOrRegion", new_address->country, "contacts", "PhysicalAddresses", key);
if (set || g_strcmp0 (new_address->code, old_address->code) != 0)
convert_indexed_contact_property_to_updatexml_physical_address (message, "PhysicalAddress", "PostalCode", new_address->code, "contacts", "PhysicalAddresses", key);
diff -up evolution-ews-3.28.5/src/server/e-ews-item.c.contact-country-forgotten evolution-ews-3.28.5/src/server/e-ews-item.c
--- evolution-ews-3.28.5/src/server/e-ews-item.c.contact-country-forgotten 2018-07-30 16:01:00.000000000 +0200
+++ evolution-ews-3.28.5/src/server/e-ews-item.c 2018-09-27 18:31:47.485039155 +0200
@@ -686,7 +686,7 @@ ews_get_physical_address (ESoapParameter
if (subparam)
address->state = e_soap_parameter_get_string_value (subparam);
- subparam = e_soap_parameter_get_first_child_by_name (param, "Country");
+ subparam = e_soap_parameter_get_first_child_by_name (param, "CountryOrRegion");
if (subparam)
address->country = e_soap_parameter_get_string_value (subparam);

@ -0,0 +1,782 @@
diff -up evolution-ews-3.28.5/src/addressbook/e-book-backend-ews.c.cve-2019-3890 evolution-ews-3.28.5/src/addressbook/e-book-backend-ews.c
--- evolution-ews-3.28.5/src/addressbook/e-book-backend-ews.c.cve-2019-3890 2019-04-15 09:43:49.672771516 +0200
+++ evolution-ews-3.28.5/src/addressbook/e-book-backend-ews.c 2019-04-15 09:43:49.683771516 +0200
@@ -2901,7 +2901,8 @@ ebb_ews_connect_sync (EBookMetaBackend *
bbews->priv->cnc, "proxy-resolver",
G_BINDING_SYNC_CREATE);
- *out_auth_result = e_ews_connection_try_credentials_sync (bbews->priv->cnc, credentials, cancellable, error);
+ *out_auth_result = e_ews_connection_try_credentials_sync (bbews->priv->cnc, credentials, NULL,
+ out_certificate_pem, out_certificate_errors, cancellable, error);
if (*out_auth_result == E_SOURCE_AUTHENTICATION_ACCEPTED) {
ESource *source = e_backend_get_source (E_BACKEND (bbews));
diff -up evolution-ews-3.28.5/src/calendar/e-cal-backend-ews.c.cve-2019-3890 evolution-ews-3.28.5/src/calendar/e-cal-backend-ews.c
--- evolution-ews-3.28.5/src/calendar/e-cal-backend-ews.c.cve-2019-3890 2019-04-15 09:43:49.676771516 +0200
+++ evolution-ews-3.28.5/src/calendar/e-cal-backend-ews.c 2019-04-15 09:43:49.684771516 +0200
@@ -1394,7 +1394,8 @@ ecb_ews_connect_sync (ECalMetaBackend *m
cbews->priv->cnc, "proxy-resolver",
G_BINDING_SYNC_CREATE);
- *out_auth_result = e_ews_connection_try_credentials_sync (cbews->priv->cnc, credentials, cancellable, error);
+ *out_auth_result = e_ews_connection_try_credentials_sync (cbews->priv->cnc, credentials, NULL,
+ out_certificate_pem, out_certificate_errors, cancellable, error);
if (*out_auth_result == E_SOURCE_AUTHENTICATION_ACCEPTED) {
ESource *source = e_backend_get_source (E_BACKEND (cbews));
diff -up evolution-ews-3.28.5/src/camel/camel-ews-store.c.cve-2019-3890 evolution-ews-3.28.5/src/camel/camel-ews-store.c
--- evolution-ews-3.28.5/src/camel/camel-ews-store.c.cve-2019-3890 2018-07-30 16:01:00.000000000 +0200
+++ evolution-ews-3.28.5/src/camel/camel-ews-store.c 2019-04-15 09:43:49.684771516 +0200
@@ -1831,6 +1831,8 @@ ews_authenticate_sync (CamelService *ser
const gchar *password;
gchar *hosturl;
gchar *old_sync_state = NULL, *new_sync_state = NULL;
+ gchar *certificate_pem = NULL;
+ GTlsCertificateFlags certificate_errors = 0;
GError *local_error = NULL;
ews_store = CAMEL_EWS_STORE (service);
@@ -1959,6 +1961,18 @@ ews_authenticate_sync (CamelService *ser
g_slist_free_full (created_folder_ids, g_free);
+ if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED) &&
+ e_ews_connection_get_ssl_error_details (connection, &certificate_pem, &certificate_errors)) {
+ source = e_ews_connection_get_source (connection);
+
+ if (source) {
+ e_source_emit_credentials_required (source, E_SOURCE_CREDENTIALS_REASON_SSL_FAILED,
+ certificate_pem, certificate_errors, local_error);
+ }
+
+ g_free (certificate_pem);
+ }
+
if (local_error == NULL) {
result = CAMEL_AUTHENTICATION_ACCEPTED;
} else if (g_error_matches (local_error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_AUTHENTICATION_FAILED)) {
diff -up evolution-ews-3.28.5/src/collection/e-ews-backend.c.cve-2019-3890 evolution-ews-3.28.5/src/collection/e-ews-backend.c
--- evolution-ews-3.28.5/src/collection/e-ews-backend.c.cve-2019-3890 2019-04-15 09:43:49.679771516 +0200
+++ evolution-ews-3.28.5/src/collection/e-ews-backend.c 2019-04-15 09:43:49.685771516 +0200
@@ -727,6 +727,15 @@ ews_backend_constructed (GObject *object
/* Reset the connectable, it steals data from Authentication extension,
where is written incorrect address */
e_backend_set_connectable (backend, NULL);
+
+ /* Eventually unset temporary SSL trust, but only once, when the process started.
+ It might bee too often anywhere lease (like in the authenticate callback) */
+ if (e_source_has_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND)) {
+ ESourceWebdav *webdav_extension;
+
+ webdav_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);
+ e_source_webdav_unset_temporary_ssl_trust (webdav_extension);
+ }
}
static void
@@ -930,7 +939,7 @@ ews_backend_create_resource_sync (EColle
}
if (!success) {
- connection = e_ews_backend_ref_connection_sync (E_EWS_BACKEND (backend), NULL, cancellable, error);
+ connection = e_ews_backend_ref_connection_sync (E_EWS_BACKEND (backend), NULL, NULL, NULL, cancellable, error);
if (connection == NULL)
return FALSE;
@@ -1037,7 +1046,7 @@ ews_backend_delete_resource_sync (EColle
const gchar *extension_name;
gboolean success = FALSE;
- connection = e_ews_backend_ref_connection_sync (E_EWS_BACKEND (backend), NULL, cancellable, error);
+ connection = e_ews_backend_ref_connection_sync (E_EWS_BACKEND (backend), NULL, NULL, NULL, cancellable, error);
if (connection == NULL)
return FALSE;
@@ -1142,7 +1151,7 @@ ews_backend_authenticate_sync (EBackend
ews_backend->priv->credentials = e_named_parameters_new_clone (credentials);
g_mutex_unlock (&ews_backend->priv->connection_lock);
- connection = e_ews_backend_ref_connection_sync (ews_backend, &result, cancellable, error);
+ connection = e_ews_backend_ref_connection_sync (ews_backend, &result, out_certificate_pem, out_certificate_errors, cancellable, error);
g_clear_object (&connection);
if (result == E_SOURCE_AUTHENTICATION_ACCEPTED) {
@@ -1223,7 +1232,7 @@ ews_backend_ref_connection_thread (GSimp
EEwsConnection *connection;
GError *error = NULL;
- connection = e_ews_backend_ref_connection_sync (E_EWS_BACKEND (object), NULL, cancellable, &error);
+ connection = e_ews_backend_ref_connection_sync (E_EWS_BACKEND (object), NULL, NULL, NULL, cancellable, &error);
/* Sanity check. */
g_return_if_fail (
@@ -1241,6 +1250,8 @@ ews_backend_ref_connection_thread (GSimp
EEwsConnection *
e_ews_backend_ref_connection_sync (EEwsBackend *backend,
ESourceAuthenticationResult *result,
+ gchar **out_certificate_pem,
+ GTlsCertificateFlags *out_certificate_errors,
GCancellable *cancellable,
GError **error)
{
@@ -1272,7 +1283,8 @@ e_ews_backend_ref_connection_sync (EEwsB
connection, "proxy-resolver",
G_BINDING_SYNC_CREATE);
- local_result = e_ews_connection_try_credentials_sync (connection, backend->priv->credentials, cancellable, error);
+ local_result = e_ews_connection_try_credentials_sync (connection, backend->priv->credentials, NULL,
+ out_certificate_pem, out_certificate_errors, cancellable, error);
if (result)
*result = local_result;
@@ -1413,7 +1425,7 @@ e_ews_backend_sync_folders_sync (EEwsBac
return TRUE;
}
- connection = e_ews_backend_ref_connection_sync (backend, NULL, cancellable, error);
+ connection = e_ews_backend_ref_connection_sync (backend, NULL, NULL, NULL, cancellable, error);
if (connection == NULL) {
backend->priv->need_update_folders = TRUE;
diff -up evolution-ews-3.28.5/src/collection/e-ews-backend.h.cve-2019-3890 evolution-ews-3.28.5/src/collection/e-ews-backend.h
--- evolution-ews-3.28.5/src/collection/e-ews-backend.h.cve-2019-3890 2018-07-30 16:01:00.000000000 +0200
+++ evolution-ews-3.28.5/src/collection/e-ews-backend.h 2019-04-15 09:43:49.685771516 +0200
@@ -63,6 +63,8 @@ EEwsConnection *
e_ews_backend_ref_connection_sync
(EEwsBackend *backend,
ESourceAuthenticationResult *result,
+ gchar **out_certificate_pem,
+ GTlsCertificateFlags *out_certificate_errors,
GCancellable *cancellable,
GError **error);
void e_ews_backend_ref_connection (EEwsBackend *backend,
diff -up evolution-ews-3.28.5/src/configuration/e-ews-config-lookup.c.cve-2019-3890 evolution-ews-3.28.5/src/configuration/e-ews-config-lookup.c
--- evolution-ews-3.28.5/src/configuration/e-ews-config-lookup.c.cve-2019-3890 2018-07-30 16:01:00.000000000 +0200
+++ evolution-ews-3.28.5/src/configuration/e-ews-config-lookup.c 2019-04-15 09:43:49.685771516 +0200
@@ -344,9 +344,54 @@ ews_config_lookup_worker_run (EConfigLoo
if (password) {
const gchar *servers;
+ gchar *certificate_host = NULL;
+ gchar *certificate_pem = NULL;
+ GTlsCertificateFlags certificate_errors = 0;
+ GError *local_error = NULL;
+
+ if (e_named_parameters_exists (params, E_CONFIG_LOOKUP_PARAM_CERTIFICATE_PEM) &&
+ e_named_parameters_exists (params, E_CONFIG_LOOKUP_PARAM_CERTIFICATE_TRUST) &&
+ e_named_parameters_exists (params, E_CONFIG_LOOKUP_PARAM_CERTIFICATE_HOST)) {
+ GTlsCertificate *certificate;
+ const gchar *param_certificate_pem;
+
+ param_certificate_pem = e_named_parameters_get (params, E_CONFIG_LOOKUP_PARAM_CERTIFICATE_PEM);
+ certificate = g_tls_certificate_new_from_pem (param_certificate_pem, -1, NULL);
+
+ if (certificate) {
+ ETrustPromptResponse trust_response;
+
+ trust_response = e_config_lookup_decode_certificate_trust (
+ e_named_parameters_get (params, E_CONFIG_LOOKUP_PARAM_CERTIFICATE_TRUST));
+
+ if (trust_response != E_TRUST_PROMPT_RESPONSE_UNKNOWN) {
+ ESourceWebdav *webdav_extension;
+
+ webdav_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);
+ e_source_webdav_update_ssl_trust (webdav_extension,
+ e_named_parameters_get (params, E_CONFIG_LOOKUP_PARAM_CERTIFICATE_HOST),
+ certificate, trust_response);
+ }
+
+ g_object_unref (certificate);
+ }
+ }
- if (e_ews_autodiscover_ws_url_sync (source, ews_settings, email_address, password, cancellable, NULL)) {
+ if (e_ews_autodiscover_ws_url_sync (source, ews_settings, email_address, password, &certificate_pem, &certificate_errors, cancellable, &local_error)) {
ews_config_lookup_worker_result_from_settings (lookup_worker, config_lookup, email_address, ews_settings, params);
+ } else if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED)) {
+ const gchar *hosturl;
+ SoupURI *suri;
+
+ hosturl = camel_ews_settings_get_hosturl (ews_settings);
+ suri = soup_uri_new (hosturl);
+ if (suri) {
+ certificate_host = g_strdup (soup_uri_get_host (suri));
+
+ soup_uri_free (suri);
+ }
+ } else {
+ g_clear_error (&local_error);
}
servers = e_named_parameters_get (params, E_CONFIG_LOOKUP_PARAM_SERVERS);
@@ -357,7 +402,7 @@ ews_config_lookup_worker_run (EConfigLoo
servers_strv = g_strsplit (servers, ";", 0);
- for (ii = 0; servers_strv && servers_strv[ii] && !g_cancellable_is_cancelled (cancellable); ii++) {
+ for (ii = 0; servers_strv && servers_strv[ii] && !g_cancellable_is_cancelled (cancellable) && !local_error; ii++) {
const gchar *server = servers_strv[ii];
gchar *tmp = NULL;
@@ -368,8 +413,21 @@ ews_config_lookup_worker_run (EConfigLoo
camel_ews_settings_set_hosturl (ews_settings, server);
- if (e_ews_autodiscover_ws_url_sync (source, ews_settings, email_address, password, cancellable, NULL)) {
+ if (e_ews_autodiscover_ws_url_sync (source, ews_settings, email_address, password, &certificate_pem, &certificate_errors, cancellable, &local_error)) {
ews_config_lookup_worker_result_from_settings (lookup_worker, config_lookup, email_address, ews_settings, params);
+ } else if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED)) {
+ const gchar *hosturl;
+ SoupURI *suri;
+
+ hosturl = camel_ews_settings_get_hosturl (ews_settings);
+ suri = soup_uri_new (hosturl);
+ if (suri) {
+ certificate_host = g_strdup (soup_uri_get_host (suri));
+
+ soup_uri_free (suri);
+ }
+ } else {
+ g_clear_error (&local_error);
}
g_free (tmp);
@@ -378,7 +436,31 @@ ews_config_lookup_worker_run (EConfigLoo
g_strfreev (servers_strv);
}
- if (out_restart_params)
+ if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED) &&
+ certificate_pem && *certificate_pem && certificate_errors) {
+ gchar *description = e_trust_prompt_describe_certificate_errors (certificate_errors);
+
+ if (description) {
+ g_set_error_literal (error, E_CONFIG_LOOKUP_WORKER_ERROR,
+ E_CONFIG_LOOKUP_WORKER_ERROR_CERTIFICATE, description);
+
+ g_free (description);
+
+ if (out_restart_params) {
+ if (!*out_restart_params)
+ *out_restart_params = e_named_parameters_new_clone (params);
+
+ e_named_parameters_set (*out_restart_params, E_CONFIG_LOOKUP_PARAM_CERTIFICATE_PEM, certificate_pem);
+ e_named_parameters_set (*out_restart_params, E_CONFIG_LOOKUP_PARAM_CERTIFICATE_HOST, certificate_host);
+ }
+ }
+ }
+
+ g_clear_error (&local_error);
+ g_free (certificate_host);
+ g_free (certificate_pem);
+
+ if (out_restart_params && !*out_restart_params)
*out_restart_params = e_named_parameters_new_clone (params);
}
diff -up evolution-ews-3.28.5/src/configuration/e-ews-config-utils.c.cve-2019-3890 evolution-ews-3.28.5/src/configuration/e-ews-config-utils.c
--- evolution-ews-3.28.5/src/configuration/e-ews-config-utils.c.cve-2019-3890 2018-07-30 16:01:00.000000000 +0200
+++ evolution-ews-3.28.5/src/configuration/e-ews-config-utils.c 2019-04-15 09:43:49.686771516 +0200
@@ -317,7 +317,7 @@ ews_config_utils_try_credentials_sync (E
if (data->try_credentials_func)
auth_result = data->try_credentials_func (data->conn, credentials, data->user_data, cancellable, error);
else
- auth_result = e_ews_connection_try_credentials_sync (data->conn, credentials, cancellable, error);
+ auth_result = e_ews_connection_try_credentials_sync (data->conn, credentials, NULL, NULL, NULL, cancellable, error);
if (auth_result == E_SOURCE_AUTHENTICATION_ACCEPTED) {
*out_authenticated = TRUE;
@@ -377,7 +377,7 @@ e_ews_config_utils_open_connection_for (
if (try_credentials_func)
result = try_credentials_func (conn, NULL, user_data, cancellable, &local_error);
else
- result = e_ews_connection_try_credentials_sync (conn, NULL, cancellable, &local_error);
+ result = e_ews_connection_try_credentials_sync (conn, NULL, NULL, NULL, NULL, cancellable, &local_error);
if (result != E_SOURCE_AUTHENTICATION_ACCEPTED) {
g_clear_object (&conn);
diff -up evolution-ews-3.28.5/src/configuration/e-mail-config-ews-autodiscover.c.cve-2019-3890 evolution-ews-3.28.5/src/configuration/e-mail-config-ews-autodiscover.c
--- evolution-ews-3.28.5/src/configuration/e-mail-config-ews-autodiscover.c.cve-2019-3890 2018-07-30 16:01:00.000000000 +0200
+++ evolution-ews-3.28.5/src/configuration/e-mail-config-ews-autodiscover.c 2019-04-15 09:43:49.686771516 +0200
@@ -45,6 +45,8 @@ struct _AsyncContext {
ESource *source;
CamelEwsSettings *ews_settings;
gchar *email_address;
+ gchar *certificate_pem;
+ GTlsCertificateFlags certificate_errors;
};
enum {
@@ -67,6 +69,7 @@ async_context_free (gpointer ptr)
g_clear_object (&async_context->source);
g_clear_object (&async_context->ews_settings);
g_free (async_context->email_address);
+ g_free (async_context->certificate_pem);
g_slice_free (AsyncContext, async_context);
}
@@ -87,6 +90,9 @@ mail_config_ews_autodiscover_finish (EMa
}
static void
+mail_config_ews_autodiscover_run (EMailConfigEwsAutodiscover *autodiscover);
+
+static void
mail_config_ews_autodiscover_run_cb (GObject *source_object,
GAsyncResult *result,
gpointer user_data)
@@ -111,17 +117,62 @@ mail_config_ews_autodiscover_run_cb (GOb
g_object_thaw_notify (G_OBJECT (settings));
if (e_activity_handle_cancellation (async_context->activity, error)) {
- g_error_free (error);
+ /* Do nothing, just free the error below */
+ } else if (g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED) &&
+ async_context->certificate_pem && *async_context->certificate_pem && async_context->certificate_errors) {
+ ETrustPromptResponse response;
+ GtkWidget *parent;
+ const gchar *host;
+
+ parent = gtk_widget_get_toplevel (GTK_WIDGET (autodiscover));
+ if (!GTK_IS_WINDOW (parent))
+ parent = NULL;
+
+ host = camel_network_settings_get_host (CAMEL_NETWORK_SETTINGS (settings));
+
+ response = e_trust_prompt_run_modal (parent ? GTK_WINDOW (parent) : NULL,
+ E_SOURCE_EXTENSION_COLLECTION, _("Exchange Web Services"),
+ host, async_context->certificate_pem, async_context->certificate_errors,
+ error->message);
+
+ g_clear_error (&error);
+
+ if (response != E_TRUST_PROMPT_RESPONSE_UNKNOWN) {
+ GTlsCertificate *certificate;
+
+ certificate = g_tls_certificate_new_from_pem (async_context->certificate_pem, -1, &error);
+ if (certificate) {
+ ESourceWebdav *extension_webdav;
+
+ extension_webdav = e_source_get_extension (async_context->source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);
+
+ e_source_webdav_update_ssl_trust (extension_webdav, host, certificate, response);
+
+ g_object_unref (certificate);
+ }
+
+ if (error) {
+ e_alert_submit (
+ alert_sink,
+ "ews:autodiscovery-error",
+ error->message, NULL);
+ }
+ }
+ if (response == E_TRUST_PROMPT_RESPONSE_ACCEPT ||
+ response == E_TRUST_PROMPT_RESPONSE_ACCEPT_TEMPORARILY) {
+ mail_config_ews_autodiscover_run (autodiscover);
+ }
} else if (error != NULL) {
e_alert_submit (
alert_sink,
"ews:autodiscovery-error",
error->message, NULL);
- g_error_free (error);
}
gtk_widget_set_sensitive (GTK_WIDGET (autodiscover), TRUE);
+
+ g_clear_error (&error);
}
static gboolean
@@ -141,6 +192,7 @@ mail_config_ews_autodiscover_sync (ECred
async_context->ews_settings, async_context->email_address,
credentials && e_named_parameters_get (credentials, E_SOURCE_CREDENTIAL_PASSWORD) ?
e_named_parameters_get (credentials, E_SOURCE_CREDENTIAL_PASSWORD) : "",
+ &async_context->certificate_pem, &async_context->certificate_errors,
cancellable, &local_error);
if (local_error == NULL) {
@@ -173,6 +225,7 @@ mail_config_ews_autodiscover_run_thread
if (without_password) {
success = e_ews_autodiscover_ws_url_sync (async_context->source,
async_context->ews_settings, async_context->email_address, "",
+ &async_context->certificate_pem, &async_context->certificate_errors,
cancellable, &local_error);
}
@@ -236,6 +289,8 @@ mail_config_ews_autodiscover_run (EMailC
async_context->source = g_object_ref (source);
async_context->ews_settings = g_object_ref (settings);
async_context->email_address = g_strdup (e_mail_config_service_page_get_email_address (page));
+ async_context->certificate_pem = NULL;
+ async_context->certificate_errors = 0;
/*
* The GTask will be run in a new thread, which will invoke
diff -up evolution-ews-3.28.5/src/server/e-ews-connection.c.cve-2019-3890 evolution-ews-3.28.5/src/server/e-ews-connection.c
--- evolution-ews-3.28.5/src/server/e-ews-connection.c.cve-2019-3890 2018-07-30 16:01:00.000000000 +0200
+++ evolution-ews-3.28.5/src/server/e-ews-connection.c 2019-04-15 09:43:49.689771516 +0200
@@ -111,6 +111,10 @@ struct _EEwsConnectionPrivate {
/* Set to TRUE when this connection had been disconnected and cannot be used anymore */
gboolean disconnected_flag;
+
+ gboolean ssl_info_set;
+ gchar *ssl_certificate_pem;
+ GTlsCertificateFlags ssl_certificate_errors;
};
enum {
@@ -836,6 +840,37 @@ ews_connection_credentials_failed (EEwsC
return expired;
}
+static void
+ews_connection_check_ssl_error (EEwsConnection *connection,
+ SoupMessage *message)
+{
+ g_return_if_fail (E_IS_EWS_CONNECTION (connection));
+ g_return_if_fail (SOUP_IS_MESSAGE (message));
+
+ if (message->status_code == SOUP_STATUS_SSL_FAILED) {
+ GTlsCertificate *certificate = NULL;
+
+ g_mutex_lock (&connection->priv->property_lock);
+
+ g_clear_pointer (&connection->priv->ssl_certificate_pem, g_free);
+ connection->priv->ssl_info_set = FALSE;
+
+ g_object_get (G_OBJECT (message),
+ "tls-certificate", &certificate,
+ "tls-errors", &connection->priv->ssl_certificate_errors,
+ NULL);
+
+ if (certificate) {
+ g_object_get (certificate, "certificate-pem", &connection->priv->ssl_certificate_pem, NULL);
+ connection->priv->ssl_info_set = TRUE;
+
+ g_object_unref (certificate);
+ }
+
+ g_mutex_unlock (&connection->priv->property_lock);
+ }
+}
+
/* Response callbacks */
static void
@@ -852,8 +887,15 @@ ews_response_cb (SoupSession *session,
if (g_cancellable_is_cancelled (enode->cancellable))
goto exit;
+ ews_connection_check_ssl_error (enode->cnc, msg);
+
if (ews_connection_credentials_failed (enode->cnc, msg, enode->simple)) {
goto exit;
+ } else if (msg->status_code == SOUP_STATUS_SSL_FAILED) {
+ g_simple_async_result_set_error (
+ enode->simple, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED,
+ "%s", msg->reason_phrase);
+ goto exit;
} else if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) {
if (msg->response_headers) {
const gchar *diagnostics;
@@ -1855,6 +1897,9 @@ ews_connection_constructed (GObject *obj
cnc->priv->soup_thread = g_thread_new (NULL, e_ews_soup_thread, cnc);
cnc->priv->soup_session = soup_session_async_new_with_options (
+ SOUP_SESSION_TIMEOUT, 90,
+ SOUP_SESSION_SSL_STRICT, TRUE,
+ SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, TRUE,
SOUP_SESSION_ASYNC_CONTEXT, cnc->priv->soup_context,
NULL);
@@ -1971,6 +2016,7 @@ ews_connection_finalize (GObject *object
g_free (priv->email);
g_free (priv->hash_key);
g_free (priv->impersonate_user);
+ g_free (priv->ssl_certificate_pem);
g_clear_object (&priv->bearer_auth);
@@ -2557,10 +2603,15 @@ e_ews_connection_update_credentials (EEw
ESourceAuthenticationResult
e_ews_connection_try_credentials_sync (EEwsConnection *cnc,
const ENamedParameters *credentials,
+ ESource *use_source,
+ gchar **out_certificate_pem,
+ GTlsCertificateFlags *out_certificate_errors,
GCancellable *cancellable,
GError **error)
{
ESourceAuthenticationResult result;
+ ESource *source;
+ gboolean de_set_source;
EwsFolderId *fid = NULL;
GSList *ids = NULL;
GError *local_error = NULL;
@@ -2574,14 +2625,31 @@ e_ews_connection_try_credentials_sync (E
fid->is_distinguished_id = TRUE;
ids = g_slist_append (ids, fid);
+ source = e_ews_connection_get_source (cnc);
+ if (use_source && use_source != source) {
+ cnc->priv->source = g_object_ref (use_source);
+ de_set_source = TRUE;
+ } else {
+ source = NULL;
+ de_set_source = FALSE;
+ }
+
e_ews_connection_get_folder_sync (
cnc, EWS_PRIORITY_MEDIUM, "Default",
NULL, ids, NULL, cancellable, &local_error);
+ if (de_set_source) {
+ g_clear_object (&cnc->priv->source);
+ cnc->priv->source = source;
+ }
+
g_slist_free_full (ids, (GDestroyNotify) e_ews_folder_id_free);
if (local_error == NULL) {
result = E_SOURCE_AUTHENTICATION_ACCEPTED;
+ } else if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED) &&
+ e_ews_connection_get_ssl_error_details (cnc, out_certificate_pem, out_certificate_errors)) {
+ result = E_SOURCE_AUTHENTICATION_ERROR_SSL_FAILED;
} else {
gboolean auth_failed;
@@ -2618,6 +2686,29 @@ e_ews_connection_get_source (EEwsConnect
return cnc->priv->source;
}
+gboolean
+e_ews_connection_get_ssl_error_details (EEwsConnection *cnc,
+ gchar **out_certificate_pem,
+ GTlsCertificateFlags *out_certificate_errors)
+{
+ g_return_val_if_fail (E_IS_EWS_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (out_certificate_pem != NULL, FALSE);
+ g_return_val_if_fail (out_certificate_errors != NULL, FALSE);
+
+ g_mutex_lock (&cnc->priv->property_lock);
+ if (!cnc->priv->ssl_info_set) {
+ g_mutex_unlock (&cnc->priv->property_lock);
+ return FALSE;
+ }
+
+ *out_certificate_pem = g_strdup (cnc->priv->ssl_certificate_pem);
+ *out_certificate_errors = cnc->priv->ssl_certificate_errors;
+
+ g_mutex_unlock (&cnc->priv->property_lock);
+
+ return TRUE;
+}
+
const gchar *
e_ews_connection_get_uri (EEwsConnection *cnc)
{
@@ -2906,6 +2997,9 @@ autodiscover_response_cb (SoupSession *s
g_set_error (
&error, SOUP_HTTP_ERROR, status,
"%d %s", status, msg->reason_phrase);
+
+ if (status == SOUP_STATUS_SSL_FAILED)
+ ews_connection_check_ssl_error (ad->cnc, msg);
}
g_free (service_url);
@@ -3056,7 +3150,8 @@ static void post_restarted (SoupMessage
}
static SoupMessage *
-e_ews_get_msg_for_url (CamelEwsSettings *settings,
+e_ews_get_msg_for_url (EEwsConnection *cnc,
+ CamelEwsSettings *settings,
const gchar *url,
xmlOutputBuffer *buf,
GError **error)
@@ -3078,6 +3173,9 @@ e_ews_get_msg_for_url (CamelEwsSettings
return NULL;
}
+ if (cnc->priv->source)
+ e_soup_ssl_trust_connect (msg, cnc->priv->source);
+
e_ews_message_attach_chunk_allocator (msg);
e_ews_message_set_user_agent_header (msg, settings);
@@ -3107,6 +3205,8 @@ e_ews_autodiscover_ws_url_sync (ESource
CamelEwsSettings *settings,
const gchar *email_address,
const gchar *password,
+ gchar **out_certificate_pem,
+ GTlsCertificateFlags *out_certificate_errors,
GCancellable *cancellable,
GError **error)
{
@@ -3125,7 +3225,7 @@ e_ews_autodiscover_ws_url_sync (ESource
result = e_async_closure_wait (closure);
- success = e_ews_autodiscover_ws_url_finish (settings, result, error);
+ success = e_ews_autodiscover_ws_url_finish (settings, result, out_certificate_pem, out_certificate_errors, error);
e_async_closure_free (closure);
@@ -3236,11 +3336,11 @@ e_ews_autodiscover_ws_url (ESource *sour
simple, ad, (GDestroyNotify) autodiscover_data_free);
/* Passing a NULL URL string returns NULL. */
- ad->msgs[0] = e_ews_get_msg_for_url (settings, url1, buf, &error);
- ad->msgs[1] = e_ews_get_msg_for_url (settings, url2, buf, NULL);
- ad->msgs[2] = e_ews_get_msg_for_url (settings, url3, buf, NULL);
- ad->msgs[3] = e_ews_get_msg_for_url (settings, url4, buf, NULL);
- ad->msgs[4] = e_ews_get_msg_for_url (settings, url5, buf, NULL);
+ ad->msgs[0] = e_ews_get_msg_for_url (cnc, settings, url1, buf, &error);
+ ad->msgs[1] = e_ews_get_msg_for_url (cnc, settings, url2, buf, NULL);
+ ad->msgs[2] = e_ews_get_msg_for_url (cnc, settings, url3, buf, NULL);
+ ad->msgs[3] = e_ews_get_msg_for_url (cnc, settings, url4, buf, NULL);
+ ad->msgs[4] = e_ews_get_msg_for_url (cnc, settings, url5, buf, NULL);
/* These have to be submitted only after they're both set in ad->msgs[]
* or there will be races with fast completion */
@@ -3300,10 +3400,13 @@ has_suffix_icmp (const gchar *text,
gboolean
e_ews_autodiscover_ws_url_finish (CamelEwsSettings *settings,
GAsyncResult *result,
+ gchar **out_certificate_pem,
+ GTlsCertificateFlags *out_certificate_errors,
GError **error)
{
GSimpleAsyncResult *simple;
struct _autodiscover_data *ad;
+ GError *local_error = NULL;
g_return_val_if_fail (
g_simple_async_result_is_valid (
@@ -3313,8 +3416,20 @@ e_ews_autodiscover_ws_url_finish (CamelE
simple = G_SIMPLE_ASYNC_RESULT (result);
ad = g_simple_async_result_get_op_res_gpointer (simple);
- if (g_simple_async_result_propagate_error (simple, error))
+ if (g_simple_async_result_propagate_error (simple, &local_error)) {
+ if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED)) {
+ if (!e_ews_connection_get_ssl_error_details (ad->cnc, out_certificate_pem, out_certificate_errors)) {
+ if (out_certificate_pem)
+ *out_certificate_pem = NULL;
+ if (out_certificate_errors)
+ *out_certificate_errors = 0;
+ }
+ }
+
+ g_propagate_error (error, local_error);
+
return FALSE;
+ }
g_warn_if_fail (ad->as_url != NULL);
g_warn_if_fail (ad->oab_url != NULL);
@@ -3473,6 +3588,8 @@ oal_response_cb (SoupSession *soup_sessi
simple = G_SIMPLE_ASYNC_RESULT (user_data);
data = g_simple_async_result_get_op_res_gpointer (simple);
+ ews_connection_check_ssl_error (data->cnc, soup_message);
+
if (ews_connection_credentials_failed (data->cnc, soup_message, simple)) {
goto exit;
} else if (soup_message->status_code != 200) {
@@ -3618,7 +3735,7 @@ e_ews_connection_get_oal_list (EEwsConne
g_return_if_fail (E_IS_EWS_CONNECTION (cnc));
- soup_message = e_ews_get_msg_for_url (cnc->priv->settings, cnc->priv->uri, NULL, &error);
+ soup_message = e_ews_get_msg_for_url (cnc, cnc->priv->settings, cnc->priv->uri, NULL, &error);
simple = g_simple_async_result_new (
G_OBJECT (cnc), callback, user_data,
@@ -3739,7 +3856,7 @@ e_ews_connection_get_oal_detail (EEwsCon
g_return_if_fail (E_IS_EWS_CONNECTION (cnc));
- soup_message = e_ews_get_msg_for_url (cnc->priv->settings, cnc->priv->uri, NULL, &error);
+ soup_message = e_ews_get_msg_for_url (cnc, cnc->priv->settings, cnc->priv->uri, NULL, &error);
simple = g_simple_async_result_new (
G_OBJECT (cnc), callback, user_data,
@@ -3826,6 +3943,8 @@ oal_download_response_cb (SoupSession *s
simple = G_SIMPLE_ASYNC_RESULT (user_data);
data = g_simple_async_result_get_op_res_gpointer (simple);
+ ews_connection_check_ssl_error (data->cnc, soup_message);
+
if (ews_connection_credentials_failed (data->cnc, soup_message, simple)) {
g_unlink (data->cache_filename);
} else if (soup_message->status_code != 200) {
@@ -3954,7 +4073,7 @@ e_ews_connection_download_oal_file (EEws
g_return_if_fail (E_IS_EWS_CONNECTION (cnc));
- soup_message = e_ews_get_msg_for_url (cnc->priv->settings, cnc->priv->uri, NULL, &error);
+ soup_message = e_ews_get_msg_for_url (cnc, cnc->priv->settings, cnc->priv->uri, NULL, &error);
simple = g_simple_async_result_new (
G_OBJECT (cnc), callback, user_data,
diff -up evolution-ews-3.28.5/src/server/e-ews-connection.h.cve-2019-3890 evolution-ews-3.28.5/src/server/e-ews-connection.h
--- evolution-ews-3.28.5/src/server/e-ews-connection.h.cve-2019-3890 2018-07-30 16:01:00.000000000 +0200
+++ evolution-ews-3.28.5/src/server/e-ews-connection.h 2019-04-15 09:43:49.689771516 +0200
@@ -426,9 +426,16 @@ ESourceAuthenticationResult
e_ews_connection_try_credentials_sync
(EEwsConnection *cnc,
const ENamedParameters *credentials,
+ ESource *use_source,
+ gchar **out_certificate_pem,
+ GTlsCertificateFlags *out_certificate_errors,
GCancellable *cancellable,
GError **error);
ESource * e_ews_connection_get_source (EEwsConnection *cnc);
+gboolean e_ews_connection_get_ssl_error_details
+ (EEwsConnection *cnc,
+ gchar **out_certificate_pem,
+ GTlsCertificateFlags *out_certificate_errors);
const gchar * e_ews_connection_get_uri (EEwsConnection *cnc);
ESoupAuthBearer *
e_ews_connection_ref_bearer_auth(EEwsConnection *cnc);
@@ -469,6 +476,8 @@ gboolean e_ews_autodiscover_ws_url_sync
CamelEwsSettings *settings,
const gchar *email_address,
const gchar *password,
+ gchar **out_certificate_pem,
+ GTlsCertificateFlags *out_certificate_errors,
GCancellable *cancellable,
GError **error);
void e_ews_autodiscover_ws_url (ESource *source,
@@ -481,6 +490,8 @@ void e_ews_autodiscover_ws_url (ESource
gboolean e_ews_autodiscover_ws_url_finish
(CamelEwsSettings *settings,
GAsyncResult *result,
+ gchar **out_certificate_pem,
+ GTlsCertificateFlags *out_certificate_errors,
GError **error);
const gchar * e_ews_connection_get_mailbox (EEwsConnection *cnc);
void e_ews_connection_set_mailbox (EEwsConnection *cnc,
diff -up evolution-ews-3.28.5/src/server/e-ews-connection-utils.c.cve-2019-3890 evolution-ews-3.28.5/src/server/e-ews-connection-utils.c
--- evolution-ews-3.28.5/src/server/e-ews-connection-utils.c.cve-2019-3890 2018-07-30 16:01:00.000000000 +0200
+++ evolution-ews-3.28.5/src/server/e-ews-connection-utils.c 2019-04-15 09:43:49.690771516 +0200
@@ -522,8 +522,13 @@ e_ews_connection_utils_prepare_message (
GCancellable *cancellable)
{
ESoupAuthBearer *using_bearer_auth;
+ ESource *source;
GError *local_error = NULL;
+ source = e_ews_connection_get_source (cnc);
+ if (source)
+ e_soup_ssl_trust_connect (message, source);
+
if (!ews_connection_utils_maybe_prepare_bearer_auth (cnc, message, cancellable))
return FALSE;

@ -0,0 +1,12 @@
diff -up evolution-ews-3.28.5/src/calendar/e-cal-backend-ews.c.disable-reminder-types evolution-ews-3.28.5/src/calendar/e-cal-backend-ews.c
--- evolution-ews-3.28.5/src/calendar/e-cal-backend-ews.c.disable-reminder-types 2018-07-30 16:01:00.000000000 +0200
+++ evolution-ews-3.28.5/src/calendar/e-cal-backend-ews.c 2018-09-27 18:30:08.889040518 +0200
@@ -3675,6 +3675,8 @@ ecb_ews_get_backend_property (ECalBacken
return g_strjoin (
",",
CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS,
+ CAL_STATIC_CAPABILITY_NO_AUDIO_ALARMS,
+ CAL_STATIC_CAPABILITY_NO_PROCEDURE_ALARMS,
CAL_STATIC_CAPABILITY_ONE_ALARM_ONLY,
CAL_STATIC_CAPABILITY_REMOVE_ALARMS,
CAL_STATIC_CAPABILITY_NO_THISANDPRIOR,

@ -0,0 +1,66 @@
From f50530ad101b47d461a345ff2b8b295b86c05d3a Mon Sep 17 00:00:00 2001
From: Milan Crha <mcrha@redhat.com>
Date: Thu, 27 Sep 2018 10:51:05 +0200
Subject: Collection backend schedules two 'populate' requests after going
online
ECollectionBackend base class makes sure the 'populate' method is called
after the backend itself goes online, thus there is no need to schedule
it in the descendant again.
Related to https://gitlab.gnome.org/GNOME/evolution-data-server/issues/36
diff --git a/src/collection/e-ews-backend.c b/src/collection/e-ews-backend.c
index 651694b7..d9a973af 100644
--- a/src/collection/e-ews-backend.c
+++ b/src/collection/e-ews-backend.c
@@ -48,7 +48,7 @@ struct _EEwsBackendPrivate {
gboolean need_update_folders;
- gulong notify_online_id;
+ gulong source_changed_id;
};
struct _SyncFoldersClosure {
@@ -647,15 +647,21 @@ static void
ews_backend_dispose (GObject *object)
{
EEwsBackendPrivate *priv;
+ ESource *source;
priv = E_EWS_BACKEND_GET_PRIVATE (object);
+ source = e_backend_get_source (E_BACKEND (object));
+ if (source && priv->source_changed_id) {
+ g_signal_handler_disconnect (source, priv->source_changed_id);
+ priv->source_changed_id = 0;
+ }
+
g_hash_table_remove_all (priv->folders);
- if (priv->connection != NULL) {
- g_object_unref (priv->connection);
- priv->connection = NULL;
- }
+ g_mutex_lock (&priv->connection_lock);
+ g_clear_object (&priv->connection);
+ g_mutex_unlock (&priv->connection_lock);
/* Chain up to parent's dispose() method. */
G_OBJECT_CLASS (e_ews_backend_parent_class)->dispose (object);
@@ -770,12 +776,8 @@ ews_backend_populate (ECollectionBackend *backend)
ews_backend->priv->need_update_folders = TRUE;
- if (!ews_backend->priv->notify_online_id) {
- ews_backend->priv->notify_online_id = g_signal_connect (
- backend, "notify::online",
- G_CALLBACK (ews_backend_populate), NULL);
-
- g_signal_connect (
+ if (!ews_backend->priv->source_changed_id) {
+ ews_backend->priv->source_changed_id = g_signal_connect (
source, "changed",
G_CALLBACK (ews_backend_source_changed_cb), ews_backend);
}

@ -0,0 +1,259 @@
diff -up evolution-ews-3.28.5/src/calendar/e-cal-backend-ews.c.import-event-timezone evolution-ews-3.28.5/src/calendar/e-cal-backend-ews.c
--- evolution-ews-3.28.5/src/calendar/e-cal-backend-ews.c.import-event-timezone 2018-07-30 16:01:00.000000000 +0200
+++ evolution-ews-3.28.5/src/calendar/e-cal-backend-ews.c 2018-09-04 11:14:27.815647542 +0200
@@ -579,7 +579,7 @@ ecb_ews_item_to_component_sync (ECalBack
if (start_zone != NULL) {
icalcomp = icalcomponent_get_first_component (vcomp, kind);
- dt = e_cal_backend_ews_get_datetime_with_zone (timezone_cache, icalcomp, ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
+ dt = e_cal_backend_ews_get_datetime_with_zone (timezone_cache, vcomp, icalcomp, ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
dt = icaltime_convert_to_zone (dt, start_zone);
icalcomponent_set_dtstart (icalcomp, dt);
@@ -587,7 +587,7 @@ ecb_ews_item_to_component_sync (ECalBack
e_timezone_cache_add_timezone (timezone_cache, start_zone);
if (end_zone != NULL) {
- dt = e_cal_backend_ews_get_datetime_with_zone (timezone_cache, icalcomp, ICAL_DTEND_PROPERTY, icalproperty_get_dtend);
+ dt = e_cal_backend_ews_get_datetime_with_zone (timezone_cache, vcomp, icalcomp, ICAL_DTEND_PROPERTY, icalproperty_get_dtend);
dt = icaltime_convert_to_zone (dt, end_zone);
icalcomponent_set_dtend (icalcomp, dt);
@@ -655,11 +655,11 @@ ecb_ews_item_to_component_sync (ECalBack
zone = icaltimezone_get_builtin_timezone (tzid);
if (zone != NULL) {
- dt = e_cal_backend_ews_get_datetime_with_zone (timezone_cache, icalcomp, ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
+ dt = e_cal_backend_ews_get_datetime_with_zone (timezone_cache, vcomp, icalcomp, ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
dt = icaltime_convert_to_zone (dt, zone);
icalcomponent_set_dtstart (icalcomp, dt);
- dt = e_cal_backend_ews_get_datetime_with_zone (timezone_cache, icalcomp, ICAL_DTEND_PROPERTY, icalproperty_get_dtend);
+ dt = e_cal_backend_ews_get_datetime_with_zone (timezone_cache, vcomp, icalcomp, ICAL_DTEND_PROPERTY, icalproperty_get_dtend);
dt = icaltime_convert_to_zone (dt, zone);
icalcomponent_set_dtend (icalcomp, dt);
}
@@ -2930,7 +2930,7 @@ ecb_ews_send_cancellation_email_sync (EC
icalcomponent_add_property (vevent, icalproperty_new_status (ICAL_STATUS_CANCELLED));
prop = icalcomponent_get_first_property (vevent, ICAL_METHOD_PROPERTY);
if (prop != NULL) icalcomponent_remove_property (vevent, prop);
- dt = e_cal_backend_ews_get_datetime_with_zone (E_TIMEZONE_CACHE (cbews), vevent, ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
+ dt = e_cal_backend_ews_get_datetime_with_zone (E_TIMEZONE_CACHE (cbews), NULL, vevent, ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
icaltz = (icaltimezone *)
(dt.zone ? dt.zone : ecb_ews_get_timezone_from_ical_component (cbews, vevent));
vtz = icaltimezone_get_component (icaltz);
@@ -2973,6 +2973,7 @@ ecb_ews_send_cancellation_email_sync (EC
static void
ecb_ews_receive_objects_no_exchange_mail (ECalBackendEws *cbews,
+ icalcomponent *vcalendar,
icalcomponent *subcomp,
GSList **ids,
GCancellable *cancellable,
@@ -2984,6 +2985,7 @@ ecb_ews_receive_objects_no_exchange_mail
convert_data.connection = cbews->priv->cnc;
convert_data.timezone_cache = E_TIMEZONE_CACHE (cbews);
convert_data.icalcomp = subcomp;
+ convert_data.vcalendar = vcalendar;
convert_data.default_zone = icaltimezone_get_utc_timezone ();
fid = e_ews_folder_id_new (cbews->priv->folder_id, NULL, FALSE);
@@ -3228,6 +3230,7 @@ ecb_ews_get_item_accept_id (ECalComponen
static gboolean
ecb_ews_do_method_request_publish_reply (ECalBackendEws *cbews,
+ icalcomponent *vcalendar,
ECalComponent *comp,
icalcomponent *subcomp,
const gchar *response_type,
@@ -3258,7 +3261,7 @@ ecb_ews_do_method_request_publish_reply
while (pass < 2) {
/*in case we do not have item id we will create item with mime content only*/
if (!item_id || (response_type && g_ascii_strcasecmp (response_type, "NEEDS-ACTION") == 0)) {
- ecb_ews_receive_objects_no_exchange_mail (cbews, subcomp, &ids, cancellable, &local_error);
+ ecb_ews_receive_objects_no_exchange_mail (cbews, vcalendar, subcomp, &ids, cancellable, &local_error);
} else {
EwsCalendarConvertData convert_data = { 0 };
@@ -3367,6 +3370,7 @@ ecb_ews_do_method_request_publish_reply
}
convert_data.timezone_cache = E_TIMEZONE_CACHE (cbews);
+ convert_data.vcalendar = vcalendar;
e_ews_connection_update_items_sync (
cbews->priv->cnc,
@@ -3452,7 +3456,7 @@ ecb_ews_receive_objects_sync (ECalBacken
comp = e_cal_component_new_from_icalcomponent (icalcomponent_new_clone (subcomp));
- success = ecb_ews_do_method_request_publish_reply (cbews, comp, subcomp, response_type, user_email, rsvp_requested, cancellable, error);
+ success = ecb_ews_do_method_request_publish_reply (cbews, icalcomp, comp, subcomp, response_type, user_email, rsvp_requested, cancellable, error);
do_refresh = TRUE;
diff -up evolution-ews-3.28.5/src/calendar/e-cal-backend-ews-utils.c.import-event-timezone evolution-ews-3.28.5/src/calendar/e-cal-backend-ews-utils.c
--- evolution-ews-3.28.5/src/calendar/e-cal-backend-ews-utils.c.import-event-timezone 2018-07-30 16:01:00.000000000 +0200
+++ evolution-ews-3.28.5/src/calendar/e-cal-backend-ews-utils.c 2018-09-04 11:16:58.892645453 +0200
@@ -178,7 +178,8 @@ e_cal_backend_ews_tz_util_get_msdn_equiv
{
const gchar *msdn_tz_location = NULL;
- g_return_val_if_fail (ical_tz_location != NULL, NULL);
+ if (!ical_tz_location || !*ical_tz_location)
+ return NULL;
g_rec_mutex_lock (&tz_mutex);
if (ical_to_msdn == NULL) {
@@ -199,7 +200,8 @@ e_cal_backend_ews_tz_util_get_ical_equiv
{
const gchar *ical_tz_location = NULL;
- g_return_val_if_fail (msdn_tz_location != NULL, NULL);
+ if (!msdn_tz_location || !*msdn_tz_location)
+ return NULL;
g_rec_mutex_lock (&tz_mutex);
if (msdn_to_ical == NULL) {
@@ -1113,11 +1115,11 @@ convert_vevent_calcomp_to_xml (ESoapMess
e_ews_message_write_string_parameter (msg, "ReminderIsSet", NULL, "false");
/* start time, end time and meeting time zone */
- dtstart = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, icalcomp, ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
+ dtstart = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, convert_data->vcalendar, icalcomp, ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
tzid_start = (icaltimezone *) (dtstart.zone ? dtstart.zone : convert_data->default_zone);
ical_location_start = icaltimezone_get_location (tzid_start);
- dtend = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, icalcomp, ICAL_DTEND_PROPERTY, icalproperty_get_dtend);
+ dtend = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, convert_data->vcalendar, icalcomp, ICAL_DTEND_PROPERTY, icalproperty_get_dtend);
tzid_end = (icaltimezone *) (dtend.zone ? dtend.zone : convert_data->default_zone);
ical_location_end = icaltimezone_get_location (tzid_end);
@@ -1272,7 +1274,7 @@ convert_vtodo_calcomp_to_xml (ESoapMessa
prop = icalcomponent_get_first_property (icalcomp, ICAL_DUE_PROPERTY);
if (prop) {
- dt = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, icalcomp, ICAL_DUE_PROPERTY, icalproperty_get_due);
+ dt = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, convert_data->vcalendar, icalcomp, ICAL_DUE_PROPERTY, icalproperty_get_due);
e_ews_cal_utils_set_time (msg, "DueDate", &dt, TRUE);
}
@@ -1285,7 +1287,7 @@ convert_vtodo_calcomp_to_xml (ESoapMessa
prop = icalcomponent_get_first_property (icalcomp, ICAL_DTSTART_PROPERTY);
if (prop) {
- dt = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, icalcomp, ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
+ dt = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, convert_data->vcalendar, icalcomp, ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
e_ews_cal_utils_set_time (msg, "StartDate", &dt, TRUE);
}
@@ -1536,8 +1538,8 @@ convert_vevent_component_to_updatexml (E
}
/* Update other properties allowed only for meeting organizers*/
/*meeting dates*/
- dtstart = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, icalcomp, ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
- dtstart_old = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, icalcomp_old, ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
+ dtstart = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, convert_data->vcalendar, icalcomp, ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
+ dtstart_old = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, convert_data->vcalendar, icalcomp_old, ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
dt_start_changed = icaltime_compare (dtstart, dtstart_old) != 0;
if (dtstart.zone != NULL) {
tzid_start = (icaltimezone *) dtstart.zone;
@@ -1548,8 +1550,8 @@ convert_vevent_component_to_updatexml (E
dt_start_changed_timezone_name = TRUE;
}
- dtend = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, icalcomp, ICAL_DTEND_PROPERTY, icalproperty_get_dtend);
- dtend_old = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, icalcomp_old, ICAL_DTEND_PROPERTY, icalproperty_get_dtend);
+ dtend = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, convert_data->vcalendar, icalcomp, ICAL_DTEND_PROPERTY, icalproperty_get_dtend);
+ dtend_old = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, convert_data->vcalendar, icalcomp_old, ICAL_DTEND_PROPERTY, icalproperty_get_dtend);
dt_end_changed = icaltime_compare (dtend, dtend_old) != 0;
if (dtend.zone != NULL) {
tzid_end = (icaltimezone *) dtend.zone;
@@ -1768,7 +1770,7 @@ convert_vtodo_component_to_updatexml (ES
prop = icalcomponent_get_first_property (icalcomp, ICAL_DUE_PROPERTY);
if (prop) {
- dt = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, icalcomp, ICAL_DUE_PROPERTY, icalproperty_get_due);
+ dt = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, convert_data->vcalendar, icalcomp, ICAL_DUE_PROPERTY, icalproperty_get_due);
e_ews_message_start_set_item_field (msg, "DueDate", "task", "Task");
e_ews_cal_utils_set_time (msg, "DueDate", &dt, TRUE);
e_ews_message_end_set_item_field (msg);
@@ -1787,7 +1789,7 @@ convert_vtodo_component_to_updatexml (ES
prop = icalcomponent_get_first_property (icalcomp, ICAL_DTSTART_PROPERTY);
if (prop) {
- dt = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, icalcomp, ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
+ dt = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, convert_data->vcalendar, icalcomp, ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
e_ews_message_start_set_item_field (msg, "StartDate", "task", "Task");
e_ews_cal_utils_set_time (msg, "StartDate", &dt, TRUE);
e_ews_message_end_set_item_field (msg);
@@ -2011,6 +2013,7 @@ e_cal_backend_ews_prepare_accept_item_re
struct icaltimetype
e_cal_backend_ews_get_datetime_with_zone (ETimezoneCache *timezone_cache,
+ icalcomponent *vcalendar,
icalcomponent *comp,
icalproperty_kind prop_kind,
struct icaltimetype (* get_func) (const icalproperty *prop))
@@ -2018,7 +2021,7 @@ e_cal_backend_ews_get_datetime_with_zone
struct icaltimetype dt = icaltime_null_time ();
icalproperty *prop;
icalparameter *param;
- const gchar *tzid;
+ const gchar *tzid, *eqv_tzid;
g_return_val_if_fail (E_IS_TIMEZONE_CACHE (timezone_cache), dt);
g_return_val_if_fail (comp != NULL, dt);
@@ -2034,6 +2037,8 @@ e_cal_backend_ews_get_datetime_with_zone
icaltime_is_null_time (dt))
return dt;
+ dt.zone = NULL;
+
param = icalproperty_get_first_parameter (prop, ICAL_TZID_PARAMETER);
if (!param)
return dt;
@@ -2042,7 +2047,23 @@ e_cal_backend_ews_get_datetime_with_zone
if (!tzid || !*tzid)
return dt;
- dt.zone = e_timezone_cache_get_timezone (timezone_cache, tzid);
+ eqv_tzid = e_cal_backend_ews_tz_util_get_ical_equivalent (tzid);
+
+ if (!eqv_tzid) {
+ /* Unlikely to work, but just in case */
+ eqv_tzid = e_cal_backend_ews_tz_util_get_msdn_equivalent (tzid);
+ if (eqv_tzid)
+ eqv_tzid = e_cal_backend_ews_tz_util_get_ical_equivalent (eqv_tzid);
+ }
+
+ if (eqv_tzid)
+ dt.zone = e_timezone_cache_get_timezone (timezone_cache, eqv_tzid);
+
+ if (!dt.zone)
+ dt.zone = e_timezone_cache_get_timezone (timezone_cache, tzid);
+
+ if (!dt.zone)
+ dt.zone = vcalendar ? icalcomponent_get_timezone (vcalendar, tzid) : NULL;
return dt;
}
diff -up evolution-ews-3.28.5/src/calendar/e-cal-backend-ews-utils.h.import-event-timezone evolution-ews-3.28.5/src/calendar/e-cal-backend-ews-utils.h
--- evolution-ews-3.28.5/src/calendar/e-cal-backend-ews-utils.h.import-event-timezone 2018-07-30 16:01:00.000000000 +0200
+++ evolution-ews-3.28.5/src/calendar/e-cal-backend-ews-utils.h 2018-09-04 11:14:27.814647542 +0200
@@ -47,6 +47,7 @@ typedef struct {
ECalComponent *comp;
ECalComponent *old_comp;
icalcomponent *icalcomp;
+ icalcomponent *vcalendar; /* can be NULL, parent of icalcomp, where timezones can be eventually found */
gchar *item_id;
gchar *change_key;
EEwsItemChangeType change_type;
@@ -82,6 +83,7 @@ guint e_cal_backend_ews_rid_to_index (ic
struct icaltimetype
e_cal_backend_ews_get_datetime_with_zone (ETimezoneCache *timezone_cache,
+ icalcomponent *vcalendar,
icalcomponent *comp,
icalproperty_kind prop_kind,
struct icaltimetype (* get_func) (const icalproperty *prop));

@ -0,0 +1,114 @@
diff -up evolution-ews-3.28.5/src/calendar/e-cal-backend-ews.c.meeting-with-attachment evolution-ews-3.28.5/src/calendar/e-cal-backend-ews.c
--- evolution-ews-3.28.5/src/calendar/e-cal-backend-ews.c.meeting-with-attachment 2018-09-27 18:32:25.783038625 +0200
+++ evolution-ews-3.28.5/src/calendar/e-cal-backend-ews.c 2018-09-27 18:32:25.786038625 +0200
@@ -2598,7 +2598,7 @@ ecb_ews_save_component_sync (ECalMetaBac
GHashTable *removed_indexes;
EwsCalendarConvertData convert_data = { 0 };
EEwsItem *item = NULL;
- const EwsId *ews_id = NULL;
+ EwsId *ews_id = NULL;
const gchar *send_meeting_invitations;
icalcomponent *icalcomp;
icalproperty *prop;
@@ -2642,7 +2642,7 @@ ecb_ews_save_component_sync (ECalMetaBac
if (item) {
g_object_ref (item);
- ews_id = e_ews_item_get_id (item);
+ ews_id = e_ews_id_copy (e_ews_item_get_id (item));
}
}
@@ -2666,6 +2666,8 @@ ecb_ews_save_component_sync (ECalMetaBac
g_clear_object (&item);
item = items_req->data;
+
+ e_ews_id_free (ews_id);
ews_id = NULL;
if (e_ews_item_get_item_type (item) == E_EWS_ITEM_TYPE_ERROR) {
@@ -2674,7 +2676,7 @@ ecb_ews_save_component_sync (ECalMetaBac
success = FALSE;
} else {
item = g_object_ref (item);
- ews_id = e_ews_item_get_id (item);
+ ews_id = e_ews_id_copy (e_ews_item_get_id (item));
}
}
@@ -2689,13 +2691,21 @@ ecb_ews_save_component_sync (ECalMetaBac
g_warn_if_fail (ews_id != NULL);
if (ews_id && ecb_ews_extract_attachments (icalcomp, &info_attachments)) {
+ gchar *changekey = NULL;
GSList *ids = NULL;
success = e_ews_connection_create_attachments_sync (cbews->priv->cnc, EWS_PRIORITY_MEDIUM,
- ews_id, info_attachments, FALSE, NULL, &ids, cancellable, error);
+ ews_id, info_attachments, FALSE, &changekey, &ids, cancellable, error);
g_slist_free_full (info_attachments, (GDestroyNotify) e_ews_attachment_info_free);
g_slist_free_full (ids, g_free);
+
+ if (success && changekey) {
+ g_free (ews_id->change_key);
+ ews_id->change_key = changekey;
+ } else {
+ g_free (changekey);
+ }
}
}
@@ -2730,6 +2740,7 @@ ecb_ews_save_component_sync (ECalMetaBac
}
icalcomponent_free (icalcomp);
+ e_ews_id_free (ews_id);
g_clear_object (&item);
for (link = (GSList *) instances; link && success; link = g_slist_next (link)) {
diff -up evolution-ews-3.28.5/src/server/e-ews-item.c.meeting-with-attachment evolution-ews-3.28.5/src/server/e-ews-item.c
--- evolution-ews-3.28.5/src/server/e-ews-item.c.meeting-with-attachment 2018-09-27 18:32:25.785038625 +0200
+++ evolution-ews-3.28.5/src/server/e-ews-item.c 2018-09-27 18:32:25.787038625 +0200
@@ -2695,3 +2695,28 @@ e_ews_item_util_strip_ex_address (const
return ex_address;
}
+
+EwsId *
+e_ews_id_copy (const EwsId *ews_id)
+{
+ EwsId *copy;
+
+ if (!ews_id)
+ return NULL;
+
+ copy = g_new0 (EwsId, 1);
+ copy->id = g_strdup (ews_id->id);
+ copy->change_key = g_strdup (ews_id->change_key);
+
+ return copy;
+}
+
+void
+e_ews_id_free (EwsId *ews_id)
+{
+ if (ews_id) {
+ g_free (ews_id->id);
+ g_free (ews_id->change_key);
+ g_free (ews_id);
+ }
+}
diff -up evolution-ews-3.28.5/src/server/e-ews-item.h.meeting-with-attachment evolution-ews-3.28.5/src/server/e-ews-item.h
--- evolution-ews-3.28.5/src/server/e-ews-item.h.meeting-with-attachment 2018-07-30 16:01:00.000000000 +0200
+++ evolution-ews-3.28.5/src/server/e-ews-item.h 2018-09-27 18:32:25.787038625 +0200
@@ -384,6 +384,8 @@ void e_ews_permissions_free (GSList *pe
/* Utility functions */
const gchar * e_ews_item_util_strip_ex_address
(const gchar *ex_address);
+EwsId * e_ews_id_copy (const EwsId *ews_id);
+void e_ews_id_free (EwsId *ews_id);
G_END_DECLS

@ -0,0 +1,707 @@
diff -up evolution-ews-3.28.5/CMakeLists.txt.oauth2-endpoints evolution-ews-3.28.5/CMakeLists.txt
--- evolution-ews-3.28.5/CMakeLists.txt.oauth2-endpoints 2020-10-07 17:08:15.761562791 +0200
+++ evolution-ews-3.28.5/CMakeLists.txt 2020-10-07 17:08:15.762562790 +0200
@@ -195,6 +195,12 @@ if(WITH_OFFICE365_REDIRECT_URI STREQUAL
set(WITH_OFFICE365_REDIRECT_URI "https://login.microsoftonline.com/common/oauth2/nativeclient")
endif(WITH_OFFICE365_REDIRECT_URI STREQUAL "")
+add_printable_variable(WITH_OFFICE365_ENDPOINT_HOST "Office365.com OAuth 2.0 endpoint host" "")
+
+if(WITH_OFFICE365_ENDPOINT_HOST STREQUAL "")
+ set(WITH_OFFICE365_ENDPOINT_HOST "login.microsoftonline.com")
+endif(WITH_OFFICE365_ENDPOINT_HOST STREQUAL "")
+
# ******************************
# Special directories
# ******************************
diff -up evolution-ews-3.28.5/config.h.in.oauth2-endpoints evolution-ews-3.28.5/config.h.in
--- evolution-ews-3.28.5/config.h.in.oauth2-endpoints 2018-07-30 16:01:00.000000000 +0200
+++ evolution-ews-3.28.5/config.h.in 2020-10-07 17:08:15.762562790 +0200
@@ -29,3 +29,6 @@
/* Define Office365 OAuth 2.0 default Redirect URI to use */
#define OFFICE365_REDIRECT_URI "@WITH_OFFICE365_REDIRECT_URI@"
+
+/* Define Office365 OAuth 2.0 default Endpoint Host to use */
+#define OFFICE365_ENDPOINT_HOST "@WITH_OFFICE365_ENDPOINT_HOST@"
diff -up evolution-ews-3.28.5/src/configuration/e-mail-config-ews-backend.c.oauth2-endpoints evolution-ews-3.28.5/src/configuration/e-mail-config-ews-backend.c
--- evolution-ews-3.28.5/src/configuration/e-mail-config-ews-backend.c.oauth2-endpoints 2020-10-07 17:08:15.761562791 +0200
+++ evolution-ews-3.28.5/src/configuration/e-mail-config-ews-backend.c 2020-10-07 17:08:15.762562790 +0200
@@ -29,6 +29,7 @@
#include <mail/e-mail-config-receiving-page.h>
#include "server/camel-ews-settings.h"
+#include "server/e-oauth2-service-office365.h"
#include "e-mail-config-ews-autodiscover.h"
#include "e-ews-config-utils.h"
@@ -50,6 +51,8 @@ struct _EMailConfigEwsBackendPrivate {
GtkWidget *oauth2_tenant_entry;
GtkWidget *oauth2_client_id_entry;
GtkWidget *oauth2_redirect_uri_entry;
+ GtkWidget *oauth2_resource_uri_entry;
+ GtkWidget *oauth2_endpoint_host_entry;
};
G_DEFINE_DYNAMIC_TYPE (
@@ -156,6 +159,11 @@ mail_config_ews_backend_insert_widgets (
GtkLabel *label;
GtkWidget *widget;
GtkWidget *container;
+ GtkWidget *expander;
+ GtkWidget *advanced_help;
+ GtkWidget *endpoint_host_label;
+ GtkWidget *redirect_uri_label;
+ GtkWidget *resource_uri_label;
const gchar *extension_name;
const gchar *text;
gchar *markup;
@@ -381,11 +389,62 @@ mail_config_ews_backend_insert_widgets (
_("There is not set any default application ID"),
g_strdup_printf (_("Default application ID is “%s”"), OFFICE365_CLIENT_ID));
- widget = gtk_label_new_with_mnemonic (_("_Redirect URI:"));
+ container = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+ gtk_grid_attach (priv->oauth2_settings_grid, container, 0, 3, 2, 1);
+
+ widget = gtk_expander_new_with_mnemonic (_("_Advanced Settings"));
+ gtk_widget_set_margin_left (widget, 12);
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ expander = widget;
+
+ e_binding_bind_property (
+ priv->oauth2_override_check, "active",
+ widget, "sensitive",
+ G_BINDING_SYNC_CREATE);
+
+ markup = g_markup_printf_escaped ("(<a href=\"https://wiki.gnome.org/Apps/Evolution/EWS/OAuth2#Alternative_endpoints\">%s</a>)", _("Help…"));
+ widget = gtk_label_new (markup);
+ gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ g_free (markup);
+ advanced_help = widget;
+
+ widget = gtk_label_new_with_mnemonic (_("_Endpoint host:"));
+ gtk_widget_set_margin_left (widget, 12);
+ gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+ gtk_grid_attach (priv->oauth2_settings_grid, widget, 0, 4, 1, 1);
+ label = GTK_LABEL (widget);
+ endpoint_host_label = widget;
+
+ e_binding_bind_property (
+ priv->oauth2_override_check, "active",
+ widget, "sensitive",
+ G_BINDING_SYNC_CREATE);
+
+ widget = gtk_entry_new ();
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_label_set_mnemonic_widget (label, widget);
+ gtk_grid_attach (priv->oauth2_settings_grid, widget, 1, 4, 1, 1);
+ priv->oauth2_endpoint_host_entry = widget;
+
+ e_binding_bind_property (
+ priv->oauth2_override_check, "active",
+ widget, "sensitive",
+ G_BINDING_SYNC_CREATE);
+
+ markup = g_strdup_printf (_("Default endpoint host is “%s”"), "login.microsoftonline.com");
+ mail_config_ews_backend_set_oauth2_tooltip (widget, OFFICE365_ENDPOINT_HOST,
+ markup,
+ g_strdup_printf (_("Default endpoint host is “%s”"), OFFICE365_ENDPOINT_HOST));
+ g_free (markup);
+
+ widget = gtk_label_new_with_mnemonic (_("Red_irect URI:"));
gtk_widget_set_margin_left (widget, 12);
gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
- gtk_grid_attach (priv->oauth2_settings_grid, widget, 0, 3, 1, 1);
+ gtk_grid_attach (priv->oauth2_settings_grid, widget, 0, 5, 1, 1);
label = GTK_LABEL (widget);
+ redirect_uri_label = widget;
e_binding_bind_property (
priv->oauth2_override_check, "active",
@@ -395,7 +454,7 @@ mail_config_ews_backend_insert_widgets (
widget = gtk_entry_new ();
gtk_widget_set_hexpand (widget, TRUE);
gtk_label_set_mnemonic_widget (label, widget);
- gtk_grid_attach (priv->oauth2_settings_grid, widget, 1, 3, 1, 1);
+ gtk_grid_attach (priv->oauth2_settings_grid, widget, 1, 5, 1, 1);
priv->oauth2_redirect_uri_entry = widget;
e_binding_bind_property (
@@ -409,8 +468,77 @@ mail_config_ews_backend_insert_widgets (
g_strdup_printf (_("Default redirect URI is “%s”"), OFFICE365_REDIRECT_URI));
g_free (markup);
+ widget = gtk_label_new_with_mnemonic (_("Re_source URI:"));
+ gtk_widget_set_margin_left (widget, 12);
+ gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+ gtk_grid_attach (priv->oauth2_settings_grid, widget, 0, 6, 1, 1);
+ label = GTK_LABEL (widget);
+ resource_uri_label = widget;
+
+ e_binding_bind_property (
+ priv->oauth2_override_check, "active",
+ widget, "sensitive",
+ G_BINDING_SYNC_CREATE);
+
+ widget = gtk_entry_new ();
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_label_set_mnemonic_widget (label, widget);
+ gtk_grid_attach (priv->oauth2_settings_grid, widget, 1, 6, 1, 1);
+ priv->oauth2_resource_uri_entry = widget;
+
+ e_binding_bind_property (
+ priv->oauth2_override_check, "active",
+ widget, "sensitive",
+ G_BINDING_SYNC_CREATE);
+
+ markup = g_strdup_printf (_("Default resource URI is derived from the Host URL, or it can eventually fall back to “%s”."), OFFICE365_FALLBACK_RESOURCE_URI);
+ mail_config_ews_backend_set_oauth2_tooltip (widget, NULL,
+ markup,
+ NULL);
+ g_free (markup);
+
gtk_widget_show_all (GTK_WIDGET (priv->oauth2_settings_grid));
+ gtk_expander_set_expanded (GTK_EXPANDER (expander),
+ e_ews_util_strcmp0 (camel_ews_settings_get_oauth2_endpoint_host (CAMEL_EWS_SETTINGS (settings)), NULL) != 0 ||
+ e_ews_util_strcmp0 (camel_ews_settings_get_oauth2_redirect_uri (CAMEL_EWS_SETTINGS (settings)), NULL) != 0 ||
+ e_ews_util_strcmp0 (camel_ews_settings_get_oauth2_resource_uri (CAMEL_EWS_SETTINGS (settings)), NULL) != 0);
+
+ e_binding_bind_property (
+ expander, "expanded",
+ advanced_help, "visible",
+ G_BINDING_SYNC_CREATE);
+
+ e_binding_bind_property (
+ expander, "expanded",
+ endpoint_host_label, "visible",
+ G_BINDING_SYNC_CREATE);
+
+ e_binding_bind_property (
+ expander, "expanded",
+ priv->oauth2_endpoint_host_entry, "visible",
+ G_BINDING_SYNC_CREATE);
+
+ e_binding_bind_property (
+ expander, "expanded",
+ redirect_uri_label, "visible",
+ G_BINDING_SYNC_CREATE);
+
+ e_binding_bind_property (
+ expander, "expanded",
+ priv->oauth2_redirect_uri_entry, "visible",
+ G_BINDING_SYNC_CREATE);
+
+ e_binding_bind_property (
+ expander, "expanded",
+ resource_uri_label, "visible",
+ G_BINDING_SYNC_CREATE);
+
+ e_binding_bind_property (
+ expander, "expanded",
+ priv->oauth2_resource_uri_entry, "visible",
+ G_BINDING_SYNC_CREATE);
+
e_binding_bind_property_full (
priv->auth_check, "active-mechanism",
priv->oauth2_settings_grid, "visible",
@@ -463,11 +591,23 @@ mail_config_ews_backend_insert_widgets (
G_BINDING_SYNC_CREATE);
e_binding_bind_object_text_property (
- settings, "oauth2-redirect_uri",
+ settings, "oauth2-redirect-uri",
priv->oauth2_redirect_uri_entry, "text",
G_BINDING_BIDIRECTIONAL |
G_BINDING_SYNC_CREATE);
+ e_binding_bind_object_text_property (
+ settings, "oauth2-resource-uri",
+ priv->oauth2_resource_uri_entry, "text",
+ G_BINDING_BIDIRECTIONAL |
+ G_BINDING_SYNC_CREATE);
+
+ e_binding_bind_object_text_property (
+ settings, "oauth2-endpoint-host",
+ priv->oauth2_endpoint_host_entry, "text",
+ G_BINDING_BIDIRECTIONAL |
+ G_BINDING_SYNC_CREATE);
+
extension_name = E_SOURCE_EXTENSION_COLLECTION;
source = e_mail_config_service_backend_get_collection (backend);
extension = e_source_get_extension (source, extension_name);
diff -up evolution-ews-3.28.5/src/server/camel-ews-settings.c.oauth2-endpoints evolution-ews-3.28.5/src/server/camel-ews-settings.c
--- evolution-ews-3.28.5/src/server/camel-ews-settings.c.oauth2-endpoints 2018-07-30 16:01:00.000000000 +0200
+++ evolution-ews-3.28.5/src/server/camel-ews-settings.c 2020-10-07 17:08:15.762562790 +0200
@@ -47,6 +47,8 @@ struct _CamelEwsSettingsPrivate {
gchar *oauth2_tenant;
gchar *oauth2_client_id;
gchar *oauth2_redirect_uri;
+ gchar *oauth2_resource_uri;
+ gchar *oauth2_endpoint_host;
};
enum {
@@ -74,7 +76,9 @@ enum {
PROP_OVERRIDE_OAUTH2,
PROP_OAUTH2_TENANT,
PROP_OAUTH2_CLIENT_ID,
- PROP_OAUTH2_REDIRECT_URI
+ PROP_OAUTH2_REDIRECT_URI,
+ PROP_OAUTH2_RESOURCE_URI,
+ PROP_OAUTH2_ENDPOINT_HOST
};
G_DEFINE_TYPE_WITH_CODE (
@@ -263,6 +267,18 @@ ews_settings_set_property (GObject *obje
CAMEL_EWS_SETTINGS (object),
g_value_get_string (value));
return;
+
+ case PROP_OAUTH2_RESOURCE_URI:
+ camel_ews_settings_set_oauth2_resource_uri (
+ CAMEL_EWS_SETTINGS (object),
+ g_value_get_string (value));
+ return;
+
+ case PROP_OAUTH2_ENDPOINT_HOST:
+ camel_ews_settings_set_oauth2_endpoint_host (
+ CAMEL_EWS_SETTINGS (object),
+ g_value_get_string (value));
+ return;
}
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -442,6 +458,20 @@ ews_settings_get_property (GObject *obje
camel_ews_settings_dup_oauth2_redirect_uri (
CAMEL_EWS_SETTINGS (object)));
return;
+
+ case PROP_OAUTH2_RESOURCE_URI:
+ g_value_take_string (
+ value,
+ camel_ews_settings_dup_oauth2_resource_uri (
+ CAMEL_EWS_SETTINGS (object)));
+ return;
+
+ case PROP_OAUTH2_ENDPOINT_HOST:
+ g_value_take_string (
+ value,
+ camel_ews_settings_dup_oauth2_endpoint_host (
+ CAMEL_EWS_SETTINGS (object)));
+ return;
}
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -466,6 +496,8 @@ ews_settings_finalize (GObject *object)
g_free (priv->oauth2_tenant);
g_free (priv->oauth2_client_id);
g_free (priv->oauth2_redirect_uri);
+ g_free (priv->oauth2_resource_uri);
+ g_free (priv->oauth2_endpoint_host);
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (camel_ews_settings_parent_class)->finalize (object);
@@ -740,6 +772,30 @@ camel_ews_settings_class_init (CamelEwsS
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_OAUTH2_RESOURCE_URI,
+ g_param_spec_string (
+ "oauth2-resource-uri",
+ "OAuth2 Resource URI",
+ "OAuth2 Resource URI to use, only if override-oauth2 is TRUE, otherwise the compile-time value is used",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_OAUTH2_ENDPOINT_HOST,
+ g_param_spec_string (
+ "oauth2-endpoint-host",
+ "OAuth2 Endpoint Host",
+ "OAuth2 endpoint host to use, only if override-oauth2 is TRUE, otherwise the compile-time value is used",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
}
static void
@@ -1543,3 +1599,97 @@ camel_ews_settings_set_oauth2_redirect_u
g_object_notify (G_OBJECT (settings), "oauth2-redirect-uri");
}
+
+const gchar *
+camel_ews_settings_get_oauth2_resource_uri (CamelEwsSettings *settings)
+{
+ g_return_val_if_fail (CAMEL_IS_EWS_SETTINGS (settings), NULL);
+
+ return settings->priv->oauth2_resource_uri;
+}
+
+gchar *
+camel_ews_settings_dup_oauth2_resource_uri (CamelEwsSettings *settings)
+{
+ const gchar *protected;
+ gchar *duplicate;
+
+ g_return_val_if_fail (CAMEL_IS_EWS_SETTINGS (settings), NULL);
+
+ g_mutex_lock (&settings->priv->property_lock);
+
+ protected = camel_ews_settings_get_oauth2_resource_uri (settings);
+ duplicate = g_strdup (protected);
+
+ g_mutex_unlock (&settings->priv->property_lock);
+
+ return duplicate;
+}
+
+void
+camel_ews_settings_set_oauth2_resource_uri (CamelEwsSettings *settings,
+ const gchar *resource_uri)
+{
+ g_return_if_fail (CAMEL_IS_EWS_SETTINGS (settings));
+
+ g_mutex_lock (&settings->priv->property_lock);
+
+ if (g_strcmp0 (settings->priv->oauth2_resource_uri, resource_uri) == 0) {
+ g_mutex_unlock (&settings->priv->property_lock);
+ return;
+ }
+
+ g_free (settings->priv->oauth2_resource_uri);
+ settings->priv->oauth2_resource_uri = e_util_strdup_strip (resource_uri);
+
+ g_mutex_unlock (&settings->priv->property_lock);
+
+ g_object_notify (G_OBJECT (settings), "oauth2-resource-uri");
+}
+
+const gchar *
+camel_ews_settings_get_oauth2_endpoint_host (CamelEwsSettings *settings)
+{
+ g_return_val_if_fail (CAMEL_IS_EWS_SETTINGS (settings), NULL);
+
+ return settings->priv->oauth2_endpoint_host;
+}
+
+gchar *
+camel_ews_settings_dup_oauth2_endpoint_host (CamelEwsSettings *settings)
+{
+ const gchar *protected;
+ gchar *duplicate;
+
+ g_return_val_if_fail (CAMEL_IS_EWS_SETTINGS (settings), NULL);
+
+ g_mutex_lock (&settings->priv->property_lock);
+
+ protected = camel_ews_settings_get_oauth2_endpoint_host (settings);
+ duplicate = g_strdup (protected);
+
+ g_mutex_unlock (&settings->priv->property_lock);
+
+ return duplicate;
+}
+
+void
+camel_ews_settings_set_oauth2_endpoint_host (CamelEwsSettings *settings,
+ const gchar *endpoint_host)
+{
+ g_return_if_fail (CAMEL_IS_EWS_SETTINGS (settings));
+
+ g_mutex_lock (&settings->priv->property_lock);
+
+ if (g_strcmp0 (settings->priv->oauth2_endpoint_host, endpoint_host) == 0) {
+ g_mutex_unlock (&settings->priv->property_lock);
+ return;
+ }
+
+ g_free (settings->priv->oauth2_endpoint_host);
+ settings->priv->oauth2_endpoint_host = e_util_strdup_strip (endpoint_host);
+
+ g_mutex_unlock (&settings->priv->property_lock);
+
+ g_object_notify (G_OBJECT (settings), "oauth2-endpoint-host");
+}
diff -up evolution-ews-3.28.5/src/server/camel-ews-settings.h.oauth2-endpoints evolution-ews-3.28.5/src/server/camel-ews-settings.h
--- evolution-ews-3.28.5/src/server/camel-ews-settings.h.oauth2-endpoints 2018-07-30 16:01:00.000000000 +0200
+++ evolution-ews-3.28.5/src/server/camel-ews-settings.h 2020-10-07 17:08:15.763562790 +0200
@@ -167,6 +167,20 @@ gchar * camel_ews_settings_dup_oauth2_r
void camel_ews_settings_set_oauth2_redirect_uri
(CamelEwsSettings *settings,
const gchar *redirect_uri);
+const gchar * camel_ews_settings_get_oauth2_resource_uri
+ (CamelEwsSettings *settings);
+gchar * camel_ews_settings_dup_oauth2_resource_uri
+ (CamelEwsSettings *settings);
+void camel_ews_settings_set_oauth2_resource_uri
+ (CamelEwsSettings *settings,
+ const gchar *resource_uri);
+const gchar * camel_ews_settings_get_oauth2_endpoint_host
+ (CamelEwsSettings *settings);
+gchar * camel_ews_settings_dup_oauth2_endpoint_host
+ (CamelEwsSettings *settings);
+void camel_ews_settings_set_oauth2_endpoint_host
+ (CamelEwsSettings *settings,
+ const gchar *endpoint_host);
G_END_DECLS
diff -up evolution-ews-3.28.5/src/server/e-ews-connection.c.oauth2-endpoints evolution-ews-3.28.5/src/server/e-ews-connection.c
--- evolution-ews-3.28.5/src/server/e-ews-connection.c.oauth2-endpoints 2020-10-07 17:08:43.161554484 +0200
+++ evolution-ews-3.28.5/src/server/e-ews-connection.c 2020-10-07 17:09:20.338543223 +0200
@@ -9914,13 +9914,7 @@ ews_connection_gather_auth_methods_cb (S
if (!has_bearer) {
/* Special-case Office365 OAuth2, because outlook.office365.com doesn't advertise Bearer */
- SoupURI *suri;
-
- suri = soup_message_get_uri (message);
- if (suri && soup_uri_get_host (suri) &&
- g_ascii_strcasecmp (soup_uri_get_host (suri), "outlook.office365.com") == 0) {
- async_data->items = g_slist_prepend (async_data->items, g_strdup ("Bearer"));
- }
+ async_data->items = g_slist_prepend (async_data->items, g_strdup ("Bearer"));
}
g_object_set_data (G_OBJECT (simple), EWS_OBJECT_KEY_AUTHS_GATHERED, GINT_TO_POINTER (1));
diff -up evolution-ews-3.28.5/src/server/e-oauth2-service-office365.c.oauth2-endpoints evolution-ews-3.28.5/src/server/e-oauth2-service-office365.c
--- evolution-ews-3.28.5/src/server/e-oauth2-service-office365.c.oauth2-endpoints 2020-10-07 17:08:15.761562791 +0200
+++ evolution-ews-3.28.5/src/server/e-oauth2-service-office365.c 2020-10-07 17:09:30.526540133 +0200
@@ -28,8 +28,6 @@
https://tsmatz.wordpress.com/2016/10/07/application-permission-with-v2-endpoint-and-microsoft-graph/
*/
-#define OFFICE365_RESOURCE "https://outlook.office.com"
-
struct _EOAuth2ServiceOffice365Private
{
GMutex string_cache_lock;
@@ -53,8 +51,10 @@ eos_office365_cache_string (EOAuth2Servi
if (!str)
return NULL;
- if (!*str)
+ if (!*str) {
+ g_free (str);
return "";
+ }
g_mutex_lock (&oauth2_office365->priv->string_cache_lock);
@@ -71,6 +71,24 @@ eos_office365_cache_string (EOAuth2Servi
return cached_str;
}
+static const gchar *
+eos_office365_get_endpoint_host (EOAuth2ServiceOffice365 *oauth2_office365,
+ CamelEwsSettings *ews_settings)
+{
+ if (ews_settings && camel_ews_settings_get_override_oauth2 (ews_settings)) {
+ gchar *endpoint_host;
+
+ endpoint_host = camel_ews_settings_dup_oauth2_endpoint_host (ews_settings);
+
+ if (endpoint_host && *endpoint_host)
+ return eos_office365_cache_string (oauth2_office365, endpoint_host);
+
+ g_free (endpoint_host);
+ }
+
+ return OFFICE365_ENDPOINT_HOST;
+}
+
static CamelEwsSettings *
eos_office365_get_camel_settings (ESource *source)
{
@@ -92,8 +110,7 @@ eos_office365_guess_can_process (EOAuth2
const gchar *hostname)
{
return e_oauth2_services_is_supported () &&
- protocol && g_ascii_strcasecmp (protocol, "ews") == 0 &&
- hostname && e_util_utf8_strstrcase (hostname, "outlook.office365.com");
+ protocol && g_ascii_strcasecmp (protocol, "ews") == 0;
}
static const gchar *
@@ -158,7 +175,8 @@ eos_office365_get_authentication_uri (EO
}
res = eos_office365_cache_string (oauth2_office365,
- g_strdup_printf ("https://login.microsoftonline.com/%s/oauth2/authorize",
+ g_strdup_printf ("https://%s/%s/oauth2/authorize",
+ eos_office365_get_endpoint_host (oauth2_office365, ews_settings),
tenant ? tenant : OFFICE365_TENANT));
g_free (tenant);
@@ -166,7 +184,10 @@ eos_office365_get_authentication_uri (EO
return res;
}
- return "https://login.microsoftonline.com/" OFFICE365_TENANT "/oauth2/authorize";
+ return eos_office365_cache_string (oauth2_office365,
+ g_strdup_printf ("https://%s/%s/oauth2/authorize",
+ eos_office365_get_endpoint_host (oauth2_office365, ews_settings),
+ OFFICE365_TENANT));
}
static const gchar *
@@ -188,7 +209,8 @@ eos_office365_get_refresh_uri (EOAuth2Se
}
res = eos_office365_cache_string (oauth2_office365,
- g_strdup_printf ("https://login.microsoftonline.com/%s/oauth2/token",
+ g_strdup_printf ("https://%s/%s/oauth2/token",
+ eos_office365_get_endpoint_host (oauth2_office365, ews_settings),
tenant ? tenant : OFFICE365_TENANT));
g_free (tenant);
@@ -196,7 +218,10 @@ eos_office365_get_refresh_uri (EOAuth2Se
return res;
}
- return "https://login.microsoftonline.com/" OFFICE365_TENANT "/oauth2/token";
+ return eos_office365_cache_string (oauth2_office365,
+ g_strdup_printf ("https://%s/%s/oauth2/token",
+ eos_office365_get_endpoint_host (oauth2_office365, ews_settings),
+ OFFICE365_TENANT));
}
static const gchar *
@@ -220,13 +245,67 @@ eos_office365_get_redirect_uri (EOAuth2S
if (redirect_uri)
return eos_office365_cache_string (oauth2_office365, redirect_uri);
+
+ if (e_ews_util_strcmp0 (camel_ews_settings_get_oauth2_endpoint_host (ews_settings), NULL) != 0) {
+ return eos_office365_cache_string (oauth2_office365,
+ g_strdup_printf ("https://%s/common/oauth2/nativeclient",
+ eos_office365_get_endpoint_host (oauth2_office365, ews_settings)));
+ }
}
res = OFFICE365_REDIRECT_URI;
if (res && *res)
return res;
- return "https://login.microsoftonline.com/common/oauth2/nativeclient";
+ return eos_office365_cache_string (oauth2_office365,
+ g_strdup_printf ("https://%s/common/oauth2/nativeclient",
+ eos_office365_get_endpoint_host (oauth2_office365, ews_settings)));
+}
+
+static const gchar *
+eos_office365_get_resource_uri (EOAuth2Service *service,
+ ESource *source)
+{
+ EOAuth2ServiceOffice365 *oauth2_office365 = E_OAUTH2_SERVICE_OFFICE365 (service);
+ CamelEwsSettings *ews_settings;
+
+ ews_settings = eos_office365_get_camel_settings (source);
+ if (ews_settings && camel_ews_settings_get_override_oauth2 (ews_settings)) {
+ gchar *resource_uri;
+
+ resource_uri = camel_ews_settings_dup_oauth2_resource_uri (ews_settings);
+
+ if (resource_uri && !*resource_uri) {
+ g_free (resource_uri);
+ resource_uri = NULL;
+ }
+
+ if (resource_uri)
+ return eos_office365_cache_string (oauth2_office365, resource_uri);
+ }
+
+ if (ews_settings) {
+ gchar *host_url;
+
+ host_url = camel_ews_settings_dup_hosturl (ews_settings);
+
+ if (host_url && *host_url) {
+ gchar *ptr;
+
+ ptr = strstr (host_url, "://");
+ ptr = ptr ? strchr (ptr + 3, '/') : NULL;
+
+ if (ptr) {
+ *ptr = '\0';
+
+ return eos_office365_cache_string (oauth2_office365, host_url);
+ }
+ }
+
+ g_free (host_url);
+ }
+
+ return OFFICE365_FALLBACK_RESOURCE_URI;
}
static void
@@ -238,7 +317,7 @@ eos_office365_prepare_authentication_uri
e_oauth2_service_util_set_to_form (uri_query, "response_mode", "query");
e_oauth2_service_util_set_to_form (uri_query, "prompt", "login");
- e_oauth2_service_util_set_to_form (uri_query, "resource", OFFICE365_RESOURCE);
+ e_oauth2_service_util_set_to_form (uri_query, "resource", eos_office365_get_resource_uri (service, source));
}
static gboolean
@@ -305,7 +384,7 @@ eos_office365_prepare_refresh_token_form
{
g_return_if_fail (form != NULL);
- e_oauth2_service_util_set_to_form (form, "resource", OFFICE365_RESOURCE);
+ e_oauth2_service_util_set_to_form (form, "resource", eos_office365_get_resource_uri (service, source));
e_oauth2_service_util_set_to_form (form, "redirect_uri", e_oauth2_service_get_redirect_uri (service, source));
}
@@ -369,3 +448,16 @@ e_oauth2_service_office365_type_register
{
e_oauth2_service_office365_register_type (type_module);
}
+
+gint
+e_ews_util_strcmp0 (const gchar *str1,
+ const gchar *str2)
+{
+ if (str1 && !*str1)
+ str1 = NULL;
+
+ if (str2 && !*str2)
+ str2 = NULL;
+
+ return g_strcmp0 (str1, str2);
+}
diff -up evolution-ews-3.28.5/src/server/e-oauth2-service-office365.h.oauth2-endpoints evolution-ews-3.28.5/src/server/e-oauth2-service-office365.h
--- evolution-ews-3.28.5/src/server/e-oauth2-service-office365.h.oauth2-endpoints 2018-07-30 16:01:00.000000000 +0200
+++ evolution-ews-3.28.5/src/server/e-oauth2-service-office365.h 2020-10-07 17:08:15.763562790 +0200
@@ -39,6 +39,8 @@
(G_TYPE_INSTANCE_GET_CLASS \
((obj), E_TYPE_OAUTH2_SERVICE_OFFICE365, EOAuth2ServiceOffice365Class))
+#define OFFICE365_FALLBACK_RESOURCE_URI "https://outlook.office365.com"
+
G_BEGIN_DECLS
typedef struct _EOAuth2ServiceOffice365 EOAuth2ServiceOffice365;
@@ -59,6 +61,9 @@ GType e_oauth2_service_office365_get_ty
void e_oauth2_service_office365_type_register
(GTypeModule *type_module);
+gint e_ews_util_strcmp0 (const gchar *str1,
+ const gchar *str2);
+
G_END_DECLS
#endif /* E_OAUTH2_SERVICE_OFFICE365_H */

@ -0,0 +1,119 @@
From bf0f75de095dc7ecb7171ab61009fab2631b4bee Mon Sep 17 00:00:00 2001
From: Luca Boccassi <luca.boccassi@microsoft.com>
Date: Tue, 2 Apr 2019 16:06:35 +0200
Subject: [PATCH] M!1 - Simplify OAuth2 for outlook.office365.com server
Two changes:
1) preset default tenant to "common"
2) do not pass 'scope' parameter in the requests, which is optional
and can cause errors like:
error:invalid_request description:AADSTS65002:
Consent between first party applications and resources must be
configured via preauthorization.
Closes https://gitlab.gnome.org/GNOME/evolution-ews/merge_requests/1
---
CMakeLists.txt | 2 +-
src/configuration/e-mail-config-ews-backend.c | 15 +++------------
src/server/e-oauth2-service-office365.c | 17 -----------------
3 files changed, 4 insertions(+), 30 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e8ea9875..dbc58832 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -180,7 +180,7 @@ endif(ENABLE_TESTS)
add_printable_variable(WITH_OFFICE365_TENANT "Office365.com OAuth 2.0 tenant" "")
if(WITH_OFFICE365_TENANT STREQUAL "")
- set(WITH_OFFICE365_TENANT "")
+ set(WITH_OFFICE365_TENANT "common")
endif(WITH_OFFICE365_TENANT STREQUAL "")
add_printable_variable(WITH_OFFICE365_CLIENT_ID "Office365.com OAuth 2.0 client ID" "")
diff --git a/src/configuration/e-mail-config-ews-backend.c b/src/configuration/e-mail-config-ews-backend.c
index fbf341b2..e62d3922 100644
--- a/src/configuration/e-mail-config-ews-backend.c
+++ b/src/configuration/e-mail-config-ews-backend.c
@@ -348,9 +348,9 @@ mail_config_ews_backend_insert_widgets (EMailConfigServiceBackend *backend,
G_BINDING_SYNC_CREATE);
mail_config_ews_backend_set_oauth2_tooltip (widget, OFFICE365_TENANT,
- /* Translators: 'Tenant' here means a term used by Microsoft to identify a company or organization in an Office 365 world.
+ /* Translators: 'Tenant' here means a term used by Microsoft to identify a company or organization in an Office 365 world. Same for 'common', it's a default URL path.
You probably do not want to translate it. More for example here: https://powerbi.microsoft.com/en-us/blog/what-is-a-tenant/ */
- _("There is not set any default tenant"),
+ _("Default tenant is “common“"),
/* Translators: 'Tenant' here means a term used by Microsoft to identify a company or organization in an Office 365 world.
You probably do not want to translate it. More for example here: https://powerbi.microsoft.com/en-us/blog/what-is-a-tenant/ */
g_strdup_printf (_("Default tenant is “%s”"), OFFICE365_TENANT));
@@ -586,23 +586,14 @@ mail_config_ews_backend_check_complete (EMailConfigServiceBackend *backend)
e_util_set_entry_issue_hint (priv->user_entry, correct ? NULL : _("User name cannot be empty"));
if (correct && camel_ews_settings_get_auth_mechanism (ews_settings) == EWS_AUTH_TYPE_OAUTH2) {
- const gchar *tenant, *client_id;
+ const gchar *client_id;
if (camel_ews_settings_get_override_oauth2 (ews_settings)) {
- tenant = camel_ews_settings_get_oauth2_tenant (ews_settings);
client_id = camel_ews_settings_get_oauth2_client_id (ews_settings);
} else {
- tenant = OFFICE365_TENANT;
client_id = OFFICE365_CLIENT_ID;
}
- correct = tenant && *tenant;
- complete = complete && correct;
-
- /* Translators: 'Tenant' here means a term used by Microsoft to identify a company or organization in an Office 365 world.
- You probably do not want to translate it. More for example here: https://powerbi.microsoft.com/en-us/blog/what-is-a-tenant/ */
- e_util_set_entry_issue_hint (priv->oauth2_tenant_entry, correct ? NULL : _("Tenant cannot be empty"));
-
correct = client_id && *client_id;
complete = complete && correct;
diff --git a/src/server/e-oauth2-service-office365.c b/src/server/e-oauth2-service-office365.c
index 4be84f6f..d660458c 100644
--- a/src/server/e-oauth2-service-office365.c
+++ b/src/server/e-oauth2-service-office365.c
@@ -30,21 +30,6 @@
#define OFFICE365_RESOURCE "https://outlook.office.com"
-#define OFFICE365_SCOPE "openid offline_access profile " \
- "Mail.ReadWrite " \
- "Mail.ReadWrite.Shared " \
- "Mail.Send " \
- "Mail.Send.Shared " \
- "Calendars.ReadWrite " \
- "Calendars.ReadWrite.Shared " \
- "Contacts.ReadWrite " \
- "Contacts.ReadWrite.Shared " \
- "Tasks.ReadWrite " \
- "Tasks.ReadWrite.Shared " \
- "MailboxSettings.ReadWrite " \
- "People.Read " \
- "User.ReadBasic.All"
-
struct _EOAuth2ServiceOffice365Private
{
GMutex string_cache_lock;
@@ -253,7 +238,6 @@ eos_office365_prepare_authentication_uri_query (EOAuth2Service *service,
e_oauth2_service_util_set_to_form (uri_query, "response_mode", "query");
e_oauth2_service_util_set_to_form (uri_query, "prompt", "login");
- e_oauth2_service_util_set_to_form (uri_query, "scope", OFFICE365_SCOPE);
e_oauth2_service_util_set_to_form (uri_query, "resource", OFFICE365_RESOURCE);
}
@@ -321,7 +305,6 @@ eos_office365_prepare_refresh_token_form (EOAuth2Service *service,
{
g_return_if_fail (form != NULL);
- e_oauth2_service_util_set_to_form (form, "scope", OFFICE365_SCOPE);
e_oauth2_service_util_set_to_form (form, "resource", OFFICE365_RESOURCE);
e_oauth2_service_util_set_to_form (form, "redirect_uri", e_oauth2_service_get_redirect_uri (service, source));
}
--
GitLab

@ -0,0 +1,75 @@
diff -up evolution-ews-3.28.5/src/calendar/e-cal-backend-ews.c.save-only-if-organizer evolution-ews-3.28.5/src/calendar/e-cal-backend-ews.c
--- evolution-ews-3.28.5/src/calendar/e-cal-backend-ews.c.save-only-if-organizer 2019-11-13 07:44:37.295278517 +0100
+++ evolution-ews-3.28.5/src/calendar/e-cal-backend-ews.c 2019-11-13 07:55:27.656269523 +0100
@@ -147,6 +147,41 @@ ecb_ews_get_collection_settings (ECalBac
return CAMEL_EWS_SETTINGS (settings);
}
+static GHashTable *
+ecb_ews_get_mail_aliases (ECalBackendEws *cbews)
+{
+ ESource *source;
+ ESourceRegistry *registry;
+ GHashTable *aliases = NULL;
+ GList *identities, *link;
+ const gchar *parent_uid;
+
+ source = e_backend_get_source (E_BACKEND (cbews));
+ parent_uid = e_source_get_parent (source);
+
+ if (!parent_uid || !*parent_uid)
+ return NULL;
+
+ registry = e_cal_backend_get_registry (E_CAL_BACKEND (cbews));
+ identities = e_source_registry_list_enabled (registry, E_SOURCE_EXTENSION_MAIL_IDENTITY);
+
+ for (link = identities; link; link = g_list_next (link)) {
+ ESource *mail_identity = link->data;
+
+ if (g_strcmp0 (parent_uid, e_source_get_parent (mail_identity)) == 0) {
+ ESourceMailIdentity *extension;
+
+ extension = e_source_get_extension (mail_identity, E_SOURCE_EXTENSION_MAIL_IDENTITY);
+ aliases = e_source_mail_identity_get_aliases_as_hash_table (extension);
+ break;
+ }
+ }
+
+ g_list_free_full (identities, g_object_unref);
+
+ return aliases;
+}
+
static void
ecb_ews_convert_error_to_edc_error (GError **perror)
{
@@ -1350,6 +1385,18 @@ ecb_ews_is_organizer (ECalBackendEws *cb
is_organizer = user_email && g_ascii_strcasecmp (email, user_email) == 0;
g_free (user_email);
+
+ if (!is_organizer) {
+ GHashTable *aliases;
+
+ aliases = ecb_ews_get_mail_aliases (cbews);
+
+ if (aliases) {
+ is_organizer = g_hash_table_contains (aliases, email);
+
+ g_hash_table_unref (aliases);
+ }
+ }
}
return is_organizer;
@@ -2595,6 +2642,10 @@ ecb_ews_save_component_sync (ECalMetaBac
g_slist_free_full (existing, g_object_unref);
g_slist_free_full (changed_instances, change_data_free);
g_slist_free_full (removed_instances, g_object_unref);
+ } else if (e_cal_component_has_organizer (master) &&
+ !ecb_ews_is_organizer (cbews, master)) {
+ success = FALSE;
+ g_propagate_error (error, EDC_ERROR_EX (PermissionDenied, _("Cannot create meetings organized by other users in an Exchange Web Services calendar.")));
} else {
GHashTable *removed_indexes;
EwsCalendarConvertData convert_data = { 0 };

File diff suppressed because it is too large Load Diff

@ -0,0 +1,22 @@
From 6d3dc9c50be654a9e250cfd53626f8526ff9eb70 Mon Sep 17 00:00:00 2001
From: Milan Crha <mcrha@redhat.com>
Date: Tue, 25 Sep 2018 16:20:12 +0200
Subject: Treat 'Unknown' ResponseType as Needs-Action
When creating a new meeting the attendees have returned by the server
an 'Unknown' ResponseType, which turned into 'Unknown' in the Evolution
UI (meeting editor). Treat it as Needs-Action instead.
diff --git a/src/calendar/e-cal-backend-ews.c b/src/calendar/e-cal-backend-ews.c
index bf995813..06d56fa0 100644
--- a/src/calendar/e-cal-backend-ews.c
+++ b/src/calendar/e-cal-backend-ews.c
@@ -311,7 +311,7 @@ ecb_ews_responsetype_to_partstat (const gchar *responsetype)
else if (g_ascii_strcasecmp (responsetype, "NoResponseReceived") == 0)
param = icalparameter_new_partstat (ICAL_PARTSTAT_NEEDSACTION);
else if (g_ascii_strcasecmp (responsetype, "Unknown") == 0)
- param = icalparameter_new_partstat (ICAL_PARTSTAT_NONE);
+ param = icalparameter_new_partstat (ICAL_PARTSTAT_NEEDSACTION);
if (!param)
param = icalparameter_new_partstat (ICAL_PARTSTAT_NONE);

@ -1,19 +1,63 @@
%undefine __cmake_in_source_build
%global json_glib_version 1.0.4
%global libmspack_version 0.4
%global libsoup_version 2.58
Name: evolution-ews
Version: 3.40.4
Release: 1%{?dist}
Version: 3.28.5
Release: 15%{?dist}.inferit
Group: Applications/Productivity
Summary: Evolution extension for Exchange Web Services
License: LGPLv2+
License: LGPLv2
URL: https://wiki.gnome.org/Apps/Evolution
Source: http://download.gnome.org/sources/%{name}/3.40/%{name}-%{version}.tar.xz
Source: http://download.gnome.org/sources/%{name}/3.28/%{name}-%{version}.tar.xz
%global eds_evo_version %{version}
Patch01: evolution-ews-3.28.5-import-event-timezone.patch
# https://gitlab.gnome.org/GNOME/evolution-ews/commit/dc50ba5a50a7b74f1d2710e5f860a7e81ab60d0b
Patch02: evolution-ews-3.28.5-disable-reminder-types.patch
# https://gitlab.gnome.org/GNOME/evolution-ews/commit/6d3dc9c50be654a9e250cfd53626f8526ff9eb70
Patch03: evolution-ews-3.28.5-unknown-responsetype-as-needs-action.patch
# https://gitlab.gnome.org/GNOME/evolution-ews/issues/19
Patch04: evolution-ews-3.28.5-contact-country-forgotten.patch
# https://gitlab.gnome.org/GNOME/evolution-ews/issues/21
Patch05: evolution-ews-3.28.5-meeting-with-attachment.patch
# https://gitlab.gnome.org/GNOME/evolution-ews/commit/f50530ad101b47d461a345ff2b8b295b86c05d3a
Patch06: evolution-ews-3.28.5-double-collection-backend-populate.patch
# RH bug #1696761
Patch07: evolution-ews-3.28.5-cve-2019-3890.patch
# RH bug #1741091
Patch08: evolution-ews-3.28.5-birthday-date.patch
# RH bug #1764818
Patch09: evolution-ews-3.28.5-sync-category-list.patch
# RH bug #1765005
Patch10: evolution-ews-3.28.5-save-only-if-organizer.patch
# RH bug #1886026
Patch11: evolution-ews-3.28.5-oauth2-simplify.patch
# RH bug #1885229
Patch12: evolution-ews-3.28.5-oauth2-endpoints.patch
# RH bug #1972749
Patch13: evolution-ews-3.28.5-cmake-variable-name-comparison.patch
# RH bug #2082245
Patch14: evolution-ews-3.28.5-autodiscover-improvements.patch
Patch15: 0001-I-250-Mail-Calendar-attachments-can-be-broken-by-the.patch
Patch16: 0002-deadlock-on-op-cancel.patch
# MSVSphere
Patch100: 0001-Added-Russian-translation.patch
Requires: evolution >= %{eds_evo_version}
Requires: evolution-data-server >= %{eds_evo_version}
Requires: %{name}-langpacks = %{version}-%{release}
@ -22,23 +66,21 @@ Requires: libmspack >= %{libmspack_version}
BuildRequires: cmake
BuildRequires: gcc
BuildRequires: intltool
BuildRequires: make
BuildRequires: pkgconfig(camel-1.2) >= %{eds_evo_version}
BuildRequires: pkgconfig(evolution-data-server-1.2) >= %{eds_evo_version}
BuildRequires: pkgconfig(evolution-mail-3.0) >= %{eds_evo_version}
BuildRequires: pkgconfig(evolution-shell-3.0) >= %{eds_evo_version}
BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(gtk+-3.0)
BuildRequires: pkgconfig(json-glib-1.0) >= %{json_glib_version}
BuildRequires: pkgconfig(libebackend-1.2) >= %{eds_evo_version}
BuildRequires: pkgconfig(libebook-1.2) >= %{eds_evo_version}
BuildRequires: pkgconfig(libecal-2.0) >= %{eds_evo_version}
BuildRequires: pkgconfig(libecal-1.2) >= %{eds_evo_version}
BuildRequires: pkgconfig(libedata-book-1.2) >= %{eds_evo_version}
BuildRequires: pkgconfig(libedata-cal-2.0) >= %{eds_evo_version}
BuildRequires: pkgconfig(libedata-cal-1.2) >= %{eds_evo_version}
BuildRequires: pkgconfig(libemail-engine) >= %{eds_evo_version}
BuildRequires: pkgconfig(libical)
BuildRequires: pkgconfig(libmspack) >= %{libmspack_version}
BuildRequires: pkgconfig(libsoup-2.4) >= %{libsoup_version}
BuildRequires: pkgconfig(libsoup-2.4)
%description
This package allows Evolution to interact with Microsoft Exchange servers,
@ -53,219 +95,125 @@ Requires: %{name} = %{version}-%{release}
This package contains translations for %{name}.
%prep
%autosetup -p1 -S gendiff
%setup -q
%patch01 -p1 -b .import-event-timezone
%patch02 -p1 -b .disable-reminder-types
%patch03 -p1 -b .unknown-responsetype-as-needs-action
%patch04 -p1 -b .contact-country-forgotten
%patch05 -p1 -b .meeting-with-attachment
%patch06 -p1 -b .double-collection-backend-populate
%patch07 -p1 -b .cve-2019-3890
%patch08 -p1 -b .birthday-date
%patch09 -p1 -b .sync-category-list
%patch10 -p1 -b .save-only-if-organizer
%patch11 -p1 -b .oauth2-simplify
%patch12 -p1 -b .oauth2-endpoints
%patch13 -p1 -b .cmake-variable-name-comparison
%patch14 -p1 -b .autodiscover-improvements
%patch15 -p1 -b .workaround-office365.com-bug
%patch16 -p1 -b .deadlock-on-cancel
%patch100 -p1
%build
mkdir _build
cd _build
export CFLAGS="$RPM_OPT_FLAGS -Wno-deprecated-declarations"
%cmake -G "Unix Makefiles"
%cmake_build
%cmake -G "Unix Makefiles" ..
make %{?_smp_mflags}
%install
%cmake_install
rm -rf $RPM_BUILD_ROOT
cd _build
make install DESTDIR=$RPM_BUILD_ROOT
%find_lang %{name}
%ldconfig_scriptlets
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
%files
%license COPYING
%doc NEWS README
%{_libdir}/evolution/modules/module-ews-configuration.so
%{_libdir}/evolution/modules/module-microsoft365-configuration.so
%{_libdir}/evolution-data-server/camel-providers/libcamelews.so
%{_libdir}/evolution-data-server/camel-providers/libcamelews.urls
%{_libdir}/evolution-data-server/camel-providers/libcamelmicrosoft365.so
%{_libdir}/evolution-data-server/camel-providers/libcamelmicrosoft365.urls
%{_libdir}/evolution-data-server/addressbook-backends/libebookbackendews.so
%{_libdir}/evolution-data-server/addressbook-backends/libebookbackendmicrosoft365.so
%{_libdir}/evolution-data-server/calendar-backends/libecalbackendews.so
%{_libdir}/evolution-data-server/calendar-backends/libecalbackendmicrosoft365.so
%{_libdir}/evolution-data-server/registry-modules/module-ews-backend.so
%{_libdir}/evolution-data-server/registry-modules/module-microsoft365-backend.so
%{_libdir}/evolution-ews/libcamelews-priv.so
%{_libdir}/evolution-ews/libevolution-ews.so
%{_libdir}/evolution-ews/libevolution-microsoft365.so
%{_datadir}/metainfo/org.gnome.Evolution-ews.metainfo.xml
%{_datadir}/evolution/errors/module-ews-configuration.error
%{_datadir}/evolution-data-server/ews/windowsZones.xml
%files langpacks -f %{name}.lang
%files langpacks -f _build/%{name}.lang
%changelog
* Fri Aug 13 2021 Milan Crha <mcrha@redhat.com> - 3.40.4-1
- Related: #1992450 (Update to 3.40.4)
* Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 3.40.3-2
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688
* Mon Jul 12 2021 Milan Crha <mcrha@redhat.com> - 3.40.3-1
- Related: #1981215 (Update to 3.40.3)
* Fri Jun 04 2021 Milan Crha <mcrha@redhat.com> - 3.40.2-1
- Related: #1967855 (Update to 3.40.2)
* Fri Apr 30 2021 Milan Crha <mcrha@redhat.com> - 3.40.1-1
- Related: #1952776 (Update to 3.40.1)
* Thu Apr 15 2021 Mohan Boddu <mboddu@redhat.com> - 3.40.0-2
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
* Fri Mar 19 2021 Milan Crha <mcrha@redhat.com> - 3.40.0-1
- Update to 3.40.0
* Fri Mar 12 2021 Milan Crha <mcrha@redhat.com> - 3.39.3-1
- Update to 3.39.3
* Fri Feb 12 2021 Milan Crha <mcrha@redhat.com> - 3.39.2-1
- Update to 3.39.2
* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 3.39.1-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
* Fri Jan 08 2021 Milan Crha <mcrha@redhat.com> - 3.39.1-1
- Update to 3.39.1
* Fri Nov 20 2020 Milan Crha <mcrha@redhat.com> - 3.38.2-1
- Update to 3.38.2
* Fri Oct 02 2020 Milan Crha <mcrha@redhat.com> - 3.38.1-1
- Update to 3.38.1
* Fri Sep 11 2020 Milan Crha <mcrha@redhat.com> - 3.38.0-1
- Update to 3.38.0
* Fri Sep 04 2020 Milan Crha <mcrha@redhat.com> - 3.37.92-1
- Update to 3.37.92
* Fri Aug 07 2020 Milan Crha <mcrha@redhat.com> - 3.37.90-1
- Update to 3.37.90
* Mon Jul 27 2020 Fedora Release Engineering <releng@fedoraproject.org> - 3.37.3-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
* Fri Jul 03 2020 Milan Crha <mcrha@redhat.com> - 3.37.3-1
- Update to 3.37.3
* Fri May 29 2020 Milan Crha <mcrha@redhat.com> - 3.37.2-1
- Update to 3.37.2
* Fri Apr 24 2020 Milan Crha <mcrha@redhat.com> - 3.37.1-1
- Update to 3.37.1
* Fri Mar 27 2020 Milan Crha <mcrha@redhat.com> - 3.36.1-1
- Update to 3.36.1
* Fri Mar 06 2020 Milan Crha <mcrha@redhat.com> - 3.36.0-1
- Update to 3.36.0
* Fri Feb 28 2020 Milan Crha <mcrha@redhat.com> - 3.35.92-1
- Update to 3.35.92
* Fri Feb 14 2020 Milan Crha <mcrha@redhat.com> - 3.35.91-1
- Update to 3.35.91
* Fri Jan 31 2020 Milan Crha <mcrha@redhat.com> - 3.35.90-1
- Update to 3.35.90
* Tue Jan 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 3.35.3-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
* Fri Jan 03 2020 Milan Crha <mcrha@redhat.com> - 3.35.3-1
- Update to 3.35.3
* Fri Nov 22 2019 Milan Crha <mcrha@redhat.com> - 3.35.2-1
- Update to 3.35.2
* Fri Oct 11 2019 Milan Crha <mcrha@redhat.com> - 3.35.1-1
- Update to 3.35.1
* Mon Oct 07 2019 Milan Crha <mcrha@redhat.com> - 3.34.1-1
- Update to 3.34.1
* Mon Sep 09 2019 Milan Crha <mcrha@redhat.com> - 3.34.0-1
- Update to 3.34.0
* Mon Sep 02 2019 Milan Crha <mcrha@redhat.com> - 3.33.92-1
- Update to 3.33.92
* Mon Aug 19 2019 Milan Crha <mcrha@redhat.com> - 3.33.91-1
- Update to 3.33.91
* Mon Aug 05 2019 Milan Crha <mcrha@redhat.com> - 3.33.90-1
- Update to 3.33.90
* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 3.33.4-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
* Mon Jul 15 2019 Milan Crha <mcrha@redhat.com> - 3.33.4-1
- Update to 3.33.4
* Mon Jun 17 2019 Milan Crha <mcrha@redhat.com> - 3.33.3-1
- Update to 3.33.3
* Mon May 20 2019 Milan Crha <mcrha@redhat.com> - 3.33.2-1
- Update to 3.33.2
* Mon Apr 22 2019 Milan Crha <mcrha@redhat.com> - 3.33.1-1
- Update to 3.33.1
* Mon Apr 08 2019 Milan Crha <mcrha@redhat.com> - 3.32.1-1
- Update to 3.32.1
* Mon Mar 11 2019 Milan Crha <mcrha@redhat.com> - 3.32.0-1
- Update to 3.32.0
* Tue Apr 16 2024 Sergey Cherevko <s.cherevko@msvsphere-os.ru> - 3.28.5-15.inferit
- Added Russian translation
- Rebuilt for MSVSphere 8.10 beta
* Mon Feb 18 2019 Milan Crha <mcrha@redhat.com> - 3.31.91-1
- Update to 3.31.91
* Thu Feb 08 2024 Milan Crha <mcrha@redhat.com> - 3.28.5-15
- Resolves: RHEL-24829 (Release queue lock as soon as possible in ews_next_request())
* Mon Feb 04 2019 Milan Crha <mcrha@redhat.com> - 3.31.90-1
- Update to 3.31.90
* Wed Dec 13 2023 Milan Crha <mcrha@redhat.com> - 3.28.5-14
- Resolves: RHEL-19376 (Backport upstream patch to workaround broken text/calendar mail attachments by the server)
* Thu Jan 31 2019 Fedora Release Engineering <releng@fedoraproject.org> - 3.31.4-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
* Fri May 06 2022 Milan Crha <mcrha@redhat.com> - 3.28.5-13
- Related: #2082245 (Fix issues in the patch found by Coverity scan)
* Mon Jan 07 2019 Milan Crha <mcrha@redhat.com> - 3.31.4-1
- Update to 3.31.4
* Fri May 06 2022 Milan Crha <mcrha@redhat.com> - 3.28.5-12
- Resolves: #2082245 (Backport fixes to improve autodiscovery)
* Mon Dec 10 2018 Milan Crha <mcrha@redhat.com> - 3.31.3-1
- Update to 3.31.3
* Wed Jun 16 2021 Milan Crha <mcrha@redhat.com> - 3.28.5-11
- Resolves: #1972749 (PrintableOptions.cmake: Correct variable name comparison)
* Mon Nov 12 2018 Milan Crha <mcrha@redhat.com> - 3.31.2-1
- Update to 3.31.2
* Wed Oct 07 2020 Milan Crha <mcrha@redhat.com> - 3.28.5-10
- Resolves: #1886026 (Simplify OAuth2 for outlook.office365.com server)
- Resolves: #1885229 (Allow change of the Microsoft 365 OAuth2 endpoints)
* Mon Oct 08 2018 Milan Crha <mcrha@redhat.com> - 3.31.1-1
- Update to 3.31.1
* Wed Nov 13 2019 Milan Crha <mcrha@redhat.com> - 3.28.5-9
- Remove patch for RH bug #1765005 (Reject creating meetings organized by other users)
* Mon Sep 24 2018 Milan Crha <mcrha@redhat.com> - 3.30.1-1
- Update to 3.30.1
* Tue Oct 29 2019 Milan Crha <mcrha@redhat.com> - 3.28.5-8
- Remove patch for RH bug #1765005 (Send meeting change notifications only if being the organizer)
* Mon Sep 03 2018 Milan Crha <mcrha@redhat.com> - 3.30.0-1
- Update to 3.30.0
* Thu Oct 24 2019 Milan Crha <mcrha@redhat.com> - 3.28.5-7
- Add patch for RH bug #1764818 (Sync CategoryList with mail Labels)
- Add patch for RH bug #1765005 (Send meeting change notifications only if being the organizer)
* Mon Aug 27 2018 Milan Crha <mcrha@redhat.com> - 3.29.92-1
- Update to 3.29.92
* Wed Oct 23 2019 Milan Crha <mcrha@redhat.com> - 3.28.5-6
- Add patch for RH bug #1741091 (Birthday date of Contact depends on system timezone)
* Mon Aug 13 2018 Milan Crha <mcrha@redhat.com> - 3.29.91-1
- Update to 3.29.91
* Mon May 27 2019 Milan Crha <mcrha@redhat.com> - 3.28.5-5
- Rebuild with added gating
* Mon Jul 30 2018 Milan Crha <mcrha@redhat.com> - 3.29.90-1
- Update to 3.29.90
* Mon Apr 15 2019 Milan Crha <mcrha@redhat.com> - 3.28.5-4
- Add patch for RH bug #1696761 (CVE-2019-3890 - SSL Certificates are not validated)
* Mon Jul 16 2018 Milan Crha <mcrha@redhat.com> - 3.29.4-1
- Update to 3.29.4
* Mon Oct 01 2018 Milan Crha <mcrha@redhat.com> - 3.28.5-3
- Add "Enable only Notification reminders in the calendar" upstream fix
- Add "Treat 'Unknown' ResponseType as Needs-Action" upstream fix
- Add "I#19 - Country is forgotten along the way to exchange server" upstream fix
- Add "I#21 - Meeting with attachment cannot be saved in 2010" upstream fix
- Add "Collection backend schedules two 'populate' requests after going online" upstream fix
* Fri Jul 13 2018 Fedora Release Engineering <releng@fedoraproject.org> - 3.29.3-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
* Tue Sep 04 2018 Milan Crha <mcrha@redhat.com> - 3.28.5-2
- Add patch for RH bug #1625162 (Calendar invites added with the wrong time zone)
* Mon Jun 18 2018 Milan Crha <mcrha@redhat.com> - 3.29.3-1
- Update to 3.29.3
* Mon Jul 30 2018 Milan Crha <mcrha@redhat.com> - 3.28.5-1
- Update to 3.28.5
* Mon May 21 2018 Milan Crha <mcrha@redhat.com> - 3.29.2-1
- Update to 3.29.2
* Mon Jul 16 2018 Milan Crha <mcrha@redhat.com> - 3.28.4-1
- Update to 3.28.4
* Mon Apr 16 2018 Milan Crha <mcrha@redhat.com> - 3.29.1-1
- Update to 3.29.1
* Mon Jun 18 2018 Milan Crha <mcrha@redhat.com> - 3.28.3-1
- Update to 3.28.3
* Mon Apr 09 2018 Milan Crha <mcrha@redhat.com> - 3.28.1-1
- Update to 3.28.1

Loading…
Cancel
Save