Hello community, here is the log from the commit of package evolution-data-server for openSUSE:Factory checked in at 2016-02-22 08:56:16 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/evolution-data-server (Old) and /work/SRC/openSUSE:Factory/.evolution-data-server.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "evolution-data-server" Changes: -------- --- /work/SRC/openSUSE:Factory/evolution-data-server/evolution-data-server.changes 2016-01-23 01:03:29.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.evolution-data-server.new/evolution-data-server.changes 2016-02-22 08:56:17.000000000 +0100 @@ -1,0 +2,16 @@ +Mon Feb 15 19:30:24 UTC 2016 - zai...@opensuse.org + +- Update to version 3.18.5: + + Use icaltzutil_set_exact_vtimezones_support(), if available. + + [IMAPx]: + - Connection could be used multiple times at once in certain + cases. + - Stop IDLE gracefully. + - Change how IDLE is handled. + - Remove runtime check from + imapx_conn_manager_dec_mailbox_hash(). + - Crash in imapx_free_capability(). + - Prefer graceful IDLE stop than forced reconnect. + + Bugs fixed: bgo#748996, bgo#759153, bgo#761527, bgo#760951. + +------------------------------------------------------------------- Old: ---- evolution-data-server-3.18.4.tar.xz New: ---- evolution-data-server-3.18.5.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ evolution-data-server.spec ++++++ --- /var/tmp/diff_new_pack.wHsEtJ/_old 2016-02-22 08:56:18.000000000 +0100 +++ /var/tmp/diff_new_pack.wHsEtJ/_new 2016-02-22 08:56:18.000000000 +0100 @@ -33,7 +33,7 @@ Name: evolution-data-server %define _evo_version 3.18 -Version: 3.18.4 +Version: 3.18.5 Release: 0 Summary: Evolution Data Server License: LGPL-2.1+ ++++++ evolution-data-server-3.18.4.tar.xz -> evolution-data-server-3.18.5.tar.xz ++++++ ++++ 1650 lines of diff (skipped) ++++ retrying with extended exclude list diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/evolution-data-server-3.18.4/NEWS new/evolution-data-server-3.18.5/NEWS --- old/evolution-data-server-3.18.4/NEWS 2016-01-18 12:55:05.000000000 +0100 +++ new/evolution-data-server-3.18.5/NEWS 2016-02-15 14:07:26.000000000 +0100 @@ -1,3 +1,21 @@ +Evolution-Data-Server 3.18.5 2016-02-15 +--------------------------------------- + +Bug Fixes: + Bug 748996 - GNetworkAddress is not thread safe (Milan Crha) + Bug 759153 - Prefer gpg2 over gpg (again, to match default for seahorse) (Milan Crha) + Bug 761527 - Local calendar interval tree not always updated (Milan Crha) + Bug 760951 - Cannot copy contact from Google to WebDAV addressbook (Milan Crha) + +Miscellaneous: + Use icaltzutil_set_exact_vtimezones_support(), if available (Milan Crha) + [IMAPx] Connection could be used multiple times at once in certain cases (Milan Crha) + [IMAPx] Stop IDLE gracefully (Milan Crha) + [IMAPx] Change how IDLE is handled (Milan Crha) + [IMAPx] Remove runtime check from imapx_conn_manager_dec_mailbox_hash() (Milan Crha) + [IMAPx] Crash in imapx_free_capability() (Milan Crha) + [IMAPx] Prefer graceful IDLE stop than forced reconnect (Milan Crha) + Evolution-Data-Server 3.18.4 2016-01-18 --------------------------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/evolution-data-server-3.18.4/addressbook/backends/webdav/e-book-backend-webdav.c new/evolution-data-server-3.18.5/addressbook/backends/webdav/e-book-backend-webdav.c --- old/evolution-data-server-3.18.4/addressbook/backends/webdav/e-book-backend-webdav.c 2015-09-21 11:19:51.000000000 +0200 +++ new/evolution-data-server-3.18.5/addressbook/backends/webdav/e-book-backend-webdav.c 2016-02-11 18:42:20.000000000 +0100 @@ -1458,6 +1458,27 @@ } static gboolean +webdav_can_use_uid (const gchar *uid) +{ + const gchar *ptr; + + if (!uid || !*uid) + return FALSE; + + for (ptr = uid; *ptr; ptr++) { + if ((*ptr >= 'a' && *ptr <= 'z') || + (*ptr >= 'A' && *ptr <= 'Z') || + (*ptr >= '0' && *ptr <= '9') || + strchr (".-@", *ptr) != NULL) + continue; + + return FALSE; + } + + return TRUE; +} + +static gboolean book_backend_webdav_create_contacts_sync (EBookBackend *backend, const gchar * const *vcards, GQueue *out_contacts, @@ -1495,7 +1516,7 @@ contact = e_contact_new_from_vcard (vcards[0]); orig_uid = e_contact_get_const (contact, E_CONTACT_UID); - if (orig_uid && *orig_uid && !e_book_backend_cache_check_contact (webdav->priv->cache, orig_uid)) { + if (orig_uid && *orig_uid && webdav_can_use_uid (orig_uid) && !e_book_backend_cache_check_contact (webdav->priv->cache, orig_uid)) { uid = g_strdup (orig_uid); } else { uid = NULL; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/evolution-data-server-3.18.4/calendar/backends/file/e-cal-backend-file.c new/evolution-data-server-3.18.5/calendar/backends/file/e-cal-backend-file.c --- old/evolution-data-server-3.18.4/calendar/backends/file/e-cal-backend-file.c 2015-09-21 15:51:55.000000000 +0200 +++ new/evolution-data-server-3.18.5/calendar/backends/file/e-cal-backend-file.c 2016-02-10 19:55:37.000000000 +0100 @@ -298,6 +298,8 @@ priv = cbfile->priv; + g_rec_mutex_lock (&priv->idle_save_rmutex); + e_intervaltree_destroy (priv->interval_tree); priv->interval_tree = NULL; @@ -307,6 +309,8 @@ g_list_free (priv->comp); priv->comp = NULL; + + g_rec_mutex_unlock (&priv->idle_save_rmutex); } /* Dispose handler for the file backend */ @@ -629,15 +633,15 @@ /* Adds component to the interval tree */ -static gboolean +static void add_component_to_intervaltree (ECalBackendFile *cbfile, ECalComponent *comp) { time_t time_start = -1, time_end = -1; ECalBackendFilePrivate *priv; - g_return_val_if_fail (cbfile != NULL, FALSE); - g_return_val_if_fail (comp != NULL, FALSE); + g_return_if_fail (cbfile != NULL); + g_return_if_fail (comp != NULL); priv = cbfile->priv; @@ -650,10 +654,11 @@ gchar *str = e_cal_component_get_as_string (comp); g_print ("Bogus component %s\n", str); g_free (str); - } else + } else { + g_rec_mutex_lock (&priv->idle_save_rmutex); e_intervaltree_insert (priv->interval_tree, time_start, time_end, comp); - - return FALSE; + g_rec_mutex_unlock (&priv->idle_save_rmutex); + } } static gboolean @@ -672,7 +677,11 @@ rid = e_cal_component_get_recurid_as_string (comp); e_cal_component_get_uid (comp, &uid); + + g_rec_mutex_lock (&priv->idle_save_rmutex); res = e_intervaltree_remove (priv->interval_tree, uid, rid); + g_rec_mutex_unlock (&priv->idle_save_rmutex); + g_free (rid); return res; @@ -776,7 +785,7 @@ if (!remove_component_from_intervaltree (cbfile, comp)) { g_message (G_STRLOC " Could not remove component from interval tree!"); - } + } icalcomponent_remove_component (priv->icalcomp, icalcomp); /* remove it from our mapping */ @@ -1127,6 +1136,8 @@ return; } + g_rec_mutex_lock (&priv->idle_save_rmutex); + cal_backend_file_take_icalcomp (cbfile, icalcomp); priv->path = uri_to_path (E_CAL_BACKEND (cbfile)); @@ -1134,6 +1145,8 @@ priv->interval_tree = e_intervaltree_new (); scan_vcalendar (cbfile); + g_rec_mutex_unlock (&priv->idle_save_rmutex); + prepare_refresh_data (cbfile); } @@ -1254,6 +1267,8 @@ /* Keep old data for comparison - free later */ + g_rec_mutex_lock (&priv->idle_save_rmutex); + icalcomp_old = priv->icalcomp; priv->icalcomp = NULL; @@ -1272,6 +1287,8 @@ priv->path = uri_to_path (E_CAL_BACKEND (cbfile)); + g_rec_mutex_unlock (&priv->idle_save_rmutex); + /* Compare old and new versions of calendar */ notify_changes (cbfile, comp_uid_hash_old, priv->comp_uid_hash); @@ -1304,6 +1321,8 @@ g_free (dirname); + g_rec_mutex_lock (&priv->idle_save_rmutex); + /* Create the new calendar information */ icalcomp = e_cal_util_new_top_level (); cal_backend_file_take_icalcomp (cbfile, icalcomp); @@ -1314,6 +1333,8 @@ priv->path = uri_to_path (E_CAL_BACKEND (cbfile)); + g_rec_mutex_unlock (&priv->idle_save_rmutex); + save (cbfile, TRUE); prepare_refresh_data (cbfile); @@ -2463,6 +2484,12 @@ e_cal_recur_ensure_end_dates (comp, TRUE, resolve_tzid, priv->icalcomp); + if (!remove_component_from_intervaltree (cbfile, comp)) { + g_message (G_STRLOC " Could not remove component from interval tree!"); + } + + add_component_to_intervaltree (cbfile, comp); + icalcomponent_add_component ( priv->icalcomp, e_cal_component_get_icalcomponent (obj_data->full_object)); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/evolution-data-server-3.18.4/calendar/libedata-cal/e-data-cal-factory.c new/evolution-data-server-3.18.5/calendar/libedata-cal/e-data-cal-factory.c --- old/evolution-data-server-3.18.4/calendar/libedata-cal/e-data-cal-factory.c 2015-09-21 11:19:59.000000000 +0200 +++ new/evolution-data-server-3.18.5/calendar/libedata-cal/e-data-cal-factory.c 2016-01-20 21:53:30.000000000 +0100 @@ -277,6 +277,10 @@ ical_set_unknown_token_handling_setting (ICAL_DISCARD_TOKEN); #endif +#ifdef HAVE_ICALTZUTIL_SET_EXACT_VTIMEZONES_SUPPORT + icaltzutil_set_exact_vtimezones_support (0); +#endif + /* XXX Pre-load all built-in timezones in libical. * * Built-in time zones in libical 0.43 are loaded on demand, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/evolution-data-server-3.18.4/calendar/libedata-cal/e-subprocess-cal-factory.c new/evolution-data-server-3.18.5/calendar/libedata-cal/e-subprocess-cal-factory.c --- old/evolution-data-server-3.18.4/calendar/libedata-cal/e-subprocess-cal-factory.c 2015-11-25 09:04:04.000000000 +0100 +++ new/evolution-data-server-3.18.5/calendar/libedata-cal/e-subprocess-cal-factory.c 2016-01-20 21:53:30.000000000 +0100 @@ -144,6 +144,10 @@ ical_set_unknown_token_handling_setting (ICAL_DISCARD_TOKEN); #endif +#ifdef HAVE_ICALTZUTIL_SET_EXACT_VTIMEZONES_SUPPORT + icaltzutil_set_exact_vtimezones_support (0); +#endif + /* XXX Pre-load all built-in timezones in libical. * * Built-in time zones in libical 0.43 are loaded on demand, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/evolution-data-server-3.18.4/camel/camel-gpg-context.c new/evolution-data-server-3.18.5/camel/camel-gpg-context.c --- old/evolution-data-server-3.18.4/camel/camel-gpg-context.c 2015-09-21 11:19:59.000000000 +0200 +++ new/evolution-data-server-3.18.5/camel/camel-gpg-context.c 2016-01-27 11:29:46.000000000 +0100 @@ -461,8 +461,8 @@ { static gint index = -1; const gchar *names[] = { + "gpg2", /* Prefer gpg2, which the seahorse might use too */ "gpg", - "gpg2", /* Prefer gpg for now, because gpg2 doesn't save passwords (neither for the session) */ NULL }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/evolution-data-server-3.18.4/camel/camel-network-service.c new/evolution-data-server-3.18.5/camel/camel-network-service.c --- old/evolution-data-server-3.18.4/camel/camel-network-service.c 2015-08-19 13:39:50.000000000 +0200 +++ new/evolution-data-server-3.18.5/camel/camel-network-service.c 2016-01-26 17:14:19.000000000 +0100 @@ -730,10 +730,21 @@ g_mutex_lock (&priv->property_lock); - if (priv->connectable != NULL) + if (priv->connectable != NULL) { connectable = g_object_ref (priv->connectable); + g_mutex_unlock (&priv->property_lock); + } else { + CamelNetworkServiceInterface *iface; + + g_mutex_unlock (&priv->property_lock); + + iface = CAMEL_NETWORK_SERVICE_GET_INTERFACE (service); + g_return_val_if_fail (iface->new_connectable != NULL, NULL); - g_mutex_unlock (&priv->property_lock); + /* This may return NULL if we don't have valid network + * settings from which to create a GSocketConnectable. */ + connectable = iface->new_connectable (service); + } return connectable; } @@ -753,24 +764,21 @@ camel_network_service_set_connectable (CamelNetworkService *service, GSocketConnectable *connectable) { - CamelNetworkServiceInterface *iface; CamelNetworkServicePrivate *priv; g_return_if_fail (CAMEL_IS_NETWORK_SERVICE (service)); - iface = CAMEL_NETWORK_SERVICE_GET_INTERFACE (service); - g_return_if_fail (iface->new_connectable != NULL); - priv = CAMEL_NETWORK_SERVICE_GET_PRIVATE (service); g_return_if_fail (priv != NULL); + /* The GNetworkAddress is not thread safe, thus rather than precache it, + create a new instance whenever it's asked for it. Keep precached only + the connectable which had been explicitly set, because there cannot be + done exact copy of it. + */ if (connectable != NULL) { g_return_if_fail (G_IS_SOCKET_CONNECTABLE (connectable)); g_object_ref (connectable); - } else { - /* This may return NULL if we don't have valid network - * settings from which to create a GSocketConnectable. */ - connectable = iface->new_connectable (service); } g_mutex_lock (&priv->property_lock); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/evolution-data-server-3.18.4/camel/providers/imapx/camel-imapx-command.c new/evolution-data-server-3.18.5/camel/providers/imapx/camel-imapx-command.c --- old/evolution-data-server-3.18.4/camel/providers/imapx/camel-imapx-command.c 2015-09-21 11:19:59.000000000 +0200 +++ new/evolution-data-server-3.18.5/camel/providers/imapx/camel-imapx-command.c 2016-02-01 15:10:44.000000000 +0100 @@ -420,7 +420,7 @@ if (type & CAMEL_IMAPX_COMMAND_LITERAL_PLUS) { g_string_append_c (buffer, '{'); g_string_append_printf (buffer, "%u", ob_size); - if (CAMEL_IMAPX_HAVE_CAPABILITY (camel_imapx_server_get_capability_info (ic->is), LITERALPLUS)) { + if (camel_imapx_server_have_capability (ic->is, IMAPX_CAPABILITY_LITERALPLUS)) { g_string_append_c (buffer, '+'); } else { type &= ~CAMEL_IMAPX_COMMAND_LITERAL_PLUS; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/evolution-data-server-3.18.4/camel/providers/imapx/camel-imapx-conn-manager.c new/evolution-data-server-3.18.5/camel/providers/imapx/camel-imapx-conn-manager.c --- old/evolution-data-server-3.18.4/camel/providers/imapx/camel-imapx-conn-manager.c 2016-01-13 12:27:48.000000000 +0100 +++ new/evolution-data-server-3.18.5/camel/providers/imapx/camel-imapx-conn-manager.c 2016-01-29 09:49:07.000000000 +0100 @@ -216,6 +216,25 @@ } static gboolean +connection_info_try_reserve (ConnectionInfo *cinfo) +{ + gboolean reserved = FALSE; + + g_return_val_if_fail (cinfo != NULL, FALSE); + + g_mutex_lock (&cinfo->lock); + + if (!cinfo->busy) { + cinfo->busy = TRUE; + reserved = TRUE; + } + + g_mutex_unlock (&cinfo->lock); + + return reserved; +} + +static gboolean connection_info_get_busy (ConnectionInfo *cinfo) { gboolean busy; @@ -394,8 +413,6 @@ count = GPOINTER_TO_INT (g_hash_table_lookup (mailboxes_hash, mailbox)); if (!count) { g_mutex_unlock (&conn_man->priv->busy_mailboxes_lock); - g_warn_if_fail (count > 0); - return; } @@ -845,9 +862,8 @@ for (link = conn_man->priv->connections; link; link = g_list_next (link)) { ConnectionInfo *candidate = link->data; - if (candidate && !connection_info_get_busy (candidate)) { + if (candidate && connection_info_try_reserve (candidate)) { cinfo = connection_info_ref (candidate); - connection_info_set_busy (cinfo, TRUE); break; } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/evolution-data-server-3.18.4/camel/providers/imapx/camel-imapx-server.c new/evolution-data-server-3.18.5/camel/providers/imapx/camel-imapx-server.c --- old/evolution-data-server-3.18.4/camel/providers/imapx/camel-imapx-server.c 2016-01-13 12:27:48.000000000 +0100 +++ new/evolution-data-server-3.18.5/camel/providers/imapx/camel-imapx-server.c 2016-02-03 12:22:51.000000000 +0100 @@ -226,6 +226,14 @@ {CAMEL_IMAPX_UNTAGGED_VANISHED, imapx_untagged_vanished, NULL, TRUE}, }; +typedef enum { + IMAPX_IDLE_STATE_OFF, /* no IDLE running at all */ + IMAPX_IDLE_STATE_SCHEDULED, /* IDLE scheduled, but still waiting */ + IMAPX_IDLE_STATE_PREPARING, /* IDLE command going to be processed */ + IMAPX_IDLE_STATE_RUNNING, /* IDLE command had been processed, server responded */ + IMAPX_IDLE_STATE_STOPPING /* DONE had been issued, waiting for completion */ +} IMAPXIdleState; + struct _CamelIMAPXServerPrivate { GWeakRef store; GCancellable *cancellable; /* the main connection cancellable, it's cancelled on disconnect */ @@ -273,19 +281,17 @@ gchar inbox_separator; /* IDLE support */ - GRecMutex idle_lock; - GThread *idle_thread; - GMainLoop *idle_main_loop; - GMainContext *idle_main_context; + GMutex idle_lock; + GCond idle_cond; + IMAPXIdleState idle_state; GSource *idle_pending; CamelIMAPXMailbox *idle_mailbox; GCancellable *idle_cancellable; - gboolean idle_running; guint idle_stamp; gboolean is_cyrus; - /* Info about the current connection */ + /* Info about the current connection; guarded by priv->stream_lock */ struct _capability_info *cinfo; GRecMutex command_lock; @@ -776,21 +782,36 @@ GCancellable *cancellable, GError **error) { + struct _capability_info *cinfo; + g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (is), FALSE); - if (is->priv->cinfo != NULL) + g_mutex_lock (&is->priv->stream_lock); + + if (is->priv->cinfo != NULL) { imapx_free_capability (is->priv->cinfo); + is->priv->cinfo = NULL; + } - is->priv->cinfo = imapx_parse_capability ( - CAMEL_IMAPX_INPUT_STREAM (input_stream), cancellable, error); + g_mutex_unlock (&is->priv->stream_lock); - if (is->priv->cinfo == NULL) + cinfo = imapx_parse_capability (CAMEL_IMAPX_INPUT_STREAM (input_stream), cancellable, error); + + if (!cinfo) return FALSE; + g_mutex_lock (&is->priv->stream_lock); + + if (is->priv->cinfo != NULL) + imapx_free_capability (is->priv->cinfo); + is->priv->cinfo = cinfo; + c (is->priv->tagprefix, "got capability flags %08x\n", is->priv->cinfo->capa); imapx_server_stash_command_arguments (is); + g_mutex_unlock (&is->priv->stream_lock); + return TRUE; } @@ -1783,7 +1804,11 @@ break; case IMAPX_CAPABILITY: if (is->priv->context->sinfo->u.cinfo) { - struct _capability_info *cinfo = is->priv->cinfo; + struct _capability_info *cinfo; + + g_mutex_lock (&is->priv->stream_lock); + + cinfo = is->priv->cinfo; is->priv->cinfo = is->priv->context->sinfo->u.cinfo; is->priv->context->sinfo->u.cinfo = NULL; if (cinfo) @@ -1800,7 +1825,10 @@ is->priv->cinfo->capa &= ~list_extended; } } + imapx_server_stash_command_arguments (is); + + g_mutex_unlock (&is->priv->stream_lock); } break; case IMAPX_COPYUID: @@ -2015,6 +2043,11 @@ c (is->priv->tagprefix, "Got continuation response for IDLE \n"); + g_mutex_lock (&is->priv->idle_lock); + is->priv->idle_state = IMAPX_IDLE_STATE_RUNNING; + g_cond_broadcast (&is->priv->idle_cond); + g_mutex_unlock (&is->priv->idle_lock); + return TRUE; } @@ -2698,7 +2731,11 @@ goto exit; } + g_mutex_lock (&is->priv->stream_lock); + if (!is->priv->cinfo) { + g_mutex_unlock (&is->priv->stream_lock); + ic = camel_imapx_command_new (is, CAMEL_IMAPX_JOB_CAPABILITY, "CAPABILITY"); success = camel_imapx_server_process_command_sync (is, ic, _("Failed to get capabilities"), cancellable, error); @@ -2707,17 +2744,24 @@ if (!success) goto exit; + } else { + g_mutex_unlock (&is->priv->stream_lock); } if (method == CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT) { + g_mutex_lock (&is->priv->stream_lock); + if (CAMEL_IMAPX_LACK_CAPABILITY (is->priv->cinfo, STARTTLS)) { + g_mutex_unlock (&is->priv->stream_lock); g_set_error ( &local_error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Failed to connect to IMAP server %s in secure mode: %s"), host, _("STARTTLS not supported")); goto exit; + } else { + g_mutex_unlock (&is->priv->stream_lock); } ic = camel_imapx_command_new (is, CAMEL_IMAPX_JOB_STARTTLS, "STARTTLS"); @@ -2725,6 +2769,8 @@ success = camel_imapx_server_process_command_sync (is, ic, _("Failed to issue STARTTLS"), cancellable, error); if (success) { + g_mutex_lock (&is->priv->stream_lock); + /* See if we got new capabilities * in the STARTTLS response. */ imapx_free_capability (is->priv->cinfo); @@ -2735,6 +2781,8 @@ c (is->priv->tagprefix, "got capability flags %08x\n", is->priv->cinfo ? is->priv->cinfo->capa : 0xFFFFFFFF); imapx_server_stash_command_arguments (is); } + + g_mutex_unlock (&is->priv->stream_lock); } camel_imapx_command_unref (ic); @@ -2773,13 +2821,17 @@ } /* Get new capabilities if they weren't already given */ + g_mutex_lock (&is->priv->stream_lock); if (is->priv->cinfo == NULL) { + g_mutex_unlock (&is->priv->stream_lock); ic = camel_imapx_command_new (is, CAMEL_IMAPX_JOB_CAPABILITY, "CAPABILITY"); success = camel_imapx_server_process_command_sync (is, ic, _("Failed to get capabilities"), cancellable, error); camel_imapx_command_unref (ic); if (!success) goto exit; + } else { + g_mutex_unlock (&is->priv->stream_lock); } } @@ -2848,7 +2900,11 @@ g_object_unref (settings); if (mechanism != NULL) { + g_mutex_lock (&is->priv->stream_lock); + if (is->priv->cinfo && !g_hash_table_lookup (is->priv->cinfo->auth_types, mechanism)) { + g_mutex_unlock (&is->priv->stream_lock); + g_set_error ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE, @@ -2856,6 +2912,8 @@ "authentication"), host, mechanism); result = CAMEL_AUTHENTICATION_ERROR; goto exit; + } else { + g_mutex_unlock (&is->priv->stream_lock); } sasl = camel_sasl_new ("imap", mechanism, service); @@ -2942,6 +3000,8 @@ /* Forget old capabilities after login. */ if (result == CAMEL_AUTHENTICATION_ACCEPTED) { + g_mutex_lock (&is->priv->stream_lock); + if (is->priv->cinfo) { imapx_free_capability (is->priv->cinfo); is->priv->cinfo = NULL; @@ -2953,6 +3013,8 @@ c (is->priv->tagprefix, "got capability flags %08x\n", is->priv->cinfo ? is->priv->cinfo->capa : 0xFFFFFFFF); imapx_server_stash_command_arguments (is); } + + g_mutex_unlock (&is->priv->stream_lock); } camel_imapx_command_unref (ic); @@ -3009,9 +3071,12 @@ goto exception; /* After login we re-capa unless the server already told us. */ + g_mutex_lock (&is->priv->stream_lock); if (is->priv->cinfo == NULL) { GError *local_error = NULL; + g_mutex_unlock (&is->priv->stream_lock); + ic = camel_imapx_command_new (is, CAMEL_IMAPX_JOB_CAPABILITY, "CAPABILITY"); camel_imapx_server_process_command_sync (is, ic, _("Failed to get capabilities"), cancellable, &local_error); camel_imapx_command_unref (ic); @@ -3020,15 +3085,20 @@ g_propagate_error (error, local_error); goto exception; } + } else { + g_mutex_unlock (&is->priv->stream_lock); } is->priv->state = IMAPX_AUTHENTICATED; preauthed: /* Fetch namespaces (if supported). */ + g_mutex_lock (&is->priv->stream_lock); if (CAMEL_IMAPX_HAVE_CAPABILITY (is->priv->cinfo, NAMESPACE)) { GError *local_error = NULL; + g_mutex_unlock (&is->priv->stream_lock); + ic = camel_imapx_command_new (is, CAMEL_IMAPX_JOB_NAMESPACE, "NAMESPACE"); camel_imapx_server_process_command_sync (is, ic, _("Failed to issue NAMESPACE"), cancellable, &local_error); camel_imapx_command_unref (ic); @@ -3037,12 +3107,16 @@ g_propagate_error (error, local_error); goto exception; } + + g_mutex_lock (&is->priv->stream_lock); } /* Enable quick mailbox resynchronization (if supported). */ if (use_qresync && CAMEL_IMAPX_HAVE_CAPABILITY (is->priv->cinfo, QRESYNC)) { GError *local_error = NULL; + g_mutex_unlock (&is->priv->stream_lock); + ic = camel_imapx_command_new (is, CAMEL_IMAPX_JOB_ENABLE, "ENABLE CONDSTORE QRESYNC"); camel_imapx_server_process_command_sync (is, ic, _("Failed to enable QResync"), cancellable, &local_error); camel_imapx_command_unref (ic); @@ -3052,6 +3126,8 @@ goto exception; } + g_mutex_lock (&is->priv->stream_lock); + is->priv->use_qresync = TRUE; } else { is->priv->use_qresync = FALSE; @@ -3061,6 +3137,8 @@ if (CAMEL_IMAPX_HAVE_CAPABILITY (is->priv->cinfo, NOTIFY)) { GError *local_error = NULL; + g_mutex_unlock (&is->priv->stream_lock); + /* XXX The list of FETCH attributes is negotiable. */ ic = camel_imapx_command_new (is, CAMEL_IMAPX_JOB_NOTIFY, "NOTIFY SET " "(selected " @@ -3079,8 +3157,12 @@ g_propagate_error (error, local_error); goto exception; } + + g_mutex_lock (&is->priv->stream_lock); } + g_mutex_unlock (&is->priv->stream_lock); + is->priv->state = IMAPX_INITIALISED; success = TRUE; @@ -3090,11 +3172,6 @@ exception: imapx_disconnect (is); - if (is->priv->cinfo) { - imapx_free_capability (is->priv->cinfo); - is->priv->cinfo = NULL; - } - exit: g_free (mechanism); @@ -3169,27 +3246,16 @@ imapx_server_dispose (GObject *object) { CamelIMAPXServer *server = CAMEL_IMAPX_SERVER (object); - gboolean idle_main_loop_is_running; g_cancellable_cancel (server->priv->cancellable); - /* Server should be shut down already. Warn if - * the idle thread is still running. */ - idle_main_loop_is_running = g_main_loop_is_running (server->priv->idle_main_loop); - g_warn_if_fail (!idle_main_loop_is_running); - - if (server->priv->idle_thread != NULL) { - g_thread_unref (server->priv->idle_thread); - server->priv->idle_thread = NULL; - } - imapx_disconnect (server); g_weak_ref_set (&server->priv->store, NULL); g_clear_object (&server->priv->subprocess); - g_rec_mutex_lock (&server->priv->idle_lock); + g_mutex_lock (&server->priv->idle_lock); g_clear_object (&server->priv->idle_cancellable); g_clear_object (&server->priv->idle_mailbox); if (server->priv->idle_pending) { @@ -3197,7 +3263,7 @@ g_source_unref (server->priv->idle_pending); server->priv->idle_pending = NULL; } - g_rec_mutex_unlock (&server->priv->idle_lock); + g_mutex_unlock (&server->priv->idle_lock); g_clear_object (&server->priv->subprocess); @@ -3233,9 +3299,8 @@ g_hash_table_destroy (is->priv->known_alerts); g_mutex_clear (&is->priv->known_alerts_lock); - g_rec_mutex_clear (&is->priv->idle_lock); - g_main_loop_unref (is->priv->idle_main_loop); - g_main_context_unref (is->priv->idle_main_context); + g_mutex_clear (&is->priv->idle_lock); + g_cond_clear (&is->priv->idle_cond); g_rec_mutex_clear (&is->priv->command_lock); @@ -3298,8 +3363,6 @@ static void camel_imapx_server_init (CamelIMAPXServer *is) { - GMainContext *main_context; - is->priv = CAMEL_IMAPX_SERVER_GET_PRIVATE (is); is->priv->untagged_handlers = create_initial_untagged_handler_table (); @@ -3328,15 +3391,11 @@ (GDestroyNotify) g_free, (GDestroyNotify) NULL); - /* Initialize IDLE thread structs. */ - - main_context = g_main_context_new (); - - g_rec_mutex_init (&is->priv->idle_lock); - is->priv->idle_main_loop = g_main_loop_new (main_context, FALSE); - is->priv->idle_main_context = g_main_context_ref (main_context); - - g_main_context_unref (main_context); + /* Initialize IDLE members. */ + g_mutex_init (&is->priv->idle_lock); + g_cond_init (&is->priv->idle_cond); + is->priv->idle_state = IMAPX_IDLE_STATE_OFF; + is->priv->idle_stamp = 0; g_rec_mutex_init (&is->priv->command_lock); } @@ -3614,8 +3673,8 @@ COMMAND_LOCK (is); if (is->priv->current_command != NULL) { - g_warning ("%s: Starting command %p (%s) while still processing %p (%s)", G_STRFUNC, - ic, camel_imapx_job_get_kind_name (ic->job_kind), + g_warning ("%s: [%c] %p: Starting command %p (%s) while still processing %p (%s)", G_STRFUNC, + is->priv->tagprefix, is, ic, camel_imapx_job_get_kind_name (ic->job_kind), is->priv->current_command, camel_imapx_job_get_kind_name (is->priv->current_command->job_kind)); } @@ -3769,6 +3828,11 @@ g_clear_object (&is->priv->connection); g_clear_object (&is->priv->subprocess); + if (is->priv->cinfo) { + imapx_free_capability (is->priv->cinfo); + is->priv->cinfo = NULL; + } + g_mutex_unlock (&is->priv->stream_lock); g_mutex_lock (&is->priv->select_lock); @@ -3776,13 +3840,13 @@ g_weak_ref_set (&is->priv->select_pending, NULL); g_mutex_unlock (&is->priv->select_lock); - if (is->priv->cinfo) { - imapx_free_capability (is->priv->cinfo); - is->priv->cinfo = NULL; - } - is->priv->is_cyrus = FALSE; is->priv->state = IMAPX_DISCONNECTED; + + g_mutex_lock (&is->priv->idle_lock); + is->priv->idle_state = IMAPX_IDLE_STATE_OFF; + g_cond_broadcast (&is->priv->idle_cond); + g_mutex_unlock (&is->priv->idle_lock); } /* Client commands */ @@ -3809,10 +3873,16 @@ if (!imapx_reconnect (is, cancellable, error)) return FALSE; + g_mutex_lock (&is->priv->stream_lock); + if (CAMEL_IMAPX_LACK_CAPABILITY (is->priv->cinfo, NAMESPACE)) { + g_mutex_unlock (&is->priv->stream_lock); + /* This also creates a needed faux NAMESPACE */ if (!camel_imapx_server_list_sync (is, "INBOX", 0, cancellable, error)) return FALSE; + } else { + g_mutex_unlock (&is->priv->stream_lock); } return TRUE; @@ -3828,11 +3898,11 @@ g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (is), FALSE); - g_rec_mutex_lock (&is->priv->idle_lock); + g_mutex_lock (&is->priv->idle_lock); idle_cancellable = is->priv->idle_cancellable; if (idle_cancellable) g_object_ref (idle_cancellable); - g_rec_mutex_unlock (&is->priv->idle_lock); + g_mutex_unlock (&is->priv->idle_lock); if (idle_cancellable) g_cancellable_cancel (idle_cancellable); @@ -4114,10 +4184,14 @@ /* If we're moving messages, prefer "UID MOVE" if supported. */ if (delete_originals) { + g_mutex_lock (&is->priv->stream_lock); + if (CAMEL_IMAPX_HAVE_CAPABILITY (is->priv->cinfo, MOVE)) { delete_originals = FALSE; use_move_command = TRUE; } + + g_mutex_unlock (&is->priv->stream_lock); } source_infos = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, camel_message_info_unref); @@ -5747,11 +5821,17 @@ g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (is), FALSE); g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), FALSE); + g_mutex_lock (&is->priv->stream_lock); + if (CAMEL_IMAPX_LACK_CAPABILITY (is->priv->cinfo, QUOTA)) { + g_mutex_unlock (&is->priv->stream_lock); + g_set_error_literal ( error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("IMAP server does not support quotas")); return FALSE; + } else { + g_mutex_unlock (&is->priv->stream_lock); } success = camel_imapx_server_ensure_selected_sync (is, mailbox, cancellable, error); @@ -5871,12 +5951,13 @@ g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (is), NULL); g_return_val_if_fail (G_IS_CANCELLABLE (idle_cancellable), NULL); - g_rec_mutex_lock (&is->priv->idle_lock); + g_mutex_lock (&is->priv->idle_lock); if (g_cancellable_is_cancelled (idle_cancellable) || - is->priv->idle_stamp != itd->idle_stamp) { - is->priv->idle_running = FALSE; - g_rec_mutex_unlock (&is->priv->idle_lock); + is->priv->idle_stamp != itd->idle_stamp || + is->priv->idle_state != IMAPX_IDLE_STATE_SCHEDULED) { + g_cond_broadcast (&is->priv->idle_cond); + g_mutex_unlock (&is->priv->idle_lock); g_clear_object (&itd->is); g_clear_object (&itd->idle_cancellable); @@ -5885,13 +5966,14 @@ return NULL; } + is->priv->idle_state = IMAPX_IDLE_STATE_PREPARING; + g_cond_broadcast (&is->priv->idle_cond); + mailbox = is->priv->idle_mailbox; if (mailbox) g_object_ref (mailbox); - is->priv->idle_running = TRUE; - - g_rec_mutex_unlock (&is->priv->idle_lock); + g_mutex_unlock (&is->priv->idle_lock); if (!mailbox) mailbox = camel_imapx_server_ref_selected (is); @@ -5917,8 +5999,18 @@ previous_timeout = imapx_server_set_connection_timeout (is->priv->connection, INACTIVITY_TIMEOUT_SECONDS + 60); g_mutex_unlock (&is->priv->stream_lock); - /* Blocks, until the DONE is issued or on inactivity timeout, error, ... */ - success = camel_imapx_server_process_command_sync (is, ic, _("Error running IDLE"), idle_cancellable, &local_error); + g_mutex_lock (&is->priv->idle_lock); + if (is->priv->idle_stamp == itd->idle_stamp && + is->priv->idle_state == IMAPX_IDLE_STATE_PREPARING) { + g_mutex_unlock (&is->priv->idle_lock); + + /* Blocks, until the DONE is issued or on inactivity timeout, error, ... */ + success = camel_imapx_server_process_command_sync (is, ic, _("Error running IDLE"), idle_cancellable, &local_error); + + rather_disconnect = rather_disconnect || !success || g_cancellable_is_cancelled (idle_cancellable); + } else { + g_mutex_unlock (&is->priv->idle_lock); + } if (previous_timeout >= 0) { g_mutex_lock (&is->priv->stream_lock); @@ -5930,16 +6022,18 @@ camel_imapx_command_unref (ic); exit: - g_rec_mutex_lock (&is->priv->idle_lock); - is->priv->idle_running = FALSE; - g_rec_mutex_unlock (&is->priv->idle_lock); + g_mutex_lock (&is->priv->idle_lock); + g_clear_object (&is->priv->idle_cancellable); + is->priv->idle_state = IMAPX_IDLE_STATE_OFF; + g_cond_broadcast (&is->priv->idle_cond); + g_mutex_unlock (&is->priv->idle_lock); if (success) - c (camel_imapx_server_get_tagprefix (is), "IDLE finished successfully"); + c (camel_imapx_server_get_tagprefix (is), "IDLE finished successfully\n"); else if (local_error) - c (camel_imapx_server_get_tagprefix (is), "IDLE finished with error: %s%s", local_error->message, rather_disconnect ? "; rather disconnect" : ""); + c (camel_imapx_server_get_tagprefix (is), "IDLE finished with error: %s%s\n", local_error->message, rather_disconnect ? "; rather disconnect" : ""); else - c (camel_imapx_server_get_tagprefix (is), "IDLE finished without error%s", rather_disconnect ? "; rather disconnect" : ""); + c (camel_imapx_server_get_tagprefix (is), "IDLE finished without error%s\n", rather_disconnect ? "; rather disconnect" : ""); if (rather_disconnect) { imapx_disconnect (is); @@ -5967,10 +6061,11 @@ if (!is) return FALSE; - g_rec_mutex_lock (&is->priv->idle_lock); + g_mutex_lock (&is->priv->idle_lock); if (g_main_current_source () == is->priv->idle_pending) { - if (!g_source_is_destroyed (g_main_current_source ())) { + if (!g_source_is_destroyed (g_main_current_source ()) && + is->priv->idle_state == IMAPX_IDLE_STATE_SCHEDULED) { IdleThreadData *itd; GThread *thread; GError *local_error = NULL; @@ -5980,11 +6075,9 @@ itd->idle_cancellable = g_object_ref (is->priv->idle_cancellable); itd->idle_stamp = is->priv->idle_stamp; - is->priv->idle_running = TRUE; - thread = g_thread_try_new (NULL, imapx_server_idle_thread, itd, &local_error); if (thread) { - is->priv->idle_thread = thread; + g_thread_unref (thread); } else { g_warning ("%s: Failed to create IDLE thread: %s", G_STRFUNC, local_error ? local_error->message : "Unknown error"); @@ -6000,7 +6093,7 @@ is->priv->idle_pending = NULL; } - g_rec_mutex_unlock (&is->priv->idle_lock); + g_mutex_unlock (&is->priv->idle_lock); return FALSE; } @@ -6010,9 +6103,14 @@ { gboolean use_idle = FALSE; + g_mutex_lock (&is->priv->stream_lock); + /* No need for IDLE if the server supports NOTIFY. */ - if (CAMEL_IMAPX_HAVE_CAPABILITY (is->priv->cinfo, NOTIFY)) + if (CAMEL_IMAPX_HAVE_CAPABILITY (is->priv->cinfo, NOTIFY)) { + g_mutex_unlock (&is->priv->stream_lock); + return FALSE; + } if (CAMEL_IMAPX_HAVE_CAPABILITY (is->priv->cinfo, IDLE)) { CamelIMAPXSettings *settings; @@ -6022,6 +6120,8 @@ g_object_unref (settings); } + g_mutex_unlock (&is->priv->stream_lock); + return use_idle; } @@ -6032,9 +6132,9 @@ g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (is), FALSE); - g_rec_mutex_lock (&is->priv->idle_lock); - in_idle = is->priv->idle_running || is->priv->idle_pending || is->priv->idle_thread; - g_rec_mutex_unlock (&is->priv->idle_lock); + g_mutex_lock (&is->priv->idle_lock); + in_idle = is->priv->idle_state != IMAPX_IDLE_STATE_OFF; + g_mutex_unlock (&is->priv->idle_lock); return in_idle; } @@ -6046,16 +6146,16 @@ g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (is), NULL); - g_rec_mutex_lock (&is->priv->idle_lock); + g_mutex_lock (&is->priv->idle_lock); - if (is->priv->idle_running || is->priv->idle_pending || is->priv->idle_thread) { + if (is->priv->idle_state != IMAPX_IDLE_STATE_OFF) { if (is->priv->idle_mailbox) mailbox = g_object_ref (is->priv->idle_mailbox); else mailbox = camel_imapx_server_ref_selected (is); } - g_rec_mutex_unlock (&is->priv->idle_lock); + g_mutex_unlock (&is->priv->idle_lock); return mailbox; } @@ -6076,7 +6176,15 @@ if (!camel_imapx_server_can_use_idle (is)) return TRUE; - g_rec_mutex_lock (&is->priv->idle_lock); + g_mutex_lock (&is->priv->idle_lock); + + if (is->priv->idle_state != IMAPX_IDLE_STATE_OFF) { + g_warn_if_fail (is->priv->idle_state == IMAPX_IDLE_STATE_OFF); + + g_mutex_unlock (&is->priv->idle_lock); + + return FALSE; + } g_warn_if_fail (is->priv->idle_cancellable == NULL); @@ -6092,114 +6200,136 @@ if (mailbox) is->priv->idle_mailbox = g_object_ref (mailbox); + is->priv->idle_state = IMAPX_IDLE_STATE_SCHEDULED; is->priv->idle_pending = g_timeout_source_new_seconds (IMAPX_IDLE_WAIT_SECONDS); g_source_set_callback ( is->priv->idle_pending, imapx_server_run_idle_thread_cb, imapx_weak_ref_new (is), (GDestroyNotify) imapx_weak_ref_free); g_source_attach (is->priv->idle_pending, NULL); - g_rec_mutex_unlock (&is->priv->idle_lock); + g_mutex_unlock (&is->priv->idle_lock); return TRUE; } +static void +imapx_server_wait_idle_stop_cancelled_cb (GCancellable *cancellable, + gpointer user_data) +{ + CamelIMAPXServer *is = user_data; + + g_return_if_fail (CAMEL_IS_IMAPX_SERVER (is)); + + g_mutex_lock (&is->priv->idle_lock); + g_cond_broadcast (&is->priv->idle_cond); + g_mutex_unlock (&is->priv->idle_lock); +} + gboolean camel_imapx_server_stop_idle_sync (CamelIMAPXServer *is, GCancellable *cancellable, GError **error) { - GThread *idle_thread; GCancellable *idle_cancellable; - CamelIMAPXCommand *idle_command = NULL; + gulong handler_id = 0; gboolean success = TRUE; g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (is), FALSE); - COMMAND_LOCK (is); - - if (is->priv->current_command && is->priv->current_command->job_kind == CAMEL_IMAPX_JOB_IDLE) { - idle_command = camel_imapx_command_ref (is->priv->current_command); - } - - COMMAND_UNLOCK (is); + g_mutex_lock (&is->priv->idle_lock); - g_rec_mutex_lock (&is->priv->idle_lock); + if (is->priv->idle_state == IMAPX_IDLE_STATE_OFF) { + g_mutex_unlock (&is->priv->idle_lock); + return TRUE; + } else if (is->priv->idle_state == IMAPX_IDLE_STATE_SCHEDULED) { + if (is->priv->idle_pending) { + g_source_destroy (is->priv->idle_pending); + g_source_unref (is->priv->idle_pending); + is->priv->idle_pending = NULL; + } - if (is->priv->idle_pending) { - g_source_destroy (is->priv->idle_pending); - g_source_unref (is->priv->idle_pending); - is->priv->idle_pending = NULL; + is->priv->idle_state = IMAPX_IDLE_STATE_OFF; + g_cond_broadcast (&is->priv->idle_cond); } idle_cancellable = is->priv->idle_cancellable ? g_object_ref (is->priv->idle_cancellable) : NULL; - idle_thread = is->priv->idle_thread; g_clear_object (&is->priv->idle_cancellable); g_clear_object (&is->priv->idle_mailbox); - is->priv->idle_thread = NULL; is->priv->idle_stamp++; - g_rec_mutex_unlock (&is->priv->idle_lock); + if (cancellable) + handler_id = g_cancellable_connect (cancellable, G_CALLBACK (imapx_server_wait_idle_stop_cancelled_cb), is, NULL); - if (idle_cancellable) { - g_cancellable_cancel (idle_cancellable); - g_object_unref (idle_cancellable); + while (is->priv->idle_state == IMAPX_IDLE_STATE_PREPARING && + !g_cancellable_is_cancelled (cancellable)) { + g_cond_wait (&is->priv->idle_cond, &is->priv->idle_lock); } - if (idle_thread) - g_thread_join (idle_thread); + if (is->priv->idle_state == IMAPX_IDLE_STATE_RUNNING && + !g_cancellable_is_cancelled (cancellable)) { + is->priv->idle_state = IMAPX_IDLE_STATE_STOPPING; + g_cond_broadcast (&is->priv->idle_cond); + g_mutex_unlock (&is->priv->idle_lock); - if (idle_command) { - CamelIMAPXCommand *ic; - gint previous_timeout = -1; - GError *local_error = NULL; + g_mutex_lock (&is->priv->stream_lock); + if (is->priv->output_stream) { + gint previous_timeout = -1; - g_return_val_if_fail (is->priv->current_command == NULL, FALSE); + /* Set the connection timeout to some short time, no need to wait for it for too long */ + if (is->priv->connection) + previous_timeout = imapx_server_set_connection_timeout (is->priv->connection, 5); - ic = camel_imapx_command_new (is, CAMEL_IMAPX_JOB_DONE, "DONE"); - ic->tag = idle_command->tag; + success = g_output_stream_flush (is->priv->output_stream, cancellable, error); + success = success && g_output_stream_write_all (is->priv->output_stream, "DONE\r\n", 6, NULL, cancellable, error); + success = success && g_output_stream_flush (is->priv->output_stream, cancellable, error); - g_mutex_lock (&is->priv->stream_lock); - /* Set the connection timeout to some short time, no need to wait for it for too long */ - if (is->priv->connection) - previous_timeout = imapx_server_set_connection_timeout (is->priv->connection, 15); + if (previous_timeout >= 0 && is->priv->connection) + imapx_server_set_connection_timeout (is->priv->connection, previous_timeout); + } else { + success = FALSE; + + /* This message won't get into UI. */ + g_set_error_literal (error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT, + "Reconnect after couldn't issue DONE command"); + } g_mutex_unlock (&is->priv->stream_lock); + g_mutex_lock (&is->priv->idle_lock); + } - success = camel_imapx_server_process_command_sync (is, ic, _("Failed to issue DONE"), cancellable, &local_error); + while (success && is->priv->idle_state != IMAPX_IDLE_STATE_OFF && + !g_cancellable_is_cancelled (cancellable)) { + g_cond_wait (&is->priv->idle_cond, &is->priv->idle_lock); + } - if (previous_timeout >= 0) { - g_mutex_lock (&is->priv->stream_lock); - if (is->priv->connection) - imapx_server_set_connection_timeout (is->priv->connection, previous_timeout); - g_mutex_unlock (&is->priv->stream_lock); - } + if (cancellable && handler_id) + g_cancellable_disconnect (cancellable, handler_id); - camel_imapx_command_unref (ic); - camel_imapx_command_unref (idle_command); + if (success && g_cancellable_is_cancelled (cancellable)) { + g_clear_error (error); - if (success) - c (camel_imapx_server_get_tagprefix (is), "DONE finished successfully\n"); - else - c (camel_imapx_server_get_tagprefix (is), "DONE finished with error: %s\n", local_error ? local_error->message : "Unknown error"); + success = FALSE; - if (!success) { - GError *tmp = local_error; + /* This message won't get into UI. */ + g_set_error_literal (error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT, + "Reconnect after cancelled IDLE stop command"); + } - local_error = NULL; + g_mutex_unlock (&is->priv->idle_lock); - g_set_error ( - &local_error, CAMEL_IMAPX_SERVER_ERROR, CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT, - "Failed to finish IDLE with DONE: %s", tmp ? tmp->message : "Unknown error"); + if (!success) { + if (idle_cancellable) + g_cancellable_cancel (idle_cancellable); - g_clear_error (&tmp); - } + g_mutex_lock (&is->priv->idle_lock); + is->priv->idle_state = IMAPX_IDLE_STATE_OFF; + g_mutex_unlock (&is->priv->idle_lock); - if (local_error) { - g_propagate_error (error, local_error); - success = FALSE; - } + imapx_disconnect (is); } + g_clear_object (&idle_cancellable); + return success; } @@ -6248,6 +6378,7 @@ return previous; } +/* This function is not thread-safe. */ const struct _capability_info * camel_imapx_server_get_capability_info (CamelIMAPXServer *is) { @@ -6256,6 +6387,36 @@ return is->priv->cinfo; } +gboolean +camel_imapx_server_have_capability (CamelIMAPXServer *is, + guint32 capability) +{ + gboolean have; + + g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (is), FALSE); + + g_mutex_lock (&is->priv->stream_lock); + have = is->priv->cinfo != NULL && (is->priv->cinfo->capa & capability) != 0; + g_mutex_unlock (&is->priv->stream_lock); + + return have; +} + +gboolean +camel_imapx_server_lack_capability (CamelIMAPXServer *is, + guint32 capability) +{ + gboolean lack; + + g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (is), FALSE); + + g_mutex_lock (&is->priv->stream_lock); + lack = is->priv->cinfo != NULL && (is->priv->cinfo->capa & capability) == 0; + g_mutex_unlock (&is->priv->stream_lock); + + return lack; +} + gchar camel_imapx_server_get_tagprefix (CamelIMAPXServer *is) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/evolution-data-server-3.18.4/camel/providers/imapx/camel-imapx-server.h new/evolution-data-server-3.18.5/camel/providers/imapx/camel-imapx-server.h --- old/evolution-data-server-3.18.4/camel/providers/imapx/camel-imapx-server.h 2016-01-13 12:27:47.000000000 +0100 +++ new/evolution-data-server-3.18.5/camel/providers/imapx/camel-imapx-server.h 2016-02-01 15:10:44.000000000 +0100 @@ -135,6 +135,12 @@ const struct _capability_info * camel_imapx_server_get_capability_info (CamelIMAPXServer *is); +gboolean camel_imapx_server_have_capability + (CamelIMAPXServer *is, + guint32 capability); +gboolean camel_imapx_server_lack_capability + (CamelIMAPXServer *is, + guint32 capability); gchar camel_imapx_server_get_tagprefix (CamelIMAPXServer *is); void camel_imapx_server_set_tagprefix diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/evolution-data-server-3.18.4/camel/providers/imapx/camel-imapx-store.c new/evolution-data-server-3.18.5/camel/providers/imapx/camel-imapx-store.c --- old/evolution-data-server-3.18.4/camel/providers/imapx/camel-imapx-store.c 2015-09-21 11:19:59.000000000 +0200 +++ new/evolution-data-server-3.18.5/camel/providers/imapx/camel-imapx-store.c 2016-02-01 15:12:44.000000000 +0100 @@ -3223,7 +3223,7 @@ /* Fabricate a CamelIMAPXNamespaceResponse if the server lacks the * NAMESPACE capability and this is the first LIST / LSUB response. */ - if (CAMEL_IMAPX_LACK_CAPABILITY (camel_imapx_server_get_capability_info (imapx_server), NAMESPACE)) { + if (camel_imapx_server_lack_capability (imapx_server, IMAPX_CAPABILITY_NAMESPACE)) { g_mutex_lock (&imapx_store->priv->namespaces_lock); if (imapx_store->priv->namespaces == NULL) { imapx_store->priv->namespaces = camel_imapx_namespace_response_faux_new (response); @@ -3287,7 +3287,7 @@ /* Fabricate a CamelIMAPXNamespaceResponse if the server lacks the * NAMESPACE capability and this is the first LIST / LSUB response. */ - if (CAMEL_IMAPX_LACK_CAPABILITY (camel_imapx_server_get_capability_info (imapx_server), NAMESPACE)) { + if (camel_imapx_server_lack_capability (imapx_server, IMAPX_CAPABILITY_NAMESPACE)) { g_mutex_lock (&imapx_store->priv->namespaces_lock); if (imapx_store->priv->namespaces == NULL) { imapx_store->priv->namespaces = camel_imapx_namespace_response_faux_new (response); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/evolution-data-server-3.18.4/config.h.in new/evolution-data-server-3.18.5/config.h.in --- old/evolution-data-server-3.18.4/config.h.in 2016-01-18 12:55:33.000000000 +0100 +++ new/evolution-data-server-3.18.5/config.h.in 2016-02-15 14:08:17.000000000 +0100 @@ -112,6 +112,9 @@ /* Define if you have Heimdal */ #undef HAVE_HEIMDAL_KRB5 +/* libical provides icaltzutil_set_exact_vtimezones_support function */ +#undef HAVE_ICALTZUTIL_SET_EXACT_VTIMEZONES_SUPPORT + /* libical provides ical_set_unknown_token_handling_setting function */ #undef HAVE_ICAL_UNKNOWN_TOKEN_HANDLING diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/evolution-data-server-3.18.4/configure.ac new/evolution-data-server-3.18.5/configure.ac --- old/evolution-data-server-3.18.4/configure.ac 2015-12-14 11:39:01.000000000 +0100 +++ new/evolution-data-server-3.18.5/configure.ac 2016-01-20 21:53:30.000000000 +0100 @@ -2,7 +2,7 @@ dnl Evolution-Data-Server version m4_define([eds_major_version], [3]) m4_define([eds_minor_version], [18]) -m4_define([eds_micro_version], [4]) +m4_define([eds_micro_version], [5]) m4_define([eds_version], [eds_major_version.eds_minor_version.eds_micro_version]) @@ -1511,19 +1511,33 @@ AC_SUBST(EVOLUTION_CALENDAR_CFLAGS) AC_SUBST(EVOLUTION_CALENDAR_LIBS) - dnl **************************** - dnl Check for ical_set_unknown_token_handling_setting function - dnl **************************** - AC_MSG_CHECKING([ical_set_unknown_token_handling_setting function]) - save_cflags=$CFLAGS; CFLAGS=$EVOLUTION_CALENDAR_CFLAGS - save_libs=$LIBS; LIBS="$EVOLUTION_CALENDAR_LIBS" - AC_LINK_IFELSE([AC_LANG_PROGRAM( - [[#include <libical/ical.h>]], - [[ical_set_unknown_token_handling_setting (ICAL_DISCARD_TOKEN)]])], - [AC_DEFINE(HAVE_ICAL_UNKNOWN_TOKEN_HANDLING, 1, [libical provides ical_set_unknown_token_handling_setting function]) ac_cv_have_iuth=yes],[ac_cv_have_iuth=no]) - CFLAGS=$save_cflags - LIBS=$save_libs - AC_MSG_RESULT([$ac_cv_have_iuth]) +dnl **************************** +dnl Check for ical_set_unknown_token_handling_setting function +dnl **************************** +AC_MSG_CHECKING([ical_set_unknown_token_handling_setting function]) +save_cflags=$CFLAGS; CFLAGS=$EVOLUTION_CALENDAR_CFLAGS +save_libs=$LIBS; LIBS="$EVOLUTION_CALENDAR_LIBS" +AC_LINK_IFELSE([AC_LANG_PROGRAM( + [[#include <libical/ical.h>]], + [[ical_set_unknown_token_handling_setting (ICAL_DISCARD_TOKEN)]])], + [AC_DEFINE(HAVE_ICAL_UNKNOWN_TOKEN_HANDLING, 1, [libical provides ical_set_unknown_token_handling_setting function]) ac_cv_have_iuth=yes],[ac_cv_have_iuth=no]) +CFLAGS=$save_cflags +LIBS=$save_libs +AC_MSG_RESULT([$ac_cv_have_iuth]) + +dnl **************************** +dnl Check for icaltzutil_set_exact_vtimezones_support function +dnl **************************** +AC_MSG_CHECKING([icaltzutil_set_exact_vtimezones_support function]) +save_cflags=$CFLAGS; CFLAGS="$EVOLUTION_DATA_SERVER_CFLAGS" +save_libs=$LIBS; LIBS="$EVOLUTION_DATA_SERVER_LIBS" +AC_LINK_IFELSE([AC_LANG_PROGRAM( + [[#include <libical/ical.h>]], + [[icaltzutil_set_exact_vtimezones_support (0)]])], + [AC_DEFINE(HAVE_ICALTZUTIL_SET_EXACT_VTIMEZONES_SUPPORT, 1, [libical provides icaltzutil_set_exact_vtimezones_support function]) ac_cv_have_isevs=yes],[ac_cv_have_isevs=no]) +CFLAGS=$save_cflags +LIBS=$save_libs +AC_MSG_RESULT([$ac_cv_have_isevs]) dnl ****************************** dnl Google flags diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/evolution-data-server-3.18.4/docs/reference/eds/html/eds-Version-Checking.html new/evolution-data-server-3.18.5/docs/reference/eds/html/eds-Version-Checking.html --- old/evolution-data-server-3.18.4/docs/reference/eds/html/eds-Version-Checking.html 2016-01-18 13:02:34.000000000 +0100 +++ new/evolution-data-server-3.18.5/docs/reference/eds/html/eds-Version-Checking.html 2016-02-15 14:15:09.000000000 +0100 @@ -203,7 +203,7 @@ <hr> <div class="refsect2"> <a name="EDS-MICRO-VERSION:CAPS"></a><h3>EDS_MICRO_VERSION</h3> -<pre class="programlisting">#define EDS_MICRO_VERSION 4 +<pre class="programlisting">#define EDS_MICRO_VERSION 5 </pre> <p>The micro version number of the Evolution-Data-Server library. Like <a class="link" href="eds-Version-Checking.html#eds-micro-version" title="eds_micro_version"><code class="function">eds_micro_version()</code></a>, but from the headers used at application compile diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/evolution-data-server-3.18.4/docs/reference/eds/html/index.html new/evolution-data-server-3.18.5/docs/reference/eds/html/index.html --- old/evolution-data-server-3.18.4/docs/reference/eds/html/index.html 2016-01-18 13:02:34.000000000 +0100 +++ new/evolution-data-server-3.18.5/docs/reference/eds/html/index.html 2016-02-15 14:15:09.000000000 +0100 @@ -15,7 +15,7 @@ <div class="titlepage"> <div> <div><table class="navigation" id="top" width="100%" cellpadding="2" cellspacing="0"><tr><th valign="middle"><p class="title">Evolution-Data-Server Reference Manual</p></th></tr></table></div> -<div><p class="releaseinfo">Reference Manual for evolution-data-server 3.18.4 +<div><p class="releaseinfo">Reference Manual for evolution-data-server 3.18.5 </p></div> <div><div class="abstract"> <p class="title"><b>Abstract</b></p> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/evolution-data-server-3.18.4/docs/reference/eds/version.xml new/evolution-data-server-3.18.5/docs/reference/eds/version.xml --- old/evolution-data-server-3.18.4/docs/reference/eds/version.xml 2016-01-18 12:55:47.000000000 +0100 +++ new/evolution-data-server-3.18.5/docs/reference/eds/version.xml 2016-02-15 14:08:30.000000000 +0100 @@ -1 +1 @@ -evolution-data-server 3.18.4 +evolution-data-server 3.18.5 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/evolution-data-server-3.18.4/libedataserver/eds-version.h new/evolution-data-server-3.18.5/libedataserver/eds-version.h --- old/evolution-data-server-3.18.4/libedataserver/eds-version.h 2016-01-18 12:55:46.000000000 +0100 +++ new/evolution-data-server-3.18.5/libedataserver/eds-version.h 2016-02-15 14:08:30.000000000 +0100 @@ -49,7 +49,7 @@ * time, rather than from the library linked against at application run * time. **/ -#define EDS_MICRO_VERSION 4 +#define EDS_MICRO_VERSION 5 /** * EDS_CHECK_VERSION: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/evolution-data-server-3.18.4/modules/ubuntu-online-accounts/evolution-data-server-uoa.desktop new/evolution-data-server-3.18.5/modules/ubuntu-online-accounts/evolution-data-server-uoa.desktop --- old/evolution-data-server-3.18.4/modules/ubuntu-online-accounts/evolution-data-server-uoa.desktop 2016-01-18 13:02:33.000000000 +0100 +++ new/evolution-data-server-3.18.5/modules/ubuntu-online-accounts/evolution-data-server-uoa.desktop 2016-02-15 14:15:08.000000000 +0100 @@ -90,4 +90,4 @@ X-GNOME-Bugzilla-Bugzilla=GNOME X-GNOME-Bugzilla-Product=evolution-data-server X-GNOME-Bugzilla-Component=General -X-GNOME-Bugzilla-Version=3.18.4 +X-GNOME-Bugzilla-Version=3.18.5 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/evolution-data-server-3.18.4/services/evolution-calendar-factory/evolution-calendar-factory.c new/evolution-data-server-3.18.5/services/evolution-calendar-factory/evolution-calendar-factory.c --- old/evolution-data-server-3.18.4/services/evolution-calendar-factory/evolution-calendar-factory.c 2015-08-19 13:39:50.000000000 +0200 +++ new/evolution-data-server-3.18.5/services/evolution-calendar-factory/evolution-calendar-factory.c 2016-01-20 21:53:30.000000000 +0100 @@ -24,9 +24,7 @@ #include <gtk/gtk.h> #endif -#ifdef HAVE_ICAL_UNKNOWN_TOKEN_HANDLING #include <libical/ical.h> -#endif #include <libedataserver/libedataserver.h> #include <libedata-cal/libedata-cal.h> @@ -83,6 +81,10 @@ ical_set_unknown_token_handling_setting (ICAL_DISCARD_TOKEN); #endif +#ifdef HAVE_ICALTZUTIL_SET_EXACT_VTIMEZONES_SUPPORT + icaltzutil_set_exact_vtimezones_support (0); +#endif + e_gdbus_templates_init_main_thread (); server = e_data_cal_factory_new (NULL, &error);