import evolution-ews-3.28.5-15.el8

c8-beta imports/c8-beta/evolution-ews-3.28.5-15.el8
MSVSphere Packaging Team 9 months ago
commit e85884af32

@ -0,0 +1 @@
22caa0a3798f51757f88fd19c9ca74284f62b0d3 SOURCES/evolution-ews-3.28.5.tar.xz

1
.gitignore vendored

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

@ -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);

@ -0,0 +1,610 @@
%global libmspack_version 0.4
Name: evolution-ews
Version: 3.28.5
Release: 15%{?dist}
Group: Applications/Productivity
Summary: Evolution extension for Exchange Web Services
License: LGPLv2
URL: https://wiki.gnome.org/Apps/Evolution
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
Requires: evolution >= %{eds_evo_version}
Requires: evolution-data-server >= %{eds_evo_version}
Requires: %{name}-langpacks = %{version}-%{release}
Requires: libmspack >= %{libmspack_version}
BuildRequires: cmake
BuildRequires: gcc
BuildRequires: intltool
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(libebackend-1.2) >= %{eds_evo_version}
BuildRequires: pkgconfig(libebook-1.2) >= %{eds_evo_version}
BuildRequires: pkgconfig(libecal-1.2) >= %{eds_evo_version}
BuildRequires: pkgconfig(libedata-book-1.2) >= %{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)
%description
This package allows Evolution to interact with Microsoft Exchange servers,
versions 2007 and later, through its Exchange Web Services (EWS) interface.
%package langpacks
Summary: Translations for %{name}
BuildArch: noarch
Requires: %{name} = %{version}-%{release}
%description langpacks
This package contains translations for %{name}.
%prep
%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
%build
mkdir _build
cd _build
export CFLAGS="$RPM_OPT_FLAGS -Wno-deprecated-declarations"
%cmake -G "Unix Makefiles" ..
make %{?_smp_mflags}
%install
rm -rf $RPM_BUILD_ROOT
cd _build
make install DESTDIR=$RPM_BUILD_ROOT
%find_lang %{name}
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
%files
%license COPYING
%doc NEWS README
%{_libdir}/evolution/modules/module-ews-configuration.so
%{_libdir}/evolution-data-server/camel-providers/libcamelews.so
%{_libdir}/evolution-data-server/camel-providers/libcamelews.urls
%{_libdir}/evolution-data-server/addressbook-backends/libebookbackendews.so
%{_libdir}/evolution-data-server/calendar-backends/libecalbackendews.so
%{_libdir}/evolution-data-server/registry-modules/module-ews-backend.so
%{_libdir}/evolution-ews/libcamelews-priv.so
%{_libdir}/evolution-ews/libevolution-ews.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 _build/%{name}.lang
%changelog
* 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())
* 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)
* Fri May 06 2022 Milan Crha <mcrha@redhat.com> - 3.28.5-13
- Related: #2082245 (Fix issues in the patch found by Coverity scan)
* Fri May 06 2022 Milan Crha <mcrha@redhat.com> - 3.28.5-12
- Resolves: #2082245 (Backport fixes to improve autodiscovery)
* Wed Jun 16 2021 Milan Crha <mcrha@redhat.com> - 3.28.5-11
- Resolves: #1972749 (PrintableOptions.cmake: Correct variable name comparison)
* 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)
* 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)
* 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)
* 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)
* 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 May 27 2019 Milan Crha <mcrha@redhat.com> - 3.28.5-5
- Rebuild with added gating
* 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 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
* 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 Jul 30 2018 Milan Crha <mcrha@redhat.com> - 3.28.5-1
- Update to 3.28.5
* Mon Jul 16 2018 Milan Crha <mcrha@redhat.com> - 3.28.4-1
- Update to 3.28.4
* 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
* Mon Mar 12 2018 Milan Crha <mcrha@redhat.com> - 3.28.0-1
- Update to 3.28.0
* Mon Mar 05 2018 Milan Crha <mcrha@redhat.com> - 3.27.92-1
- Update to 3.27.92
* Mon Feb 19 2018 Milan Crha <mcrha@redhat.com> - 3.27.91-1
- Update to 3.27.91
* Tue Feb 06 2018 Milan Crha <mcrha@redhat.com> - 3.27.90-1
- Update to 3.27.90
* Mon Jan 08 2018 Milan Crha <mcrha@redhat.com> - 3.27.4-1
- Update to 3.27.4
* Mon Dec 11 2017 Milan Crha <mcrha@redhat.com> - 3.27.3-1
- Update to 3.27.3
* Mon Nov 13 2017 Milan Crha <mcrha@redhat.com> - 3.27.2-1
- Update to 3.27.2
* Wed Nov 08 2017 Milan Crha <mcrha@redhat.com> - 3.27.1-2
- Rebuild for newer libical
* Mon Oct 16 2017 Milan Crha <mcrha@redhat.com> - 3.27.1-1
- Update to 3.27.1
* Mon Oct 02 2017 Milan Crha <mcrha@redhat.com> - 3.26.1-1
- Update to 3.26.1
* Mon Sep 11 2017 Milan Crha <mcrha@redhat.com> - 3.26.0-1
- Update to 3.26.0
* Mon Sep 04 2017 Milan Crha <mcrha@redhat.com> - 3.25.92.2-1
- Update to 3.25.92.2
* Mon Sep 04 2017 Milan Crha <mcrha@redhat.com> - 3.25.92-1
- Update to 3.25.92
* Tue Aug 22 2017 Ville Skyttä <ville.skytta@iki.fi> - 3.25.91-2
- Install COPYING as %%license
* Mon Aug 21 2017 Milan Crha <mcrha@redhat.com> - 3.25.91-1
- Update to 3.25.91
* Mon Aug 07 2017 Milan Crha <mcrha@redhat.com> - 3.25.90-1
- Update to 3.25.90
* Wed Aug 02 2017 Fedora Release Engineering <releng@fedoraproject.org> - 3.25.4-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild
* Mon Jul 31 2017 Florian Weimer <fweimer@redhat.com> - 3.25.4-3
- Rebuild with binutils fix for ppc64le (#1475636)
* Wed Jul 26 2017 Fedora Release Engineering <releng@fedoraproject.org> - 3.25.4-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
* Mon Jul 17 2017 Milan Crha <mcrha@redhat.com> - 3.25.4-1
- Update to 3.25.4
* Mon Jun 19 2017 Milan Crha <mcrha@redhat.com> - 3.25.3-1
- Update to 3.25.3
* Mon May 22 2017 Milan Crha <mcrha@redhat.com> - 3.25.2-1
- Update to 3.25.2
* Thu Apr 27 2017 Milan Crha <mcrha@redhat.com> - 3.25.1-2
- Split translations into separate package
* Mon Apr 24 2017 Milan Crha <mcrha@redhat.com> - 3.25.1-1
- Update to 3.25.1
* Mon Apr 10 2017 Milan Crha <mcrha@redhat.com> - 3.24.1-1
- Update to 3.24.1
* Mon Mar 20 2017 Milan Crha <mcrha@redhat.com> - 3.24.0-1
- Update to 3.24.0
* Mon Mar 13 2017 Milan Crha <mcrha@redhat.com> - 3.23.92-1
- Update to 3.23.92
* Mon Feb 27 2017 Milan Crha <mcrha@redhat.com> - 3.23.91-1
- Update to 3.23.91
* Mon Feb 13 2017 Milan Crha <mcrha@redhat.com> - 3.23.90-1
- Update to 3.23.90
* Fri Feb 10 2017 Fedora Release Engineering <releng@fedoraproject.org> - 3.23.4-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild
* Mon Jan 16 2017 Milan Crha <mcrha@redhat.com> - 3.23.4-1
- Update to 3.23.4
* Mon Dec 12 2016 Milan Crha <mcrha@redhat.com> - 3.23.3-1
- Update to 3.23.3
* Mon Nov 21 2016 Milan Crha <mcrha@redhat.com> - 3.23.2-1
- Update to 3.23.2
* Mon Oct 24 2016 Milan Crha <mcrha@redhat.com> - 3.23.1-1
- Update to 3.23.1
* Mon Oct 10 2016 Milan Crha <mcrha@redhat.com> - 3.22.1-1
- Update to 3.22.1
* Mon Sep 19 2016 Milan Crha <mcrha@redhat.com> - 3.22.0-1
- Update to 3.22.0
* Mon Sep 12 2016 Milan Crha <mcrha@redhat.com> - 3.21.92-1
- Update to 3.21.92
* Mon Aug 29 2016 Milan Crha <mcrha@redhat.com> - 3.21.91-1
- Update to 3.21.91
* Mon Aug 15 2016 Milan Crha <mcrha@redhat.com> - 3.21.90-1
- Update to 3.21.90
* Mon Jul 18 2016 Milan Crha <mcrha@redhat.com> - 3.21.4-1
- Update to 3.21.4
* Mon Jun 20 2016 Milan Crha <mcrha@redhat.com> - 3.21.3-1
- Update to 3.21.3
* Mon May 23 2016 Milan Crha <mcrha@redhat.com> - 3.21.2-1
- Update to 3.21.2
* Mon Apr 25 2016 Milan Crha <mcrha@redhat.com> - 3.21.1-1
- Update to 3.21.1
* Mon Apr 11 2016 Milan Crha <mcrha@redhat.com> - 3.20.1-1
- Update to 3.20.1
* Mon Mar 21 2016 Milan Crha <mcrha@redhat.com> - 3.20.0-1
- Update to 3.20.0
* Mon Mar 14 2016 Milan Crha <mcrha@redhat.com> - 3.19.92-1
- Update to 3.19.92
* Mon Feb 29 2016 Milan Crha <mcrha@redhat.com> - 3.19.91-1
- Update to 3.19.91
* Mon Feb 15 2016 Milan Crha <mcrha@redhat.com> - 3.19.90-1
- Update to 3.19.90
* Wed Feb 03 2016 Fedora Release Engineering <releng@fedoraproject.org> - 3.19.4-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild
* Mon Jan 18 2016 David Tardon <dtardon@redhat.com> - 3.19.4-2
- rebuild for libical 2.0.0
* Mon Jan 18 2016 Milan Crha <mcrha@redhat.com> - 3.19.4-1
- Update to 3.19.4
* Mon Dec 14 2015 Milan Crha <mcrha@redhat.com> - 3.19.3-1
- Update to 3.19.3
* Mon Nov 23 2015 Milan Crha <mcrha@redhat.com> - 3.19.2-1
- Update to 3.19.2
* Mon Oct 26 2015 Milan Crha <mcrha@redhat.com> - 3.19.1-1
- Update to 3.19.1
* Mon Oct 12 2015 Milan Crha <mcrha@redhat.com> - 3.18.1-1
- Update to 3.18.1
* Mon Sep 21 2015 Milan Crha <mcrha@redhat.com> - 3.18.0-1
- Update to 3.18.0
* Mon Sep 14 2015 Milan Crha <mcrha@redhat.com> - 3.17.92-1
- Update to 3.17.92
* Mon Aug 31 2015 Milan Crha <mcrha@redhat.com> - 3.17.91-1
- Update to 3.17.91
* Mon Aug 17 2015 Milan Crha <mcrha@redhat.com> - 3.17.90-1
- Update to 3.17.90
* Mon Jul 20 2015 Milan Crha <mcrha@redhat.com> - 3.17.4-1
- Update to 3.17.4
* Mon Jun 22 2015 Milan Crha <mcrha@redhat.com> - 3.17.3-1
- Update to 3.17.3
* Wed Jun 17 2015 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.17.2-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild
* Mon May 25 2015 Milan Crha <mcrha@redhat.com> - 3.17.2-1
- Update to 3.17.2
* Mon Apr 27 2015 Milan Crha <mcrha@redhat.com> - 3.17.1-1
- Update to 3.17.1
* Mon Apr 13 2015 Milan Crha <mcrha@redhat.com> - 3.16.1-1
- Update to 3.16.1
* Mon Mar 23 2015 Milan Crha <mcrha@redhat.com> - 3.16.0-1
- Update to 3.16.0
* Mon Mar 16 2015 Milan Crha <mcrha@redhat.com> - 3.15.92-1
- Update to 3.15.92
* Mon Mar 02 2015 Milan Crha <mcrha@redhat.com> - 3.15.91-1
- Update to 3.15.91
* Mon Feb 16 2015 Milan Crha <mcrha@redhat.com> - 3.13.90-1
- Update to 3.13.90
* Mon Jan 26 2015 Milan Crha <mcrha@redhat.com> - 3.13.10-1
- Update to 3.13.10
* Mon Dec 22 2014 Milan Crha <mcrha@redhat.com> - 3.13.9-1
- Update to 3.13.9
* Mon Nov 24 2014 Milan Crha <mcrha@redhat.com> - 3.13.8-1
- Update to 3.13.8
* Mon Oct 27 2014 Milan Crha <mcrha@redhat.com> - 3.13.7-1
- Update to 3.13.7
* Mon Sep 22 2014 Milan Crha <mcrha@redhat.com> - 3.13.6-1
- Update to 3.13.6
* Mon Aug 25 2014 Milan Crha <mcrha@redhat.com> - 3.13.5-1
- Update to 3.13.5
* Sat Aug 16 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.13.4-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild
* Wed Jul 30 2014 Milan Crha <mcrha@redhat.com> - 3.13.4-1
- Update to 3.13.4
* Mon Jul 14 2014 Milan Crha <mcrha@redhat.com> - 3.12.4-1
- Update to 3.12.4
* Mon Jun 09 2014 Milan Crha <mcrha@redhat.com> - 3.12.3-1
- Update to 3.12.3
* Sat Jun 07 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.12.2-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild
* Mon May 12 2014 Milan Crha <mcrha@redhat.com> - 3.12.2-1
- Update to 3.12.2
* Mon Apr 14 2014 Milan Crha <mcrha@redhat.com> - 3.12.1-1
- Update to 3.12.1
* Mon Mar 24 2014 Milan Crha <mcrha@redhat.com> - 3.12.0-1
- Update to 3.12.0
* Mon Mar 17 2014 Milan Crha <mcrha@redhat.com> - 3.11.92-1
- Update to 3.11.92
* Mon Mar 03 2014 Milan Crha <mcrha@redhat.com> - 3.11.91-1
- Update to 3.11.91
* Mon Feb 17 2014 Milan Crha <mcrha@redhat.com> - 3.11.90-1
- Update to 3.11.90
* Mon Feb 03 2014 Milan Crha <mcrha@redhat.com> - 3.11.5-1
- Update to 3.11.5
* Mon Jan 13 2014 Milan Crha <mcrha@redhat.com> - 3.11.4-1
- Update to 3.11.4
* Sun Dec 01 2013 Matthew Barnes <mbarnes@redhat.com> - 3.11.2-3
- Add $RPM_OPT_FLAGS to $CFLAGS (RH bug #1035930)
* Thu Nov 21 2013 Milan Crha <mcrha@redhat.com> - 3.11.2-2
- Rebuild for new libical (RH bug #1023020)
* Mon Nov 18 2013 Milan Crha <mcrha@redhat.com> - 3.11.2-1
- Update to 3.11.2
- Disable compiler warnings about deprecated symbols
* Tue Oct 22 2013 Matthew Barnes <mbarnes@redhat.com> - 3.11.1-1
- Update to 3.11.1
* Mon Oct 14 2013 Milan Crha <mcrha@redhat.com> - 3.10.1-1
- Update to 3.10.1
* Mon Sep 23 2013 Milan Crha <mcrha@redhat.com> - 3.10.0-1
- Update to 3.10.0
* Mon Sep 16 2013 Milan Crha <mcrha@redhat.com> - 3.9.92-1
- Update to 3.9.92
* Mon Sep 02 2013 Milan Crha <mcrha@redhat.com> - 3.9.91-1
- Update to 3.9.91
* Mon Aug 19 2013 Milan Crha <mcrha@redhat.com> - 3.9.90-1
- Update to 3.9.90
* Mon Jul 29 2013 Milan Crha <mcrha@redhat.com> - 3.9.5-1
- Update to 3.9.5
* Mon Jul 08 2013 Milan Crha <mcrha@redhat.com> - 3.9.4-1
- Update to 3.9.4
* Mon Jun 17 2013 Milan Crha <mcrha@redhat.com> - 3.9.3-1
- Update to 3.9.3
- Add dependency on libmspack 0.4+
* Mon May 27 2013 Milan Crha <mcrha@redhat.com> - 3.9.2-1
- Update to 3.9.2
* Sat May 25 2013 Rex Dieter <rdieter@fedoraproject.org> 3.9.1-2
- rebuild (libical)
* Mon Apr 29 2013 Milan Crha <mcrha@redhat.com> - 3.9.1-1
- Update to 3.9.1
* Mon Mar 25 2013 Milan Crha <mcrha@redhat.com> - 3.8.0-1
- Update to 3.8.0
* Mon Mar 18 2013 Milan Crha <mcrha@redhat.com> - 3.7.92-1
- Update to 3.7.92
* Mon Mar 04 2013 Milan Crha <mcrha@redhat.com> - 3.7.91-1
- Update to 3.7.91
* Mon Feb 18 2013 Milan Crha <mcrha@redhat.com> - 3.7.90-1
- Update to 3.7.90
* Mon Feb 04 2013 Milan Crha <mcrha@redhat.com> - 3.7.5-1
- Update to 3.7.5
* Mon Jan 14 2013 Milan Crha <mcrha@redhat.com> - 3.7.4-1
- Update to 3.7.4
* Thu Dec 20 2012 Matthew Barnes <mbarnes@redhat.com> - 3.7.3.1-1
- Update to 3.7.3.1
* Mon Nov 19 2012 Milan Crha <mcrha@redhat.com> - 3.7.2-1
- Update to 3.7.2
* Mon Oct 22 2012 Milan Crha <mcrha@redhat.com> - 3.7.1-1
- Update to 3.7.1
* Mon Sep 17 2012 Milan Crha <mcrha@redhat.com> - 3.5.92-1
- Update to 3.5.92
* Mon Sep 03 2012 Milan Crha <mcrha@redhat.com> - 3.5.91-1
- Update to 3.5.91
- Remove patch for new xmlOutputBuffer API (fixed upstream)
* Mon Aug 20 2012 Milan Crha <mcrha@redhat.com> - 3.5.90-1
- Update to 3.5.90
- Add patch for new xmlOutputBuffer API
* Mon Aug 06 2012 Milan Crha <mcrha@redhat.com> - 3.5.5-1
- Update to 3.5.5
* Thu Jul 19 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.5.4-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild
* Mon Jul 16 2012 Milan Crha <mcrha@redhat.com> - 3.5.4-1
- Update to 3.5.4
* Mon Jun 25 2012 Matthew Barnes <mbarnes@redhat.com> - 3.5.3-1
- Update to 3.5.3
* Mon Jun 04 2012 Milan Crha <mcrha@redhat.com> - 3.5.2-1
- Update to 3.5.2
* Sun Apr 29 2012 Matthew Barnes <mbarnes@redhat.com> - 3.5.1-1
- Update to 3.5.1
* Mon Mar 26 2012 Milan Crha <mcrha@redhat.com> - 3.4.0-1
- Update to 3.4.0
* Mon Mar 19 2012 Milan Crha <mcrha@redhat.com> - 3.3.92-1
- Update to 3.3.92
* Tue Mar 06 2012 Milan Crha <mcrha@redhat.com> - 3.3.91-1
- Update to 3.3.91
* Mon Feb 20 2012 Milan Crha <mcrha@redhat.com> - 3.3.90-1
- Update to 3.3.90
* Mon Feb 06 2012 Milan Crha <mcrha@redhat.com> - 3.3.5-1
- Update to 3.3.5
* Mon Jan 16 2012 Milan Crha <mcrha@redhat.com> - 3.3.4-1
- Update to 3.3.4
* Fri Jan 13 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.3.3-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild
* Mon Dec 19 2011 Milan Crha <mcrha@redhat.com> - 3.3.3-1
- Update to 3.3.3
- Removed the last patch (fixed upstream)
* Mon Nov 21 2011 Milan Crha <mcrha@redhat.com> - 3.3.2-1
- Update to 3.3.2
- Removed obsolete patches (fixed upstream)
* Mon Nov 07 2011 Matthew Barnes <mbarnes@redhat.com> - 3.3.1-1
- Initial packaging for Fedora 17.
Loading…
Cancel
Save