--- Begin Message ---
Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock
Hi,
upstream has put a lot of work in stabilizing the evolution 3.12
branch, which is also the version used for GNOME 3.14.
There is a new upstream release, and already a dozen other bugfixes in
the git, most of which are either trivial changes or interesting fixes
to get into jessie.
There is also a pair of simple bugs fixed in the packaging.
I’m attaching the upstream and Debian diffes, without translation
changes. If you want to look at the patches individually, you can have a
look at:
https://git.gnome.org/browse/evolution-data-server/log/?h=evolution-data-server-3-12
If you prefer that I retain only the changes that are about crashes or
UI issues, please tell me so.
unblock evolution-data-server/3.12.9~git20141128.5242b0-1
Thanks for considering.
--
.''`. Josselin Mouette
: :' :
`. `'
`-
Index: debian/changelog
===================================================================
--- debian/changelog (révision 2640)
+++ debian/changelog (copie de travail)
@@ -1,3 +1,12 @@
+evolution-data-server (3.12.9~git20141128.5242b0-1) UNRELEASED; urgency=medium
+
+ * Fix dependencies for development packages. Closes: #724595.
+ * Depend on gnome-keyring. Closes: #739324, #753478.
+ * New upstream git snapshot from stable branch, includes only bugfixes
+ and translations.
+
+ -- Josselin Mouette <joss@debian.org> Fri, 28 Nov 2014 09:29:02 +0100
+
evolution-data-server (3.12.7.1-1) unstable; urgency=medium
* New upstream release 3.12.7.1
Index: debian/control
===================================================================
--- debian/control (révision 2640)
+++ debian/control (copie de travail)
@@ -63,7 +63,8 @@
Depends: ${shlibs:Depends},
${misc:Depends},
evolution-data-server-common (= ${source:Version}),
- libcamel-1.2-49 (= ${binary:Version})
+ libcamel-1.2-49 (= ${binary:Version}),
+ gnome-keyring
Suggests: evolution,
evolution-data-server-dbg (= ${binary:Version})
Breaks: libecal1.2-7 (<< 2.32),
@@ -157,12 +158,11 @@
gir1.2-edataserver-1.2 (= ${binary:Version}),
${shlibs:Depends},
${misc:Depends},
- libedata-book1.2-dev,
+ libglib2.0-dev,
libcamel1.2-dev (= ${binary:Version}),
+ libsecret-1-dev,
libxml2-dev,
- libglib2.0-dev,
- libsoup2.4-dev,
- libsecret-1-dev
+ libsoup2.4-dev
Description: Utility library for evolution data servers (development files)
The data server, called "Evolution Data Server" is responsible for managing
calendar and addressbook information.
@@ -204,10 +204,10 @@
${misc:Depends},
${shlibs:Depends},
libglib2.0-dev,
- libedataserver1.2-dev (= ${binary:Version}),
- libsqlite3-dev (>= 3.5),
- libnss3-dev,
- libnspr4-dev
+ libsecret-1-dev,
+ libxml2-dev,
+ libsoup2.4-dev,
+ libsqlite3-dev (>= 3.5)
Description: Development files for libcamel
This package contains header files and static library for libcamel.
.
@@ -238,6 +238,7 @@
${shlibs:Depends},
libedataserver1.2-dev (= ${binary:Version}),
libebook-contacts1.2-dev (= ${binary:Version}),
+ libedata-book1.2-dev (= ${binary:Version}),
libcamel1.2-dev (= ${binary:Version}),
libglib2.0-dev
Description: Client library for evolution address books (development files)
@@ -278,9 +279,8 @@
Depends: libedata-book-1.2-20 (= ${binary:Version}),
${misc:Depends},
${shlibs:Depends},
- libedataserver1.2-dev (= ${binary:Version}),
libebackend1.2-dev (= ${binary:Version}),
- libebook1.2-dev (= ${binary:Version}),
+ libebook-contacts1.2-dev (= ${binary:Version}),
libglib2.0-dev
Description: Backend library for evolution address books (development files)
Evolution is the integrated mail, calendar, task and address book
@@ -372,7 +372,6 @@
${misc:Depends},
${shlibs:Depends},
libical-dev (>= 0.43),
- libedataserver1.2-dev (= ${binary:Version}),
libecal1.2-dev (= ${binary:Version}),
libebackend1.2-dev (= ${binary:Version}),
libglib2.0-dev
@@ -399,6 +398,7 @@
Architecture: any
Depends: libebackend-1.2-7 (= ${binary:Version}),
${misc:Depends},
+ libedataserver1.2-dev (= ${binary:Version}),
libglib2.0-dev
Description: Utility library for evolution data servers (development files)
This package contains header files and static library for libebackend.
Index: debian/libedataserver-1.2-18.symbols
===================================================================
--- debian/libedataserver-1.2-18.symbols (révision 2640)
+++ debian/libedataserver-1.2-18.symbols (copie de travail)
@@ -1033,6 +1033,8 @@
e_source_registry_create_sources_finish@Base 3.5.91
e_source_registry_create_sources_sync@Base 3.5.91
e_source_registry_debug_dump@Base 3.5.91
+ e_source_registry_debug_enabled@Base 3.12.9~
+ e_source_registry_debug_print@Base 3.12.9~
e_source_registry_dup_unique_display_name@Base 3.8.2
e_source_registry_find_extension@Base 3.5.91
e_source_registry_free_display_tree@Base 3.5.91
diff --git a/MAINTAINERS b/MAINTAINERS
index b3f5048..4c3ab4a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1,2 +1 @@
-Matthew Barnes <mbarnes@redhat.com>
Milan Crha <mcrha@redhat.com>
diff --git a/NEWS b/NEWS
index eed51fa..84ffba9 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,35 @@
+Evolution-Data-Server 3.12.8 2014-11-10
+-----------------------------------------
+
+Bug Fixes:
+ Bug 737733 - [IMAPx] Prevent "Stream has outstanding operation" error (Milan Crha)
+ Bug 738288 - EBookSqlite is leaking memory in ebsql_ref_from_hash function (Mateusz Polrola)
+ Bug 698964 - Hide password prompt right after getting the password (Milan Crha)
+ Bug 708166 - Update EClient properties on idle after GDBusProxy notify (Milan Crha)
+ Bug 737930 - Claims invalid PGP signature for single line mail (Christian Schaarschmidt)
+ Bug 738724 - [IMAPx] Message flag changes not always saved (Milan Crha)
+ Bug 738965 - [SQLite VFS] Crash due to missing xFetch definition (Milan Crha)
+ Bug 738184 - [IMAPx] Not every server returns empty namespace prefix for INBOX (Milan Crha)
+ Bug 712392 - Delay server availability checks on network change (Milan Crha)
+ Bug 739343 - Google Task with Due Date freezes UI on save (Milan Crha)
+ Bug 738724 - [IMAPx] Message flag changes not always saved (Milan Crha)
+
+Miscellaneous:
+ Update MAINTAINERS, doap. (Matthew Barnes)
+ [CamelService] Connect/Disconnect rely on provided cancellable (Milan Crha)
+ [CamelFolder/Store] Check online state of the session too before connecting (Milan Crha)
+ [CamelIMAPXConnManager] Can starve in close connections (Milan Crha)
+ [CamelOfflineStore] Count with host reachability update delay (Milan Crha)
+ [IMAPx] Do not connect to the server in offline mode (Milan Crha)
+ [IMAPx] Try to reconnect after socket I/O timeout (Milan Crha)
+ [CamelIMAPXServer] Assign tagprefix per account (Milan Crha)
+ Use 90 seconds timeout for Camel connections (Milan Crha)
+ Disabling/enabling Collection master source doesn't update children properly (Milan Crha)
+ camel_folder_thaw: Save changes to local summary (Milan Crha)
+
+Translations:
+ Kjartan Maraas (nb)
+
Evolution-Data-Server 3.12.7.1 2014-10-14
-----------------------------------------
diff --git a/addressbook/backends/ldap/e-book-backend-ldap.c b/addressbook/backends/ldap/e-book-backend-ldap.c
index c3305af..3ddc1ed 100644
--- a/addressbook/backends/ldap/e-book-backend-ldap.c
+++ b/addressbook/backends/ldap/e-book-backend-ldap.c
@@ -1179,11 +1179,11 @@ get_dn_attribute_name (gchar *rootdn,
EContact *contact)
{
/* Use 'uid' is already used in root DN,
- * then use the 'description' field. */
+ * then use the 'cn' field. */
if (strncmp (rootdn, "uid=", 4) == 0 ||
strstr (rootdn, ",uid=") ||
(contact && e_contact_get (contact, E_CONTACT_IS_LIST)))
- return "description";
+ return "cn";
/* Use 'uid' field */
return "uid";
diff --git a/addressbook/libebook-contacts/e-contact.c b/addressbook/libebook-contacts/e-contact.c
index 7a59169..6c3ffb8 100644
--- a/addressbook/libebook-contacts/e-contact.c
+++ b/addressbook/libebook-contacts/e-contact.c
@@ -863,6 +863,10 @@ e_contact_find_attribute_with_types (EContact *contact,
{
GList *l, *attrs;
gboolean found_needed1, found_needed2;
+ gboolean can_empty_needed2;
+
+ can_empty_needed2 = g_ascii_strcasecmp (attr_name, "TEL") == 0 && type_needed2 &&
+ g_ascii_strcasecmp (type_needed2, "VOICE") == 0;
attrs = e_vcard_get_attributes (E_VCARD (contact));
@@ -881,6 +885,7 @@ e_contact_find_attribute_with_types (EContact *contact,
for (params = e_vcard_attribute_get_params (attr); params; params = params->next) {
EVCardAttributeParam *param = params->data;
const gchar *param_name = e_vcard_attribute_param_get_name (param);
+ gint n_types = 0;
if (!g_ascii_strcasecmp (param_name, EVC_TYPE)) {
gboolean matches = FALSE;
@@ -892,11 +897,12 @@ e_contact_find_attribute_with_types (EContact *contact,
found_needed2 = values && !values->next;
while (values && values->data) {
+ n_types++;
+
if (!found_needed1 && !g_ascii_strcasecmp ((gchar *) values->data, type_needed1)) {
found_needed1 = TRUE;
matches = TRUE;
- }
- else if (!found_needed2 && !g_ascii_strcasecmp ((gchar *) values->data, type_needed2)) {
+ } else if (!found_needed2 && !g_ascii_strcasecmp ((gchar *) values->data, type_needed2)) {
found_needed2 = TRUE;
matches = TRUE;
} else if (found_needed1) {
@@ -907,7 +913,7 @@ e_contact_find_attribute_with_types (EContact *contact,
values = values->next;
}
- if (!matches) {
+ if (!matches && (!can_empty_needed2 || n_types != 1)) {
/* this is to enforce that we find an attribute
* with *only* the TYPE='s we need. This may seem like
* an odd restriction but it's the only way at present to
@@ -917,7 +923,7 @@ e_contact_find_attribute_with_types (EContact *contact,
}
}
- if (found_needed1 && found_needed2) {
+ if (found_needed1 && (found_needed2 || (n_types == 1 && can_empty_needed2))) {
if (nth-- == 0)
return attr;
else
diff --git a/addressbook/libebook/e-book-client.c b/addressbook/libebook/e-book-client.c
index b507c51..2ecf4f6 100644
--- a/addressbook/libebook/e-book-client.c
+++ b/addressbook/libebook/e-book-client.c
@@ -524,78 +524,91 @@ book_client_dbus_proxy_error_cb (EDBusAddressBook *dbus_proxy,
}
}
+typedef struct {
+ EClient *client;
+ EDBusAddressBook *dbus_proxy;
+ gchar *property_name;
+} IdleProxyNotifyData;
+
static void
-book_client_dbus_proxy_notify_cb (EDBusAddressBook *dbus_proxy,
- GParamSpec *pspec,
- GWeakRef *client_weak_ref)
+idle_proxy_notify_data_free (gpointer ptr)
{
- EClient *client;
+ IdleProxyNotifyData *ipn = ptr;
+
+ if (ipn) {
+ g_clear_object (&ipn->client);
+ g_clear_object (&ipn->dbus_proxy);
+ g_free (ipn->property_name);
+ g_free (ipn);
+ }
+}
+
+static gboolean
+book_client_dbus_proxy_notify_idle_cb (gpointer user_data)
+{
+ IdleProxyNotifyData *ipn = user_data;
const gchar *backend_prop_name = NULL;
- client = g_weak_ref_get (client_weak_ref);
- if (client == NULL)
- return;
+ g_return_val_if_fail (ipn != NULL, FALSE);
- if (g_str_equal (pspec->name, "cache-dir")) {
+ if (g_str_equal (ipn->property_name, "cache-dir")) {
backend_prop_name = CLIENT_BACKEND_PROPERTY_CACHE_DIR;
}
- if (g_str_equal (pspec->name, "capabilities")) {
+ if (g_str_equal (ipn->property_name, "capabilities")) {
gchar **strv;
gchar *csv = NULL;
backend_prop_name = CLIENT_BACKEND_PROPERTY_CAPABILITIES;
- strv = e_dbus_address_book_dup_capabilities (dbus_proxy);
+ strv = e_dbus_address_book_dup_capabilities (ipn->dbus_proxy);
if (strv != NULL) {
csv = g_strjoinv (",", strv);
g_strfreev (strv);
}
- e_client_set_capabilities (client, csv);
+ e_client_set_capabilities (ipn->client, csv);
g_free (csv);
}
- if (g_str_equal (pspec->name, "online")) {
+ if (g_str_equal (ipn->property_name, "online")) {
gboolean online;
backend_prop_name = CLIENT_BACKEND_PROPERTY_ONLINE;
- online = e_dbus_address_book_get_online (dbus_proxy);
- e_client_set_online (client, online);
+ online = e_dbus_address_book_get_online (ipn->dbus_proxy);
+ e_client_set_online (ipn->client, online);
}
- if (g_str_equal (pspec->name, "required-fields")) {
+ if (g_str_equal (ipn->property_name, "required-fields")) {
backend_prop_name = BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS;
}
- if (g_str_equal (pspec->name, "revision")) {
+ if (g_str_equal (ipn->property_name, "revision")) {
backend_prop_name = CLIENT_BACKEND_PROPERTY_REVISION;
}
- if (g_str_equal (pspec->name, "supported-fields")) {
+ if (g_str_equal (ipn->property_name, "supported-fields")) {
backend_prop_name = BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS;
}
- if (g_str_equal (pspec->name, "writable")) {
+ if (g_str_equal (ipn->property_name, "writable")) {
gboolean writable;
backend_prop_name = CLIENT_BACKEND_PROPERTY_READONLY;
- writable = e_dbus_address_book_get_writable (dbus_proxy);
- e_client_set_readonly (client, !writable);
+ writable = e_dbus_address_book_get_writable (ipn->dbus_proxy);
+ e_client_set_readonly (ipn->client, !writable);
}
- if (g_str_equal (pspec->name, "locale")) {
+ if (g_str_equal (ipn->property_name, "locale")) {
backend_prop_name = "locale";
}
if (backend_prop_name != NULL) {
- GSource *idle_source;
- GMainContext *main_context;
SignalClosure *signal_closure;
signal_closure = g_slice_new0 (SignalClosure);
- g_weak_ref_init (&signal_closure->client, client);
+ g_weak_ref_init (&signal_closure->client, ipn->client);
signal_closure->property_name = g_strdup (backend_prop_name);
/* The 'locale' is not an EClient property, so just transport
@@ -603,22 +616,43 @@ book_client_dbus_proxy_notify_cb (EDBusAddressBook *dbus_proxy,
*/
if (g_str_equal (backend_prop_name, "locale"))
signal_closure->property_value =
- e_dbus_address_book_dup_locale (dbus_proxy);
+ e_dbus_address_book_dup_locale (ipn->dbus_proxy);
- main_context = e_client_ref_main_context (client);
+ book_client_emit_backend_property_changed_idle_cb (signal_closure);
+ signal_closure_free (signal_closure);
+ }
- idle_source = g_idle_source_new ();
- g_source_set_callback (
- idle_source,
- book_client_emit_backend_property_changed_idle_cb,
- signal_closure,
- (GDestroyNotify) signal_closure_free);
- g_source_attach (idle_source, main_context);
- g_source_unref (idle_source);
+ return FALSE;
+}
- g_main_context_unref (main_context);
- }
+static void
+book_client_dbus_proxy_notify_cb (EDBusAddressBook *dbus_proxy,
+ GParamSpec *pspec,
+ GWeakRef *client_weak_ref)
+{
+ EClient *client;
+ GSource *idle_source;
+ GMainContext *main_context;
+ IdleProxyNotifyData *ipn;
+
+ client = g_weak_ref_get (client_weak_ref);
+ if (client == NULL)
+ return;
+
+ ipn = g_new0 (IdleProxyNotifyData, 1);
+ ipn->client = g_object_ref (client);
+ ipn->dbus_proxy = g_object_ref (dbus_proxy);
+ ipn->property_name = g_strdup (pspec->name);
+ main_context = e_client_ref_main_context (client);
+
+ idle_source = g_idle_source_new ();
+ g_source_set_callback (idle_source, book_client_dbus_proxy_notify_idle_cb,
+ ipn, idle_proxy_notify_data_free);
+ g_source_attach (idle_source, main_context);
+ g_source_unref (idle_source);
+
+ g_main_context_unref (main_context);
g_object_unref (client);
}
diff --git a/addressbook/libedata-book/e-book-backend-sqlitedb.c b/addressbook/libedata-book/e-book-backend-sqlitedb.c
index 7f5396c..2793e47 100644
--- a/addressbook/libedata-book/e-book-backend-sqlitedb.c
+++ b/addressbook/libedata-book/e-book-backend-sqlitedb.c
@@ -321,15 +321,22 @@ book_backend_sql_exec_real (sqlite3 *db,
GError **error)
{
gchar *errmsg = NULL;
- gint ret = -1;
+ gint ret = -1, retries = 0;
ret = sqlite3_exec (db, stmt, callback, data, &errmsg);
while (ret == SQLITE_BUSY || ret == SQLITE_LOCKED || ret == -1) {
+ /* try for ~15 seconds, then give up */
+ if (retries > 150)
+ break;
+ retries++;
+
if (errmsg) {
sqlite3_free (errmsg);
errmsg = NULL;
}
g_thread_yield ();
+ g_usleep (100 * 1000); /* Sleep for 100 ms */
+
ret = sqlite3_exec (db, stmt, callback, data, &errmsg);
}
diff --git a/addressbook/libedata-book/e-book-backend.c b/addressbook/libedata-book/e-book-backend.c
index 7f070f4..137084c 100644
--- a/addressbook/libedata-book/e-book-backend.c
+++ b/addressbook/libedata-book/e-book-backend.c
@@ -681,7 +681,7 @@ book_backend_shutdown (EBookBackend *backend)
source = e_backend_get_source (E_BACKEND (backend));
- g_print (
+ e_source_registry_debug_print (
"The %s instance for \"%s\" is shutting down.\n",
G_OBJECT_TYPE_NAME (backend),
e_source_get_display_name (source));
diff --git a/addressbook/libedata-book/e-book-sqlite.c b/addressbook/libedata-book/e-book-sqlite.c
index 87b1c80..e3770fe 100644
--- a/addressbook/libedata-book/e-book-sqlite.c
+++ b/addressbook/libedata-book/e-book-sqlite.c
@@ -718,7 +718,7 @@ ebsql_ref_from_hash (const gchar *path)
g_object_ref (ebsql);
}
- return NULL;
+ return ebsql;
}
static void
@@ -1082,7 +1082,7 @@ ebsql_exec (EBookSqlite *ebsql,
{
gboolean had_cancel;
gchar *errmsg = NULL;
- gint ret = -1;
+ gint ret = -1, retries = 0;
gint64 t1 = 0, t2;
/* Debug output for statements and query plans */
@@ -1106,11 +1106,17 @@ ebsql_exec (EBookSqlite *ebsql,
ret = sqlite3_exec (ebsql->priv->db, stmt, callback, data, &errmsg);
while (ret == SQLITE_BUSY || ret == SQLITE_LOCKED || ret == -1) {
+ /* try for ~15 seconds, then give up */
+ if (retries > 150)
+ break;
+ retries++;
+
if (errmsg) {
sqlite3_free (errmsg);
errmsg = NULL;
}
g_thread_yield ();
+ g_usleep (100 * 1000); /* Sleep for 100 ms */
if (t1)
t1 = g_get_monotonic_time();
diff --git a/calendar/backends/caldav/e-cal-backend-caldav.c b/calendar/backends/caldav/e-cal-backend-caldav.c
index 686020e..bae0a48 100644
--- a/calendar/backends/caldav/e-cal-backend-caldav.c
+++ b/calendar/backends/caldav/e-cal-backend-caldav.c
@@ -4343,6 +4343,7 @@ extract_objects (icalcomponent *icomp,
{
icalcomponent *scomp;
icalcomponent_kind kind;
+ GSList *link;
kind = icalcomponent_isa (icomp);
@@ -4360,12 +4361,15 @@ extract_objects (icalcomponent *icomp,
scomp = icalcomponent_get_first_component (icomp, ekind);
while (scomp) {
- /* Remove components from toplevel here */
*objects = g_slist_prepend (*objects, scomp);
- icalcomponent_remove_component (icomp, scomp);
scomp = icalcomponent_get_next_component (icomp, ekind);
}
+
+ for (link = *objects; link; link = g_slist_next (link)) {
+ /* Remove components from toplevel here */
+ icalcomponent_remove_component (icomp, link->data);
+ }
}
static gboolean
@@ -4575,7 +4579,10 @@ do_receive_objects (ECalBackendSync *backend,
/* Extract optional timezone compnents */
extract_timezones (cbdav, icomp);
- tmethod = icalcomponent_get_method (icomp);
+ if (icalcomponent_get_first_property (icomp, ICAL_METHOD_PROPERTY))
+ tmethod = icalcomponent_get_method (icomp);
+ else
+ tmethod = ICAL_METHOD_PUBLISH;
for (iter = objects; iter && !err; iter = iter->next) {
icalcomponent *scomp;
diff --git a/calendar/backends/file/e-cal-backend-file.c b/calendar/backends/file/e-cal-backend-file.c
index ff02976..db1ad26 100644
--- a/calendar/backends/file/e-cal-backend-file.c
+++ b/calendar/backends/file/e-cal-backend-file.c
@@ -319,6 +319,8 @@ e_cal_backend_file_dispose (GObject *object)
cbfile = E_CAL_BACKEND_FILE (object);
priv = cbfile->priv;
+ free_refresh_data (E_CAL_BACKEND_FILE (object));
+
/* Save if necessary */
if (priv->is_dirty)
save_file_when_idle (cbfile);
@@ -346,8 +348,6 @@ e_cal_backend_file_finalize (GObject *object)
if (priv->dirty_idle_id)
g_source_remove (priv->dirty_idle_id);
- free_refresh_data (E_CAL_BACKEND_FILE (object));
-
g_mutex_clear (&priv->refresh_lock);
g_rec_mutex_clear (&priv->idle_save_rmutex);
diff --git a/calendar/backends/gtasks/e-cal-backend-gtasks.c b/calendar/backends/gtasks/e-cal-backend-gtasks.c
index 9f68cb7..2e668e4 100644
--- a/calendar/backends/gtasks/e-cal-backend-gtasks.c
+++ b/calendar/backends/gtasks/e-cal-backend-gtasks.c
@@ -1322,6 +1322,17 @@ ecb_gtasks_stop_view (ECalBackend *backend,
}
static void
+ecb_gtasks_add_timezone (ECalBackend *backend,
+ EDataCal *cal,
+ guint32 opid,
+ GCancellable *cancellable,
+ const gchar *tzobject)
+{
+ /* Nothing to do, times are in UTC */
+ e_data_cal_respond_add_timezone (cal, opid, NULL);
+}
+
+static void
ecb_gtasks_shutdown (ECalBackend *backend)
{
ECalBackendGTasks *gtasks;
@@ -1438,5 +1449,6 @@ e_cal_backend_gtasks_class_init (ECalBackendGTasksClass *class)
backend_class->discard_alarm = ecb_gtasks_discard_alarm;
backend_class->start_view = ecb_gtasks_start_view;
backend_class->stop_view = ecb_gtasks_stop_view;
+ backend_class->add_timezone = ecb_gtasks_add_timezone;
backend_class->shutdown = ecb_gtasks_shutdown;
}
diff --git a/calendar/libecal/e-cal-client.c b/calendar/libecal/e-cal-client.c
index 29ddb3d..baf0c3c 100644
--- a/calendar/libecal/e-cal-client.c
+++ b/calendar/libecal/e-cal-client.c
@@ -574,94 +574,128 @@ cal_client_dbus_proxy_error_cb (EDBusCalendar *dbus_proxy,
}
}
+typedef struct {
+ EClient *client;
+ EDBusCalendar *dbus_proxy;
+ gchar *property_name;
+} IdleProxyNotifyData;
+
static void
-cal_client_dbus_proxy_notify_cb (EDBusCalendar *dbus_proxy,
- GParamSpec *pspec,
- GWeakRef *client_weak_ref)
+idle_proxy_notify_data_free (gpointer ptr)
{
- EClient *client;
+ IdleProxyNotifyData *ipn = ptr;
+
+ if (ipn) {
+ g_clear_object (&ipn->client);
+ g_clear_object (&ipn->dbus_proxy);
+ g_free (ipn->property_name);
+ g_free (ipn);
+ }
+}
+
+static gboolean
+cal_client_dbus_proxy_notify_idle_cb (gpointer user_data)
+{
+ IdleProxyNotifyData *ipn = user_data;
const gchar *backend_prop_name = NULL;
- client = g_weak_ref_get (client_weak_ref);
- if (client == NULL)
- return;
+ g_return_val_if_fail (ipn != NULL, FALSE);
- if (g_str_equal (pspec->name, "alarm-email-address")) {
+ if (g_str_equal (ipn->property_name, "alarm-email-address")) {
backend_prop_name = CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS;
}
- if (g_str_equal (pspec->name, "cache-dir")) {
+ if (g_str_equal (ipn->property_name, "cache-dir")) {
backend_prop_name = CLIENT_BACKEND_PROPERTY_CACHE_DIR;
}
- if (g_str_equal (pspec->name, "cal-email-address")) {
+ if (g_str_equal (ipn->property_name, "cal-email-address")) {
backend_prop_name = CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS;
}
- if (g_str_equal (pspec->name, "capabilities")) {
+ if (g_str_equal (ipn->property_name, "capabilities")) {
gchar **strv;
gchar *csv = NULL;
backend_prop_name = CLIENT_BACKEND_PROPERTY_CAPABILITIES;
- strv = e_dbus_calendar_dup_capabilities (dbus_proxy);
+ strv = e_dbus_calendar_dup_capabilities (ipn->dbus_proxy);
if (strv != NULL) {
csv = g_strjoinv (",", strv);
g_strfreev (strv);
}
- e_client_set_capabilities (client, csv);
+ e_client_set_capabilities (ipn->client, csv);
g_free (csv);
}
- if (g_str_equal (pspec->name, "default-object")) {
+ if (g_str_equal (ipn->property_name, "default-object")) {
backend_prop_name = CAL_BACKEND_PROPERTY_DEFAULT_OBJECT;
}
- if (g_str_equal (pspec->name, "online")) {
+ if (g_str_equal (ipn->property_name, "online")) {
gboolean online;
backend_prop_name = CLIENT_BACKEND_PROPERTY_ONLINE;
- online = e_dbus_calendar_get_online (dbus_proxy);
- e_client_set_online (client, online);
+ online = e_dbus_calendar_get_online (ipn->dbus_proxy);
+ e_client_set_online (ipn->client, online);
}
- if (g_str_equal (pspec->name, "revision")) {
+ if (g_str_equal (ipn->property_name, "revision")) {
backend_prop_name = CLIENT_BACKEND_PROPERTY_REVISION;
}
- if (g_str_equal (pspec->name, "writable")) {
+ if (g_str_equal (ipn->property_name, "writable")) {
gboolean writable;
backend_prop_name = CLIENT_BACKEND_PROPERTY_READONLY;
- writable = e_dbus_calendar_get_writable (dbus_proxy);
- e_client_set_readonly (client, !writable);
+ writable = e_dbus_calendar_get_writable (ipn->dbus_proxy);
+ e_client_set_readonly (ipn->client, !writable);
}
if (backend_prop_name != NULL) {
- GSource *idle_source;
- GMainContext *main_context;
SignalClosure *signal_closure;
signal_closure = g_slice_new0 (SignalClosure);
- g_weak_ref_init (&signal_closure->client, client);
+ g_weak_ref_init (&signal_closure->client, ipn->client);
signal_closure->property_name = g_strdup (backend_prop_name);
- main_context = e_client_ref_main_context (client);
+ cal_client_emit_backend_property_changed_idle_cb (signal_closure);
+ signal_closure_free (signal_closure);
+ }
- idle_source = g_idle_source_new ();
- g_source_set_callback (
- idle_source,
- cal_client_emit_backend_property_changed_idle_cb,
- signal_closure,
- (GDestroyNotify) signal_closure_free);
- g_source_attach (idle_source, main_context);
- g_source_unref (idle_source);
+ return FALSE;
+}
- g_main_context_unref (main_context);
- }
+static void
+cal_client_dbus_proxy_notify_cb (EDBusCalendar *dbus_proxy,
+ GParamSpec *pspec,
+ GWeakRef *client_weak_ref)
+{
+ EClient *client;
+ GSource *idle_source;
+ GMainContext *main_context;
+ IdleProxyNotifyData *ipn;
+ client = g_weak_ref_get (client_weak_ref);
+ if (client == NULL)
+ return;
+
+ ipn = g_new0 (IdleProxyNotifyData, 1);
+ ipn->client = g_object_ref (client);
+ ipn->dbus_proxy = g_object_ref (dbus_proxy);
+ ipn->property_name = g_strdup (pspec->name);
+
+ main_context = e_client_ref_main_context (client);
+
+ idle_source = g_idle_source_new ();
+ g_source_set_callback (idle_source, cal_client_dbus_proxy_notify_idle_cb,
+ ipn, idle_proxy_notify_data_free);
+ g_source_attach (idle_source, main_context);
+ g_source_unref (idle_source);
+
+ g_main_context_unref (main_context);
g_object_unref (client);
}
@@ -5289,7 +5323,7 @@ e_cal_client_remove_object_finish (ECalClient *client,
* This function allows the removal of instances of a recurrent
* appointment. By using a combination of the @uid, @rid and @mod
* arguments, you can remove specific instances. If what you want
- * is to remove all instances, use %NULL @rid and E_CAL_OBJ_MODE_THIS
+ * is to remove all instances, use %NULL @rid and E_CAL_OBJ_MODE_ALL
* for the @mod.
*
* Returns: %TRUE if successful, %FALSE otherwise.
diff --git a/calendar/libecal/e-cal-component.c b/calendar/libecal/e-cal-component.c
index 2480cad..38fe96f 100644
--- a/calendar/libecal/e-cal-component.c
+++ b/calendar/libecal/e-cal-component.c
@@ -271,6 +271,7 @@ free_icalcomponent (ECalComponent *comp,
/* Free the mappings */
priv->uid = NULL;
+ priv->recur_id.recur_time.prop = NULL;
priv->status = NULL;
diff --git a/calendar/libedata-cal/e-cal-backend-sexp.c b/calendar/libedata-cal/e-cal-backend-sexp.c
index af30224..3e9eaf5 100644
--- a/calendar/libedata-cal/e-cal-backend-sexp.c
+++ b/calendar/libedata-cal/e-cal-backend-sexp.c
@@ -45,6 +45,7 @@ struct _ECalBackendSExpPrivate {
ESExp *search_sexp;
gchar *text;
SearchContext *search_context;
+ GMutex search_context_lock;
};
struct _SearchContext {
@@ -1104,6 +1105,7 @@ cal_backend_sexp_finalize (GObject *object)
e_sexp_unref (priv->search_sexp);
g_free (priv->text);
g_free (priv->search_context);
+ g_mutex_clear (&priv->search_context_lock);
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (e_cal_backend_sexp_parent_class)->finalize (object);
@@ -1125,6 +1127,8 @@ e_cal_backend_sexp_init (ECalBackendSExp *sexp)
{
sexp->priv = E_CAL_BACKEND_SEXP_GET_PRIVATE (sexp);
sexp->priv->search_context = g_new (SearchContext, 1);
+
+ g_mutex_init (&sexp->priv->search_context_lock);
}
/* 'builtin' functions */
@@ -1254,6 +1258,8 @@ e_cal_backend_sexp_match_comp (ECalBackendSExp *sexp,
g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
g_return_val_if_fail (E_IS_TIMEZONE_CACHE (cache), FALSE);
+ g_mutex_lock (&sexp->priv->search_context_lock);
+
sexp->priv->search_context->comp = g_object_ref (comp);
sexp->priv->search_context->cache = g_object_ref (cache);
@@ -1266,6 +1272,8 @@ e_cal_backend_sexp_match_comp (ECalBackendSExp *sexp,
e_sexp_result_free (sexp->priv->search_sexp, r);
+ g_mutex_unlock (&sexp->priv->search_context_lock);
+
return retval;
}
diff --git a/calendar/libedata-cal/e-cal-backend.c b/calendar/libedata-cal/e-cal-backend.c
index c0a023a..d05bdc5 100644
--- a/calendar/libedata-cal/e-cal-backend.c
+++ b/calendar/libedata-cal/e-cal-backend.c
@@ -731,7 +731,7 @@ cal_backend_shutdown (ECalBackend *backend)
source = e_backend_get_source (E_BACKEND (backend));
- g_print (
+ e_source_registry_debug_print (
"The %s instance for \"%s\" is shutting down.\n",
G_OBJECT_TYPE_NAME (backend),
e_source_get_display_name (source));
diff --git a/camel/camel-db.c b/camel/camel-db.c
index eba5590..fb0e581 100644
--- a/camel/camel-db.c
+++ b/camel/camel-db.c
@@ -194,6 +194,20 @@ camel_sqlite3_file_ ## _nm _params \
return cFile->old_vfs_file->pMethods->_nm _call; \
}
+#define def_subclassed_void(_nm, _params, _call) \
+static void \
+camel_sqlite3_file_ ## _nm _params \
+{ \
+ CamelSqlite3File *cFile; \
+ \
+ g_return_if_fail (old_vfs != NULL); \
+ g_return_if_fail (pFile != NULL); \
+ \
+ cFile = (CamelSqlite3File *) pFile; \
+ g_return_if_fail (cFile->old_vfs_file->pMethods != NULL); \
+ cFile->old_vfs_file->pMethods->_nm _call; \
+}
+
def_subclassed (xRead, (sqlite3_file *pFile, gpointer pBuf, gint iAmt, sqlite3_int64 iOfst), (cFile->old_vfs_file, pBuf, iAmt, iOfst))
def_subclassed (xWrite, (sqlite3_file *pFile, gconstpointer pBuf, gint iAmt, sqlite3_int64 iOfst), (cFile->old_vfs_file, pBuf, iAmt, iOfst))
def_subclassed (xTruncate, (sqlite3_file *pFile, sqlite3_int64 size), (cFile->old_vfs_file, size))
@@ -203,6 +217,12 @@ def_subclassed (xUnlock, (sqlite3_file *pFile, gint lockType), (cFile->old_vfs_f
def_subclassed (xFileControl, (sqlite3_file *pFile, gint op, gpointer pArg), (cFile->old_vfs_file, op, pArg))
def_subclassed (xSectorSize, (sqlite3_file *pFile), (cFile->old_vfs_file))
def_subclassed (xDeviceCharacteristics, (sqlite3_file *pFile), (cFile->old_vfs_file))
+def_subclassed (xShmMap, (sqlite3_file *pFile, gint iPg, gint pgsz, gint n, void volatile **arr), (cFile->old_vfs_file, iPg, pgsz, n, arr))
+def_subclassed (xShmLock, (sqlite3_file *pFile, gint offset, gint n, gint flags), (cFile->old_vfs_file, offset, n, flags))
+def_subclassed_void (xShmBarrier, (sqlite3_file *pFile), (cFile->old_vfs_file))
+def_subclassed (xShmUnmap, (sqlite3_file *pFile, gint deleteFlag), (cFile->old_vfs_file, deleteFlag))
+def_subclassed (xFetch, (sqlite3_file *pFile, sqlite3_int64 iOfst, int iAmt, void **pp), (cFile->old_vfs_file, iOfst, iAmt, pp))
+def_subclassed (xUnfetch, (sqlite3_file *pFile, sqlite3_int64 iOfst, void *p), (cFile->old_vfs_file, iOfst, p))
#undef def_subclassed
@@ -351,6 +371,23 @@ camel_sqlite3_vfs_xOpen (sqlite3_vfs *pVfs,
use_subclassed (xFileControl);
use_subclassed (xSectorSize);
use_subclassed (xDeviceCharacteristics);
+
+ if (io_methods.iVersion > 1) {
+ use_subclassed (xShmMap);
+ use_subclassed (xShmLock);
+ use_subclassed (xShmBarrier);
+ use_subclassed (xShmUnmap);
+ }
+
+ if (io_methods.iVersion > 2) {
+ use_subclassed (xFetch);
+ use_subclassed (xUnfetch);
+ }
+
+ if (io_methods.iVersion > 3) {
+ g_warning ("%s: Unchecked IOMethods version %d, downgrading to version 3", G_STRFUNC, io_methods.iVersion);
+ io_methods.iVersion = 3;
+ }
#undef use_subclassed
}
@@ -443,16 +480,24 @@ cdb_sql_exec (sqlite3 *db,
GError **error)
{
gchar *errmsg = NULL;
- gint ret = -1;
+ gint ret = -1, retries = 0;
d (g_print ("Camel SQL Exec:\n%s\n", stmt));
ret = sqlite3_exec (db, stmt, callback, data, &errmsg);
while (ret == SQLITE_BUSY || ret == SQLITE_LOCKED || ret == -1) {
+ /* try for ~15 seconds, then give up */
+ if (retries > 150)
+ break;
+ retries++;
+
if (errmsg) {
sqlite3_free (errmsg);
errmsg = NULL;
}
+ g_thread_yield ();
+ g_usleep (100 * 1000); /* Sleep for 100 ms */
+
ret = sqlite3_exec (db, stmt, NULL, NULL, &errmsg);
}
diff --git a/camel/camel-folder.c b/camel/camel-folder.c
index 92bc914..8718c79 100644
--- a/camel/camel-folder.c
+++ b/camel/camel-folder.c
@@ -518,6 +518,7 @@ folder_maybe_connect_sync (CamelFolder *folder,
CamelService *service;
CamelStore *parent_store;
CamelServiceConnectionStatus status;
+ CamelSession *session;
gboolean connect = FALSE;
gboolean success = TRUE;
@@ -527,8 +528,10 @@ folder_maybe_connect_sync (CamelFolder *folder,
parent_store = camel_folder_get_parent_store (folder);
service = CAMEL_SERVICE (parent_store);
+ session = camel_service_ref_session (service);
status = camel_service_get_connection_status (service);
- connect = (status != CAMEL_SERVICE_CONNECTED);
+ connect = camel_session_get_online (session) && (status != CAMEL_SERVICE_CONNECTED);
+ g_clear_object (&session);
if (connect && CAMEL_IS_NETWORK_SERVICE (parent_store)) {
/* Disregard errors here. Just want to
@@ -965,6 +968,9 @@ folder_thaw (CamelFolder *folder)
if (info) {
camel_folder_changed (folder, info);
camel_folder_change_info_free (info);
+
+ if (folder->summary)
+ camel_folder_summary_save_to_db (folder->summary, NULL);
}
}
diff --git a/camel/camel-gpg-context.c b/camel/camel-gpg-context.c
index 2a3b94b..8c3104b 100644
--- a/camel/camel-gpg-context.c
+++ b/camel/camel-gpg-context.c
@@ -1880,16 +1880,15 @@ gpg_verify_sync (CamelCipherContext *context,
canon_stream = camel_stream_mem_new ();
/* strip trailing white-spaces */
- filter = camel_stream_filter_new (canon_stream);
+ filter = camel_stream_filter_new (istream);
canon = camel_mime_filter_canon_new (CAMEL_MIME_FILTER_CANON_CRLF | CAMEL_MIME_FILTER_CANON_STRIP);
camel_stream_filter_add (CAMEL_STREAM_FILTER (filter), canon);
g_object_unref (canon);
- camel_stream_write_to_stream (istream, filter, NULL, NULL);
+ camel_stream_write_to_stream (filter, canon_stream, NULL, NULL);
g_object_unref (filter);
-
- g_seekable_seek (G_SEEKABLE (istream), 0, G_SEEK_SET, NULL, NULL);
+ g_object_unref (istream);
g_seekable_seek (G_SEEKABLE (canon_stream), 0, G_SEEK_SET, NULL, NULL);
@@ -1945,7 +1944,7 @@ gpg_verify_sync (CamelCipherContext *context,
g_unlink (sigfile);
g_free (sigfile);
}
- g_object_unref (istream);
+
g_object_unref (canon_stream);
return validity;
diff --git a/camel/camel-network-service.c b/camel/camel-network-service.c
index c54f284..3e6462d 100644
--- a/camel/camel-network-service.c
+++ b/camel/camel-network-service.c
@@ -460,19 +460,25 @@ network_service_set_host_reachable (CamelNetworkService *service,
camel_service_disconnect_sync (
CAMEL_SERVICE (service), FALSE, NULL, &local_error);
if (local_error != NULL) {
- g_warning ("%s: %s", G_STRFUNC, local_error->message);
+ if (!G_IS_IO_ERROR (local_error, G_IO_ERROR_CANCELLED))
+ g_warning ("%s: %s", G_STRFUNC, local_error->message);
g_error_free (local_error);
}
}
}
static gboolean
-network_service_update_host_reachable_idle_cb (gpointer user_data)
+network_service_update_host_reachable_timeout_cb (gpointer user_data)
{
CamelNetworkService *service;
CamelNetworkServicePrivate *priv;
GCancellable *old_cancellable;
GCancellable *new_cancellable;
+ GSource *current_source;
+
+ current_source = g_main_current_source ();
+ if (current_source && g_source_is_destroyed (current_source))
+ return FALSE;
service = CAMEL_NETWORK_SERVICE (user_data);
priv = CAMEL_NETWORK_SERVICE_GET_PRIVATE (service);
@@ -519,22 +525,28 @@ network_service_update_host_reachable (CamelNetworkService *service)
g_mutex_lock (&priv->update_host_reachable_lock);
+ if (priv->update_host_reachable) {
+ g_source_destroy (priv->update_host_reachable);
+ g_source_unref (priv->update_host_reachable);
+ priv->update_host_reachable = NULL;
+ }
+
if (priv->update_host_reachable == NULL) {
GMainContext *main_context;
- GSource *idle_source;
+ GSource *timeout_source;
main_context = camel_session_ref_main_context (session);
- idle_source = g_idle_source_new ();
- g_source_set_priority (idle_source, G_PRIORITY_LOW);
+ timeout_source = g_timeout_source_new_seconds (5);
+ g_source_set_priority (timeout_source, G_PRIORITY_LOW);
g_source_set_callback (
- idle_source,
- network_service_update_host_reachable_idle_cb,
+ timeout_source,
+ network_service_update_host_reachable_timeout_cb,
g_object_ref (service),
(GDestroyNotify) g_object_unref);
- g_source_attach (idle_source, main_context);
- priv->update_host_reachable = g_source_ref (idle_source);
- g_source_unref (idle_source);
+ g_source_attach (timeout_source, main_context);
+ priv->update_host_reachable = g_source_ref (timeout_source);
+ g_source_unref (timeout_source);
g_main_context_unref (main_context);
}
@@ -643,6 +655,14 @@ network_service_connect_sync (CamelNetworkService *service,
g_object_unref (settings);
+ if (connection) {
+ GSocket *socket;
+
+ socket = g_socket_connection_get_socket (connection);
+ if (socket)
+ g_socket_set_timeout (socket, 90);
+ }
+
return (connection != NULL) ? G_IO_STREAM (connection) : NULL;
}
@@ -1017,8 +1037,19 @@ camel_network_service_can_reach_sync (CamelNetworkService *service,
G_IS_IO_ERROR (local_error, G_IO_ERROR_HOST_UNREACHABLE) ||
G_IS_RESOLVER_ERROR (local_error, G_RESOLVER_ERROR_NOT_FOUND);
- if (update_property)
+ if (update_property) {
+ g_mutex_lock (&priv->update_host_reachable_lock);
+
+ if (priv->update_host_reachable) {
+ g_source_destroy (priv->update_host_reachable);
+ g_source_unref (priv->update_host_reachable);
+ priv->update_host_reachable = NULL;
+ }
+
+ g_mutex_unlock (&priv->update_host_reachable_lock);
+
network_service_set_host_reachable (service, can_reach);
+ }
g_clear_object (&connectable);
diff --git a/camel/camel-offline-store.c b/camel/camel-offline-store.c
index c56ed94..d55ee32 100644
--- a/camel/camel-offline-store.c
+++ b/camel/camel-offline-store.c
@@ -188,9 +188,18 @@ camel_offline_store_set_online_sync (CamelOfflineStore *store,
status = camel_service_get_connection_status (service);
if (CAMEL_IS_NETWORK_SERVICE (store)) {
- host_reachable =
- camel_network_service_get_host_reachable (
- CAMEL_NETWORK_SERVICE (store));
+ /* When going to set the 'online' state, then check with up-to-date
+ value, otherwise use the cached value. The cached value is
+ updated with few seconds timeout, thus it can be stale here. */
+ if (online)
+ host_reachable =
+ camel_network_service_can_reach_sync (
+ CAMEL_NETWORK_SERVICE (store),
+ cancellable, NULL);
+ else
+ host_reachable =
+ camel_network_service_get_host_reachable (
+ CAMEL_NETWORK_SERVICE (store));
}
store_is_online = camel_offline_store_get_online (store);
@@ -288,9 +297,12 @@ camel_offline_store_prepare_for_offline_sync (CamelOfflineStore *store,
session = camel_service_ref_session (service);
if (CAMEL_IS_NETWORK_SERVICE (store)) {
+ /* Check with up-to-date value. The cached value is updated with
+ few seconds timeout, thus it can be stale here. */
host_reachable =
- camel_network_service_get_host_reachable (
- CAMEL_NETWORK_SERVICE (store));
+ camel_network_service_can_reach_sync (
+ CAMEL_NETWORK_SERVICE (store),
+ cancellable, NULL);
}
store_is_online = camel_offline_store_get_online (store);
diff --git a/camel/camel-service.c b/camel/camel-service.c
index 38ab90d..c8e4a3b 100644
--- a/camel/camel-service.c
+++ b/camel/camel-service.c
@@ -1809,6 +1809,11 @@ camel_service_connect (CamelService *service,
g_return_if_fail (CAMEL_IS_SERVICE (service));
+ if (cancellable)
+ g_object_ref (cancellable);
+ else
+ cancellable = g_cancellable_new ();
+
task = g_task_new (service, cancellable, callback, user_data);
g_task_set_source_tag (task, camel_service_connect);
g_task_set_priority (task, io_priority);
@@ -1864,6 +1869,7 @@ camel_service_connect (CamelService *service,
g_mutex_unlock (&service->priv->connection_lock);
+ g_object_unref (cancellable);
g_object_unref (task);
}
@@ -1975,6 +1981,11 @@ camel_service_disconnect (CamelService *service,
g_return_if_fail (CAMEL_IS_SERVICE (service));
+ if (cancellable)
+ g_object_ref (cancellable);
+ else
+ cancellable = g_cancellable_new ();
+
task = g_task_new (service, cancellable, callback, user_data);
g_task_set_source_tag (task, camel_service_disconnect);
g_task_set_priority (task, io_priority);
@@ -2038,6 +2049,7 @@ camel_service_disconnect (CamelService *service,
g_mutex_unlock (&service->priv->connection_lock);
+ g_object_unref (cancellable);
g_object_unref (task);
}
diff --git a/camel/camel-store.c b/camel/camel-store.c
index 81238ba..5906c17 100644
--- a/camel/camel-store.c
+++ b/camel/camel-store.c
@@ -296,6 +296,7 @@ store_maybe_connect_sync (CamelStore *store,
{
CamelService *service;
CamelServiceConnectionStatus status;
+ CamelSession *session;
gboolean connect = FALSE;
gboolean success = TRUE;
@@ -303,8 +304,10 @@ store_maybe_connect_sync (CamelStore *store,
* when the CamelService is online but disconnected. */
service = CAMEL_SERVICE (store);
+ session = camel_service_ref_session (service);
status = camel_service_get_connection_status (service);
- connect = (status != CAMEL_SERVICE_CONNECTED);
+ connect = camel_session_get_online (session) && (status != CAMEL_SERVICE_CONNECTED);
+ g_clear_object (&session);
if (connect && CAMEL_IS_NETWORK_SERVICE (store)) {
/* Disregard errors here. Just want to
@@ -476,6 +479,9 @@ store_synchronize_sync (CamelStore *store,
for (ii = 0; ii < folders->len; ii++) {
CamelFolder *folder = folders->pdata[ii];
+ if (folder->summary)
+ camel_folder_summary_save_to_db (folder->summary, NULL);
+
if (!CAMEL_IS_VEE_FOLDER (folder) && local_error == NULL) {
camel_folder_synchronize_sync (
folder, expunge, cancellable, &local_error);
diff --git a/camel/providers/imapx/camel-imapx-conn-manager.c b/camel/providers/imapx/camel-imapx-conn-manager.c
index b6298d0..3471e1b 100644
--- a/camel/providers/imapx/camel-imapx-conn-manager.c
+++ b/camel/providers/imapx/camel-imapx-conn-manager.c
@@ -47,6 +47,9 @@ struct _CamelIMAPXConnManagerPrivate {
GWeakRef store;
GRWLock rw_lock;
guint limit_max_connections;
+
+ GMutex pending_connections_lock;
+ GSList *pending_connections; /* GCancellable * */
};
struct _ConnectionInfo {
@@ -340,6 +343,23 @@ imapx_conn_manager_remove_info (CamelIMAPXConnManager *con_man,
}
static void
+imax_conn_manager_cancel_pending_connections (CamelIMAPXConnManager *con_man)
+{
+ GSList *link;
+
+ g_return_if_fail (CAMEL_IS_IMAPX_CONN_MANAGER (con_man));
+
+ g_mutex_lock (&con_man->priv->pending_connections_lock);
+ for (link = con_man->priv->pending_connections; link; link = g_slist_next (link)) {
+ GCancellable *cancellable = link->data;
+
+ if (cancellable)
+ g_cancellable_cancel (cancellable);
+ }
+ g_mutex_unlock (&con_man->priv->pending_connections_lock);
+}
+
+static void
imapx_conn_manager_set_store (CamelIMAPXConnManager *con_man,
CamelStore *store)
{
@@ -395,6 +415,8 @@ imapx_conn_manager_dispose (GObject *object)
(GDestroyNotify) connection_info_unref);
priv->connections = NULL;
+ imax_conn_manager_cancel_pending_connections (CAMEL_IMAPX_CONN_MANAGER (object));
+
g_weak_ref_set (&priv->store, NULL);
/* Chain up to parent's dispose() method. */
@@ -408,7 +430,10 @@ imapx_conn_manager_finalize (GObject *object)
priv = CAMEL_IMAPX_CONN_MANAGER_GET_PRIVATE (object);
+ g_warn_if_fail (priv->pending_connections == NULL);
+
g_rw_lock_clear (&priv->rw_lock);
+ g_mutex_clear (&priv->pending_connections_lock);
g_weak_ref_clear (&priv->store);
/* Chain up to parent's finalize() method. */
@@ -447,6 +472,7 @@ camel_imapx_conn_manager_init (CamelIMAPXConnManager *con_man)
con_man->priv = CAMEL_IMAPX_CONN_MANAGER_GET_PRIVATE (con_man);
g_rw_lock_init (&con_man->priv->rw_lock);
+ g_mutex_init (&con_man->priv->pending_connections_lock);
g_weak_ref_init (&con_man->priv->store, NULL);
}
@@ -691,6 +717,37 @@ exit:
return is;
}
+static gchar
+imapx_conn_manager_get_next_free_tagprefix_unlocked (CamelIMAPXConnManager *con_man)
+{
+ gchar adept;
+ GList *iter;
+
+ /* the 'Z' is dedicated to auth types query */
+ adept = 'A';
+ while (adept < 'Z') {
+ for (iter = con_man->priv->connections; iter; iter = g_list_next (iter)) {
+ ConnectionInfo *cinfo = iter->data;
+
+ if (!cinfo || !cinfo->is)
+ continue;
+
+ if (cinfo->is->tagprefix == adept)
+ break;
+ }
+
+ /* Read all current active connections and none has the same tag prefix */
+ if (!iter)
+ break;
+
+ adept++;
+ }
+
+ g_return_val_if_fail (adept >= 'A' && adept < 'Z', 'Z');
+
+ return adept;
+}
+
static CamelIMAPXServer *
imapx_create_new_connection_unlocked (CamelIMAPXConnManager *con_man,
const gchar *folder_name,
@@ -715,6 +772,7 @@ imapx_create_new_connection_unlocked (CamelIMAPXConnManager *con_man,
imapx_store = CAMEL_IMAPX_STORE (store);
is = camel_imapx_server_new (imapx_store);
+ is->tagprefix = imapx_conn_manager_get_next_free_tagprefix_unlocked (con_man);
/* XXX As part of the connect operation the CamelIMAPXServer will
* have to call camel_session_authenticate_sync(), but it has
@@ -798,11 +856,20 @@ camel_imapx_conn_manager_get_connection (CamelIMAPXConnManager *con_man,
g_return_val_if_fail (CAMEL_IS_IMAPX_CONN_MANAGER (con_man), NULL);
+ g_mutex_lock (&con_man->priv->pending_connections_lock);
+ if (cancellable) {
+ g_object_ref (cancellable);
+ } else {
+ cancellable = g_cancellable_new ();
+ }
+ con_man->priv->pending_connections = g_slist_prepend (con_man->priv->pending_connections, cancellable);
+ g_mutex_unlock (&con_man->priv->pending_connections_lock);
+
/* Hold the writer lock while we requisition a CamelIMAPXServer
* to prevent other threads from adding or removing connections. */
CON_WRITE_LOCK (con_man);
- /* Check if we got cancelled while waiting for the lock. */
+ /* Check if we've got cancelled while waiting for the lock. */
if (!g_cancellable_set_error_if_cancelled (cancellable, error)) {
is = imapx_find_connection_unlocked (con_man, folder_name, for_expensive_job);
if (is == NULL) {
@@ -838,6 +905,11 @@ camel_imapx_conn_manager_get_connection (CamelIMAPXConnManager *con_man,
CON_WRITE_UNLOCK (con_man);
+ g_mutex_lock (&con_man->priv->pending_connections_lock);
+ con_man->priv->pending_connections = g_slist_remove (con_man->priv->pending_connections, cancellable);
+ g_object_unref (cancellable);
+ g_mutex_unlock (&con_man->priv->pending_connections_lock);
+
return is;
}
@@ -892,6 +964,10 @@ camel_imapx_conn_manager_close_connections (CamelIMAPXConnManager *con_man,
g_return_if_fail (CAMEL_IS_IMAPX_CONN_MANAGER (con_man));
+ /* Do this before acquiring the write lock, because any pending
+ connection holds the write lock, thus makes this request starve. */
+ imax_conn_manager_cancel_pending_connections (con_man);
+
CON_WRITE_LOCK (con_man);
c('*', "Closing all %d connections, with propagated error: %s\n", g_list_length (con_man->priv->connections), error ? error->message : "none");
diff --git a/camel/providers/imapx/camel-imapx-mailbox.c b/camel/providers/imapx/camel-imapx-mailbox.c
index 3f4edd0..f5744e1 100644
--- a/camel/providers/imapx/camel-imapx-mailbox.c
+++ b/camel/providers/imapx/camel-imapx-mailbox.c
@@ -46,8 +46,12 @@ struct _CamelIMAPXMailboxPrivate {
guint32 uidnext;
guint32 uidvalidity;
guint64 highestmodseq;
+ guint32 permanentflags;
+
+ CamelIMAPXMailboxState state;
GMutex property_lock;
+ GRecMutex update_lock;
/* Protected by the "property_lock". */
GHashTable *attributes;
@@ -94,6 +98,7 @@ imapx_mailbox_finalize (GObject *object)
g_free (priv->name);
g_mutex_clear (&priv->property_lock);
+ g_rec_mutex_clear (&priv->update_lock);
g_hash_table_destroy (priv->attributes);
g_sequence_free (priv->message_map);
g_strfreev (priv->quota_roots);
@@ -120,7 +125,10 @@ camel_imapx_mailbox_init (CamelIMAPXMailbox *mailbox)
mailbox->priv = CAMEL_IMAPX_MAILBOX_GET_PRIVATE (mailbox);
g_mutex_init (&mailbox->priv->property_lock);
+ g_rec_mutex_init (&mailbox->priv->update_lock);
mailbox->priv->message_map = g_sequence_new (NULL);
+ mailbox->priv->permanentflags = ~0;
+ mailbox->priv->state = CAMEL_IMAPX_MAILBOX_STATE_CREATED;
}
/**
@@ -212,6 +220,7 @@ camel_imapx_mailbox_clone (CamelIMAPXMailbox *mailbox,
clone->priv->uidnext = mailbox->priv->uidnext;
clone->priv->uidvalidity = mailbox->priv->uidvalidity;
clone->priv->highestmodseq = mailbox->priv->highestmodseq;
+ clone->priv->state = mailbox->priv->state;
clone->priv->quota_roots = g_strdupv (mailbox->priv->quota_roots);
@@ -233,6 +242,46 @@ camel_imapx_mailbox_clone (CamelIMAPXMailbox *mailbox,
}
/**
+ * camel_imapx_mailbox_get_state:
+ * @mailbox: a #CamelIMAPXMailbox
+ *
+ * Returns current state of the mailbox. This is used for folder
+ * structure updates, to identify newly created, updated, renamed
+ * or removed mailboxes.
+ *
+ * Returns: Current (update) state of the mailbox.
+ *
+ * Since: 3.12.9
+ **/
+CamelIMAPXMailboxState
+camel_imapx_mailbox_get_state (CamelIMAPXMailbox *mailbox)
+{
+ g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), CAMEL_IMAPX_MAILBOX_STATE_UNKNOWN);
+
+ return mailbox->priv->state;
+}
+
+/**
+ * camel_imapx_mailbox_set_state:
+ * @mailbox: a #CamelIMAPXMailbox
+ * @state: a new #CamelIMAPXMailboxState to set
+ *
+ * Sets current (update) state of the mailbox. This is used for folder
+ * structure updates, to identify newly created, updated, renamed
+ * or removed mailboxes.
+ *
+ * Since: 3.12.9
+ **/
+void
+camel_imapx_mailbox_set_state (CamelIMAPXMailbox *mailbox,
+ CamelIMAPXMailboxState state)
+{
+ g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
+
+ mailbox->priv->state = state;
+}
+
+/**
* camel_imapx_mailbox_exists:
* @mailbox: a #CamelIMAPXMailbox
*
@@ -663,6 +712,41 @@ camel_imapx_mailbox_set_highestmodseq (CamelIMAPXMailbox *mailbox,
}
/**
+ * camel_imapx_mailbox_get_permanentflags:
+ * @mailbox: a #CamelIMAPXMailbox
+ *
+ * Returns: PERMANENTFLAGS response for the mailbox, or ~0, if the mailbox
+ * was not selected yet.
+ *
+ * Since: 3.12.8
+ **/
+guint32
+camel_imapx_mailbox_get_permanentflags (CamelIMAPXMailbox *mailbox)
+{
+ g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), ~0);
+
+ return mailbox->priv->permanentflags;
+}
+
+/**
+ * camel_imapx_mailbox_set_permanentflags:
+ * @mailbox: a #CamelIMAPXMailbox
+ * @permanentflags: a newly-reported "PERMANENTFLAGS" value
+ *
+ * Updates the last know value for PERMANENTFLAGS for this mailbox.
+ *
+ * Since: 3.12.8
+ **/
+void
+camel_imapx_mailbox_set_permanentflags (CamelIMAPXMailbox *mailbox,
+ guint32 permanentflags)
+{
+ g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
+
+ mailbox->priv->permanentflags = permanentflags;
+}
+
+/**
* camel_imapx_mailbox_dup_quota_roots:
* @mailbox: a #CamelIMAPXMailbox
*
@@ -1108,3 +1192,20 @@ camel_imapx_mailbox_handle_status_response (CamelIMAPXMailbox *mailbox,
mailbox->priv->highestmodseq = value64;
}
+/* Prevents running FETCH and STORE at the same time for the given mailbox */
+void
+camel_imapx_mailbox_lock_update (CamelIMAPXMailbox *mailbox)
+{
+ g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
+
+ g_rec_mutex_lock (&mailbox->priv->update_lock);
+}
+
+/* Prevents running FETCH and STORE at the same time for the given mailbox */
+void
+camel_imapx_mailbox_unlock_update (CamelIMAPXMailbox *mailbox)
+{
+ g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
+
+ g_rec_mutex_unlock (&mailbox->priv->update_lock);
+}
diff --git a/camel/providers/imapx/camel-imapx-mailbox.h b/camel/providers/imapx/camel-imapx-mailbox.h
index 76af75d..5b9ef52 100644
--- a/camel/providers/imapx/camel-imapx-mailbox.h
+++ b/camel/providers/imapx/camel-imapx-mailbox.h
@@ -47,6 +47,13 @@ typedef struct _CamelIMAPXMailbox CamelIMAPXMailbox;
typedef struct _CamelIMAPXMailboxClass CamelIMAPXMailboxClass;
typedef struct _CamelIMAPXMailboxPrivate CamelIMAPXMailboxPrivate;
+typedef enum {
+ CAMEL_IMAPX_MAILBOX_STATE_UNKNOWN,
+ CAMEL_IMAPX_MAILBOX_STATE_CREATED,
+ CAMEL_IMAPX_MAILBOX_STATE_UPDATED,
+ CAMEL_IMAPX_MAILBOX_STATE_RENAMED
+} CamelIMAPXMailboxState;
+
/**
* CamelIMAPXMailbox:
*
@@ -73,6 +80,12 @@ CamelIMAPXMailbox *
camel_imapx_mailbox_clone
(CamelIMAPXMailbox *mailbox,
const gchar *new_mailbox_name);
+CamelIMAPXMailboxState
+ camel_imapx_mailbox_get_state
+ (CamelIMAPXMailbox *mailbox);
+void camel_imapx_mailbox_set_state
+ (CamelIMAPXMailbox *mailbox,
+ CamelIMAPXMailboxState state);
gboolean camel_imapx_mailbox_exists
(CamelIMAPXMailbox *mailbox);
gint camel_imapx_mailbox_compare
@@ -120,6 +133,11 @@ guint64 camel_imapx_mailbox_get_highestmodseq
void camel_imapx_mailbox_set_highestmodseq
(CamelIMAPXMailbox *mailbox,
guint64 highestmodseq);
+guint32 camel_imapx_mailbox_get_permanentflags
+ (CamelIMAPXMailbox *mailbox);
+void camel_imapx_mailbox_set_permanentflags
+ (CamelIMAPXMailbox *mailbox,
+ guint32 permanentflags);
gchar ** camel_imapx_mailbox_dup_quota_roots
(CamelIMAPXMailbox *mailbox);
void camel_imapx_mailbox_set_quota_roots
@@ -157,6 +175,11 @@ void camel_imapx_mailbox_handle_status_response
(CamelIMAPXMailbox *mailbox,
CamelIMAPXStatusResponse *response);
+void camel_imapx_mailbox_lock_update
+ (CamelIMAPXMailbox *mailbox);
+void camel_imapx_mailbox_unlock_update
+ (CamelIMAPXMailbox *mailbox);
+
G_END_DECLS
#endif /* CAMEL_IMAPX_MAILBOX_H */
diff --git a/camel/providers/imapx/camel-imapx-namespace-response.c b/camel/providers/imapx/camel-imapx-namespace-response.c
index 3295d10..75e1938 100644
--- a/camel/providers/imapx/camel-imapx-namespace-response.c
+++ b/camel/providers/imapx/camel-imapx-namespace-response.c
@@ -500,7 +500,10 @@ camel_imapx_namespace_response_lookup_for_path (CamelIMAPXNamespaceResponse *res
/* Special handling when searching for an empty prefix. */
if (find_empty_prefix) {
- if (*prefix == '\0') {
+ if (*prefix == '\0' ||
+ g_ascii_strcasecmp (prefix, "INBOX") == 0 ||
+ (g_ascii_strncasecmp (prefix, "INBOX", 5) == 0 &&
+ prefix[5] == separator && !prefix[6])) {
g_queue_push_tail (&candidates, namespace);
break;
}
@@ -523,6 +526,11 @@ camel_imapx_namespace_response_lookup_for_path (CamelIMAPXNamespaceResponse *res
/* First candidate is the preferred namespace. */
match = g_queue_pop_head (&candidates);
+
+ /* Fallback to the first known namespace when none suitable for the given path found */
+ if (!match && head && head->data)
+ match = head->data;
+
if (match != NULL)
g_object_ref (match);
diff --git a/camel/providers/imapx/camel-imapx-server.c b/camel/providers/imapx/camel-imapx-server.c
index d61b702..ff5fa96 100644
--- a/camel/providers/imapx/camel-imapx-server.c
+++ b/camel/providers/imapx/camel-imapx-server.c
@@ -125,6 +125,7 @@ struct _RefreshInfoData {
struct _SyncChangesData {
CamelFolder *folder;
GPtrArray *changed_uids;
+ gboolean own_allocated_changed_uids;
guint32 on_set;
guint32 off_set;
GArray *on_user; /* imapx_flag_change */
@@ -365,7 +366,6 @@ struct _CamelIMAPXServerPrivate {
GWeakRef select_closing;
GWeakRef select_pending;
CamelFolderChangeInfo *changes;
- guint32 permanentflags;
/* Data items to request in STATUS commands:
* STATUS $mailbox_name ($status_data_items) */
@@ -843,10 +843,16 @@ static void
sync_changes_data_free (SyncChangesData *data)
{
if (data->folder != NULL) {
- camel_folder_free_uids (data->folder, data->changed_uids);
+ if (!data->own_allocated_changed_uids)
+ camel_folder_free_uids (data->folder, data->changed_uids);
g_object_unref (data->folder);
}
+ if (data->own_allocated_changed_uids && data->changed_uids) {
+ g_ptr_array_foreach (data->changed_uids, (GFunc) camel_pstring_free, NULL);
+ g_ptr_array_free (data->changed_uids, TRUE);
+ }
+
imapx_sync_free_user (data->on_user);
imapx_sync_free_user (data->off_user);
@@ -1204,6 +1210,25 @@ imapx_server_reset_inactivity_timer (CamelIMAPXServer *is)
g_mutex_unlock (&is->priv->inactivity_timeout_lock);
}
+static gint
+imapx_server_set_connection_timeout (GIOStream *connection,
+ gint timeout_seconds)
+{
+ GSocket *socket;
+ gint previous_timeout = -1;
+
+ if (!G_IS_SOCKET_CONNECTION (connection))
+ return previous_timeout;
+
+ socket = g_socket_connection_get_socket (connection);
+ if (socket) {
+ previous_timeout = g_socket_get_timeout (socket);
+ g_socket_set_timeout (socket, timeout_seconds);
+ }
+
+ return previous_timeout;
+}
+
/* Must hold QUEUE_LOCK */
static void
imapx_command_start (CamelIMAPXServer *is,
@@ -1280,9 +1305,11 @@ imapx_command_start (CamelIMAPXServer *is,
string = g_strdup_printf (
"%c%05u %s\r\n", is->tagprefix, ic->tag, cp->data);
+ g_mutex_lock (&is->priv->stream_lock);
g_output_stream_write_all (
output_stream, string, strlen (string),
NULL, cancellable, &local_error);
+ g_mutex_unlock (&is->priv->stream_lock);
g_free (string);
if (local_error != NULL)
@@ -2197,14 +2224,17 @@ imapx_untagged_fetch (CamelIMAPXServer *is,
size than it actually is, which results in no data being read from
the server for that particular offset. */
if (body_size) {
+ g_mutex_lock (&is->priv->stream_lock);
if (!g_output_stream_write_all (
output_stream, body_data, body_size,
NULL, cancellable, error)) {
+ g_mutex_unlock (&is->priv->stream_lock);
g_prefix_error (
error, "%s: ",
_("Error writing to cache stream"));
return FALSE;
}
+ g_mutex_unlock (&is->priv->stream_lock);
}
}
}
@@ -2273,7 +2303,7 @@ imapx_untagged_fetch (CamelIMAPXServer *is,
changed = imapx_update_message_info_flags (
mi, finfo->flags,
finfo->user_flags,
- is->priv->permanentflags,
+ camel_imapx_mailbox_get_permanentflags (select_mailbox),
select_folder,
(select_pending == NULL));
} else {
@@ -2431,7 +2461,7 @@ imapx_untagged_fetch (CamelIMAPXServer *is,
data = camel_imapx_job_get_data (job);
g_return_val_if_fail (data != NULL, FALSE);
- imapx_set_message_info_flags_for_new_message (mi, server_flags, server_user_flags, FALSE, NULL, is->priv->permanentflags);
+ imapx_set_message_info_flags_for_new_message (mi, server_flags, server_user_flags, FALSE, NULL, camel_imapx_mailbox_get_permanentflags (mailbox));
camel_folder_summary_add (folder->summary, mi);
camel_folder_change_info_add_uid (data->changes, mi->uid);
@@ -2860,10 +2890,6 @@ imapx_untagged_ok_no_bad (CamelIMAPXServer *is,
g_clear_object (&select_pending);
}
break;
- case IMAPX_PERMANENTFLAGS:
- is->priv->permanentflags =
- is->priv->context->sinfo->u.permanentflags;
- break;
case IMAPX_ALERT:
c (is->tagprefix, "ALERT!: %s\n", is->priv->context->sinfo->text);
{
@@ -3146,9 +3172,11 @@ imapx_continuation (CamelIMAPXServer *is,
return FALSE;
c (is->tagprefix, "got auth continuation, feeding token '%s' back to auth mech\n", resp);
+ g_mutex_lock (&is->priv->stream_lock);
n_bytes_written = g_output_stream_write_all (
output_stream, resp, strlen (resp),
NULL, cancellable, error);
+ g_mutex_unlock (&is->priv->stream_lock);
g_free (resp);
if (n_bytes_written < 0)
@@ -3173,11 +3201,13 @@ imapx_continuation (CamelIMAPXServer *is,
if (file_input_stream == NULL)
return FALSE;
+ g_mutex_lock (&is->priv->stream_lock);
n_bytes_written = g_output_stream_splice (
output_stream,
G_INPUT_STREAM (file_input_stream),
G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE,
cancellable, error);
+ g_mutex_unlock (&is->priv->stream_lock);
g_object_unref (file_input_stream);
@@ -3186,9 +3216,11 @@ imapx_continuation (CamelIMAPXServer *is,
break; }
case CAMEL_IMAPX_COMMAND_STRING:
+ g_mutex_lock (&is->priv->stream_lock);
n_bytes_written = g_output_stream_write_all (
output_stream, cp->ob, cp->ob_size,
NULL, cancellable, error);
+ g_mutex_unlock (&is->priv->stream_lock);
if (n_bytes_written < 0)
return FALSE;
break;
@@ -3218,9 +3250,11 @@ noskip:
c (is->tagprefix, "next part of command \"%c%05u: %s\"\n", is->tagprefix, ic->tag, cp->data);
+ g_mutex_lock (&is->priv->stream_lock);
n_bytes_written = g_output_stream_write_all (
output_stream, cp->data, strlen (cp->data),
NULL, cancellable, error);
+ g_mutex_unlock (&is->priv->stream_lock);
if (n_bytes_written < 0)
return FALSE;
@@ -3233,8 +3267,10 @@ noskip:
c (is->tagprefix, "%p: queueing continuation\n", ic);
}
+ g_mutex_lock (&is->priv->stream_lock);
n_bytes_written = g_output_stream_write_all (
output_stream, "\r\n", 2, NULL, cancellable, error);
+ g_mutex_unlock (&is->priv->stream_lock);
if (n_bytes_written < 0)
return FALSE;
@@ -3514,6 +3550,25 @@ imapx_command_run_sync (CamelIMAPXServer *is,
return success;
}
+static gboolean
+imapx_ensure_mailbox_permanentflags (CamelIMAPXServer *is,
+ CamelIMAPXMailbox *mailbox,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (is), FALSE);
+ g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), FALSE);
+
+ if (camel_imapx_mailbox_get_permanentflags (mailbox) != ~0)
+ return TRUE;
+
+ /* This will also invoke SELECT command, which updates PERMANENTFLAGS
+ for the mailbox. There might be possible to use EXAMINE for it,
+ but some servers do not return the same set of flags as with SELECT.
+ It's a little hack on top of the IMAPx implementation. */
+ return camel_imapx_server_noop (is, mailbox, cancellable, error);
+}
+
/* ********************************************************************** */
// IDLE support
@@ -3533,8 +3588,10 @@ imapx_command_idle_stop (CamelIMAPXServer *is,
cancellable = g_weak_ref_get (&is->priv->parser_cancellable);
+ g_mutex_lock (&is->priv->stream_lock);
success = g_output_stream_write_all (
output_stream, "DONE\r\n", 6, NULL, cancellable, error);
+ g_mutex_unlock (&is->priv->stream_lock);
if (!success) {
g_prefix_error (error, "Unable to issue DONE: ");
@@ -3630,6 +3687,7 @@ camel_imapx_server_idle (CamelIMAPXServer *is,
GError **error)
{
CamelIMAPXJob *job;
+ gint previous_connection_timeout;
gboolean success;
job = camel_imapx_job_new (cancellable);
@@ -3638,8 +3696,13 @@ camel_imapx_server_idle (CamelIMAPXServer *is,
camel_imapx_job_set_mailbox (job, mailbox);
+ previous_connection_timeout = imapx_server_set_connection_timeout (is->priv->connection, 0);
+
success = imapx_submit_job (is, job, error);
+ if (previous_connection_timeout >= 0)
+ imapx_server_set_connection_timeout (is->priv->connection, previous_connection_timeout);
+
camel_imapx_job_unref (job);
return success;
@@ -3941,6 +4004,7 @@ imapx_command_select_done (CamelIMAPXServer *is,
CamelIMAPXCommandQueue *failed;
GQueue trash = G_QUEUE_INIT;
GList *list, *link;
+ gboolean noperm_error;
c (is->tagprefix, "Select failed: %s\n", local_error ? local_error->message : "Unknown error");
@@ -3957,6 +4021,9 @@ imapx_command_select_done (CamelIMAPXServer *is,
QUEUE_LOCK (is);
+ noperm_error = select_pending != NULL && ic->status && ic->status->result == IMAPX_NO &&
+ (ic->status->condition == IMAPX_NOPERM || ic->status->condition == IMAPX_UNKNOWN);
+
if (select_pending != NULL) {
GList *head = camel_imapx_command_queue_peek_head_link (is->queue);
@@ -3980,6 +4047,13 @@ imapx_command_select_done (CamelIMAPXServer *is,
}
}
+ if (noperm_error) {
+ /* This avoids another SELECT try on this mailbox;
+ the mailbox can be write-only in this case. */
+ if (camel_imapx_mailbox_get_permanentflags (select_pending) == ~0)
+ camel_imapx_mailbox_set_permanentflags (select_pending, 0);
+ }
+
while ((link = g_queue_pop_head (&trash)) != NULL) {
CamelIMAPXCommand *cw = link->data;
camel_imapx_command_ref (cw);
@@ -4004,7 +4078,8 @@ imapx_command_select_done (CamelIMAPXServer *is,
continue;
}
- camel_imapx_job_cancel (failed_job);
+ if (!noperm_error)
+ camel_imapx_job_cancel (failed_job);
if (ic->status)
cw->status = imapx_copy_status (ic->status);
@@ -4121,8 +4196,6 @@ imapx_maybe_select (CamelIMAPXServer *is,
g_weak_ref_set (&is->priv->select_closing, select_mailbox);
- is->priv->permanentflags = 0;
-
/* Hrm, what about reconnecting? */
is->state = IMAPX_INITIALISED;
}
@@ -4497,16 +4570,6 @@ connected:
while (1) {
GInputStream *input_stream;
- // poll ? wait for other stuff? loop?
- if (camel_application_is_exiting) {
- g_set_error (
- error, G_IO_ERROR,
- G_IO_ERROR_CANCELLED,
- "Connection to server cancelled\n");
- success = FALSE;
- goto exit;
- }
-
input_stream = camel_imapx_server_ref_input_stream (is);
tok = camel_imapx_input_stream_token (
@@ -5275,7 +5338,7 @@ imapx_command_copy_messages_step_done (CamelIMAPXServer *is,
((CamelMessageInfoBase *) source_info)->user_flags,
TRUE,
((CamelMessageInfoBase *) source_info)->user_tags,
- is->priv->permanentflags);
+ camel_imapx_mailbox_get_permanentflags (data->destination));
if (is_new)
camel_folder_summary_add (destination->summary, destination_info);
camel_folder_change_info_add_uid (changes, destination_info->uid);
@@ -5472,7 +5535,7 @@ imapx_command_append_message_done (CamelIMAPXServer *is,
((CamelMessageInfoBase *) data->info)->user_flags,
TRUE,
((CamelMessageInfoBase *) data->info)->user_tags,
- is->priv->permanentflags);
+ camel_imapx_mailbox_get_permanentflags (mailbox));
camel_folder_summary_add (folder->summary, mi);
changes = camel_folder_change_info_new ();
camel_folder_change_info_add_uid (changes, mi->uid);
@@ -5918,7 +5981,7 @@ imapx_job_scan_changes_done (CamelIMAPXServer *is,
(CamelMessageInfo *) info,
r->server_flags,
r->server_user_flags,
- is->priv->permanentflags,
+ camel_imapx_mailbox_get_permanentflags (mailbox),
folder, FALSE))
camel_folder_change_info_change_uid (
data->changes,
@@ -7292,9 +7355,11 @@ imapx_command_sync_changes_done (CamelIMAPXServer *is,
/* lock cache ? */
} else {
- guint32 unseen;
+ guint32 unseen, permanentflags;
gint i;
+ permanentflags = camel_imapx_mailbox_get_permanentflags (mailbox);
+
for (i = 0; i < data->changed_uids->len; i++) {
CamelIMAPXMessageInfo *xinfo = (CamelIMAPXMessageInfo *) camel_folder_summary_get (folder->summary,
data->changed_uids->pdata[i]);
@@ -7312,7 +7377,7 @@ imapx_command_sync_changes_done (CamelIMAPXServer *is,
xinfo->info.flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
}
xinfo->info.dirty = TRUE;
- if ((is->priv->permanentflags & CAMEL_MESSAGE_USER) != 0 ||
+ if ((permanentflags & CAMEL_MESSAGE_USER) != 0 ||
camel_flag_list_size (&xinfo->server_user_flags) == 0)
camel_flag_list_copy (&xinfo->server_user_flags, &xinfo->info.user_flags);
@@ -7370,7 +7435,7 @@ imapx_job_sync_changes_start (CamelIMAPXJob *job,
SyncChangesData *data;
CamelFolder *folder;
CamelIMAPXMailbox *mailbox;
- guint32 i, j;
+ guint32 i, j, permanentflags;
struct _uidset_state ss;
GPtrArray *uids;
gint on;
@@ -7384,6 +7449,7 @@ imapx_job_sync_changes_start (CamelIMAPXJob *job,
folder = imapx_server_ref_folder (is, mailbox);
g_return_val_if_fail (folder != NULL, FALSE);
+ permanentflags = camel_imapx_mailbox_get_permanentflags (mailbox);
uids = data->changed_uids;
for (on = 0; on < 2; on++) {
@@ -7414,8 +7480,8 @@ imapx_job_sync_changes_start (CamelIMAPXJob *job,
if (info == NULL)
continue;
- flags = info->info.flags & CAMEL_IMAPX_SERVER_FLAGS;
- sflags = info->server_flags & CAMEL_IMAPX_SERVER_FLAGS;
+ flags = (info->info.flags & CAMEL_IMAPX_SERVER_FLAGS) & permanentflags;
+ sflags = (info->server_flags & CAMEL_IMAPX_SERVER_FLAGS) & permanentflags;
send = 0;
remove_deleted_flag =
@@ -7441,7 +7507,7 @@ imapx_job_sync_changes_start (CamelIMAPXJob *job,
}
send = imapx_uidset_add (&ss, ic, camel_message_info_uid (info));
}
- if (send == 1 || (i == uids->len - 1 && imapx_uidset_done (&ss, ic))) {
+ if (send == 1 || (i == uids->len - 1 && ic && imapx_uidset_done (&ss, ic))) {
g_atomic_int_add (&job->commands, 1);
camel_imapx_command_add (ic, " %tFLAGS.SILENT (%t)", on?"+":"-", flags_table[j].name);
imapx_command_queue (is, ic);
@@ -7456,11 +7522,20 @@ imapx_job_sync_changes_start (CamelIMAPXJob *job,
else
data->unread_change++;
}
+
+ /* The second round and the server doesn't support saving user flags,
+ thus store them at least locally */
+ if (on && (permanentflags & CAMEL_MESSAGE_USER) == 0) {
+ camel_flag_list_copy (&info->server_user_flags, &info->info.user_flags);
+ }
+
camel_message_info_unref (info);
}
+
+ g_warn_if_fail (ic == NULL);
}
- if (user_set) {
+ if (user_set && (permanentflags & CAMEL_MESSAGE_USER) != 0) {
CamelIMAPXCommand *ic = NULL;
for (j = 0; j < user_set->len; j++) {
@@ -7619,11 +7694,21 @@ imapx_ready_to_read (GInputStream *input_stream,
g_clear_object (&output_stream);
g_clear_object (&cancellable);
+ if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT)) {
+ QUEUE_LOCK (is);
+ if (camel_imapx_command_queue_is_empty (is->active) && is->state != IMAPX_SHUTDOWN) {
+ camel_imapx_debug (io, is->tagprefix, "Ignoring timeout error, nothing was waiting (original error: %s)\n", local_error->message);
+ g_clear_error (&local_error);
+ }
+ QUEUE_UNLOCK (is);
+ }
+
if (local_error != NULL) {
camel_imapx_debug (io, is->tagprefix, "Data read failed with error '%s'\n", local_error->message);
/* Sadly, G_IO_ERROR_FAILED is also used for 'Connection reset by peer' error */
- if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_FAILED)) {
+ if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_FAILED) ||
+ g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT)) {
local_error->domain = CAMEL_IMAPX_SERVER_ERROR;
local_error->code = CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT;
}
@@ -7859,18 +7944,12 @@ static void
imapx_server_constructed (GObject *object)
{
CamelIMAPXServer *server;
- CamelIMAPXServerClass *class;
/* Chain up to parent's method. */
G_OBJECT_CLASS (camel_imapx_server_parent_class)->constructed (object);
server = CAMEL_IMAPX_SERVER (object);
- class = CAMEL_IMAPX_SERVER_GET_CLASS (server);
-
- server->tagprefix = class->tagprefix;
- class->tagprefix++;
- if (class->tagprefix > 'Z')
- class->tagprefix = 'A';
+ server->tagprefix = 'Z';
}
static void
@@ -7959,8 +8038,6 @@ camel_imapx_server_class_init (CamelIMAPXServerClass *class)
NULL, NULL,
g_cclosure_marshal_VOID__BOXED,
G_TYPE_NONE, 1, G_TYPE_ERROR);
-
- class->tagprefix = 'A';
}
static void
@@ -8407,6 +8484,13 @@ camel_imapx_server_copy_message (CamelIMAPXServer *is,
g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (destination), FALSE);
g_return_val_if_fail (uids != NULL, FALSE);
+ /* That's okay if the "SELECT" fails here, as it can be due to
+ the folder being write-only; just ignore the error and continue. */
+ imapx_ensure_mailbox_permanentflags (is, destination, cancellable, NULL);
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return FALSE;
+
data = g_slice_new0 (CopyMessagesData);
data->destination = g_object_ref (destination);
data->uids = g_ptr_array_new ();
@@ -8470,6 +8554,13 @@ camel_imapx_server_append_message (CamelIMAPXServer *is,
g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), FALSE);
/* CamelMessageInfo can be NULL. */
+ /* That's okay if the "SELECT" fails here, as it can be due to
+ the folder being write-only; just ignore the error and continue. */
+ imapx_ensure_mailbox_permanentflags (is, mailbox, cancellable, NULL);
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return FALSE;
+
/* Append just assumes we have no/a dodgy connection. We dump
* stuff into the 'new' directory, and let the summary know it's
* there. Then we fire off a no-reply job which will asynchronously
@@ -8544,6 +8635,9 @@ camel_imapx_server_append_message (CamelIMAPXServer *is,
g_free (uid);
+ if (camel_mime_message_has_attachment (message))
+ ((CamelMessageInfoBase *) info)->flags |= CAMEL_MESSAGE_ATTACHMENTS;
+
/* So, we actually just want to let the server loop that
* messages need appending, i think. This is so the same
* mechanism is used for normal uploading as well as
@@ -8616,8 +8710,8 @@ camel_imapx_server_refresh_info (CamelIMAPXServer *is,
gboolean registered = TRUE;
const gchar *mailbox_name;
- g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (is), FALSE);
- g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), FALSE);
+ g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (is), NULL);
+ g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), NULL);
/* Don't run concurrent refreshes on the same mailbox.
* If a refresh is already in progress, let it finish
@@ -8629,6 +8723,9 @@ camel_imapx_server_refresh_info (CamelIMAPXServer *is,
return camel_folder_change_info_new ();
}
+ if (!imapx_ensure_mailbox_permanentflags (is, mailbox, cancellable, error))
+ return NULL;
+
QUEUE_LOCK (is);
data = g_slice_new0 (RefreshInfoData);
@@ -8654,11 +8751,17 @@ camel_imapx_server_refresh_info (CamelIMAPXServer *is,
QUEUE_UNLOCK (is);
+ if (registered)
+ camel_imapx_mailbox_lock_update (mailbox);
+
if (registered && camel_imapx_job_run (job, is, error)) {
changes = data->changes;
data->changes = NULL;
}
+ if (registered)
+ camel_imapx_mailbox_unlock_update (mailbox);
+
camel_imapx_job_unref (job);
return changes;
@@ -8745,11 +8848,15 @@ imapx_server_sync_changes (CamelIMAPXServer *is,
gboolean remove_deleted_flags;
gboolean nothing_to_do;
gboolean registered;
+ gboolean own_allocated_changed_uids = FALSE;
gboolean success = TRUE;
folder = imapx_server_ref_folder (is, mailbox);
g_return_val_if_fail (folder != NULL, FALSE);
+ if (!imapx_ensure_mailbox_permanentflags (is, mailbox, cancellable, error))
+ return FALSE;
+
/* We calculate two masks, a mask of all flags which have been
* turned off and a mask of all flags which have been turned
* on. If either of these aren't 0, then we have work to do,
@@ -8818,73 +8925,65 @@ imapx_server_sync_changes (CamelIMAPXServer *is,
camel_imapx_folder_add_move_to_real_trash (
CAMEL_IMAPX_FOLDER (folder), uid);
- flags &= is->priv->permanentflags;
- sflags &= is->priv->permanentflags;
-
if (flags != sflags) {
off_orset |= (flags ^ sflags) & ~flags;
on_orset |= (flags ^ sflags) & flags;
}
- if ((is->priv->permanentflags & CAMEL_MESSAGE_USER) != 0) {
- uflags = info->info.user_flags;
- suflags = info->server_user_flags;
- while (uflags || suflags) {
- gint res;
-
- if (uflags) {
- if (suflags)
- res = strcmp (uflags->name, suflags->name);
- else if (*uflags->name)
- res = -1;
- else {
- uflags = uflags->next;
- continue;
- }
- } else {
- res = 1;
+ uflags = info->info.user_flags;
+ suflags = info->server_user_flags;
+ while (uflags || suflags) {
+ gint res;
+
+ if (uflags) {
+ if (suflags)
+ res = strcmp (uflags->name, suflags->name);
+ else if (*uflags->name)
+ res = -1;
+ else {
+ uflags = uflags->next;
+ continue;
}
+ } else {
+ res = 1;
+ }
- if (res == 0) {
+ if (res == 0) {
+ uflags = uflags->next;
+ suflags = suflags->next;
+ } else {
+ GArray *user_set;
+ CamelFlag *user_flag;
+ struct _imapx_flag_change *change = NULL, add = { 0 };
+
+ if (res < 0) {
+ if (on_user == NULL)
+ on_user = g_array_new (FALSE, FALSE, sizeof (struct _imapx_flag_change));
+ user_set = on_user;
+ user_flag = uflags;
uflags = uflags->next;
- suflags = suflags->next;
} else {
- GArray *user_set;
- CamelFlag *user_flag;
- struct _imapx_flag_change *change = NULL, add = { 0 };
-
- if (res < 0) {
- if (on_user == NULL)
- on_user = g_array_new (FALSE, FALSE, sizeof (struct _imapx_flag_change));
- user_set = on_user;
- user_flag = uflags;
- uflags = uflags->next;
- } else {
- if (off_user == NULL)
- off_user = g_array_new (FALSE, FALSE, sizeof (struct _imapx_flag_change));
- user_set = off_user;
- user_flag = suflags;
- suflags = suflags->next;
- }
+ if (off_user == NULL)
+ off_user = g_array_new (FALSE, FALSE, sizeof (struct _imapx_flag_change));
+ user_set = off_user;
+ user_flag = suflags;
+ suflags = suflags->next;
+ }
- /* Could sort this and binary search */
- for (j = 0; j < user_set->len; j++) {
- change = &g_array_index (user_set, struct _imapx_flag_change, j);
- if (strcmp (change->name, user_flag->name) == 0)
- goto found;
- }
- add.name = g_strdup (user_flag->name);
- add.infos = g_ptr_array_new ();
- g_array_append_val (user_set, add);
- change = &add;
- found:
- camel_message_info_ref (info);
- g_ptr_array_add (change->infos, info);
+ /* Could sort this and binary search */
+ for (j = 0; j < user_set->len; j++) {
+ change = &g_array_index (user_set, struct _imapx_flag_change, j);
+ if (strcmp (change->name, user_flag->name) == 0)
+ goto found;
}
+ add.name = g_strdup (user_flag->name);
+ add.infos = g_ptr_array_new ();
+ g_array_append_val (user_set, add);
+ change = &add;
+ found:
+ camel_message_info_ref (info);
+ g_ptr_array_add (change->infos, info);
}
- } else {
- /* Cannot save user flags to the server => store them locally only */
- camel_flag_list_copy (&info->server_user_flags, &info->info.user_flags);
}
camel_message_info_unref (info);
@@ -8910,16 +9009,57 @@ imapx_server_sync_changes (CamelIMAPXServer *is,
job = imapx_server_ref_job (is, mailbox, IMAPX_JOB_SYNC_CHANGES, NULL);
if (job != NULL) {
- if (pri > job->pri)
- job->pri = pri;
+ GPtrArray *new_changed_uids;
+ GHashTable *known_uids;
+ GHashTableIter iter;
+ gpointer key, value;
+ gint ii;
- camel_imapx_job_unref (job);
+ known_uids = g_hash_table_new (g_str_hash, g_str_equal);
+ data = camel_imapx_job_get_data (job);
+
+ if (data && data->changed_uids) {
+ for (ii = 0; ii < changed_uids->len; ii++) {
+ g_hash_table_insert (known_uids, changed_uids->pdata[ii], GINT_TO_POINTER (1));
+ }
+
+ for (ii = 0; ii < data->changed_uids->len; ii++) {
+ g_hash_table_remove (known_uids, data->changed_uids->pdata[ii]);
+ }
+ }
+
+ if (g_hash_table_size (known_uids) == 0) {
+ /* The pending job stores changes for the same UIDs */
+ if (pri > job->pri)
+ job->pri = pri;
+
+ camel_imapx_job_unref (job);
+
+ imapx_sync_free_user (on_user);
+ imapx_sync_free_user (off_user);
+ camel_folder_free_uids (folder, changed_uids);
+ g_object_unref (folder);
+ g_hash_table_destroy (known_uids);
+ return TRUE;
+ }
+
+ new_changed_uids = g_ptr_array_sized_new (g_hash_table_size (known_uids));
+
+ /* What left in known_uids are message info changes which are not being
+ saved in the pending job */
+
+ g_hash_table_iter_init (&iter, known_uids);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ g_ptr_array_add (new_changed_uids, (gpointer) camel_pstring_strdup (key));
+ }
+
+ g_hash_table_destroy (known_uids);
- imapx_sync_free_user (on_user);
- imapx_sync_free_user (off_user);
camel_folder_free_uids (folder, changed_uids);
- g_object_unref (folder);
- return TRUE;
+ changed_uids = new_changed_uids;
+
+ /* Why would anyone define a virtual function for the free on the folder? */
+ own_allocated_changed_uids = TRUE;
}
QUEUE_LOCK (is);
@@ -8927,6 +9067,7 @@ imapx_server_sync_changes (CamelIMAPXServer *is,
data = g_slice_new0 (SyncChangesData);
data->folder = g_object_ref (folder);
data->changed_uids = changed_uids; /* takes ownership */
+ data->own_allocated_changed_uids = own_allocated_changed_uids;
data->on_set = on_orset;
data->off_set = off_orset;
data->on_user = on_user; /* takes ownership */
@@ -8948,8 +9089,14 @@ imapx_server_sync_changes (CamelIMAPXServer *is,
QUEUE_UNLOCK (is);
+ if (job_type == IMAPX_JOB_SYNC_CHANGES && registered)
+ camel_imapx_mailbox_lock_update (mailbox);
+
success = registered && camel_imapx_job_run (job, is, error);
+ if (job_type == IMAPX_JOB_SYNC_CHANGES && registered)
+ camel_imapx_mailbox_unlock_update (mailbox);
+
camel_imapx_job_unref (job);
g_object_unref (folder);
diff --git a/camel/providers/imapx/camel-imapx-server.h b/camel/providers/imapx/camel-imapx-server.h
index a8bdbd7..095953f 100644
--- a/camel/providers/imapx/camel-imapx-server.h
+++ b/camel/providers/imapx/camel-imapx-server.h
@@ -129,8 +129,6 @@ struct _CamelIMAPXServer {
struct _CamelIMAPXServerClass {
GObjectClass parent_class;
- gchar tagprefix;
-
/* Signals */
void (*mailbox_select) (CamelIMAPXServer *is,
CamelIMAPXMailbox *mailbox);
diff --git a/camel/providers/imapx/camel-imapx-store.c b/camel/providers/imapx/camel-imapx-store.c
index 947d7e8..d8b5162 100644
--- a/camel/providers/imapx/camel-imapx-store.c
+++ b/camel/providers/imapx/camel-imapx-store.c
@@ -848,11 +848,15 @@ imapx_query_auth_types_sync (CamelService *service,
GError **error)
{
CamelServiceAuthType *authtype;
+ CamelIMAPXStore *imapx_store;
GList *sasl_types = NULL;
GList *t, *next;
CamelIMAPXServer *server;
- server = camel_imapx_server_new (CAMEL_IMAPX_STORE (service));
+ imapx_store = CAMEL_IMAPX_STORE (service);
+
+ server = camel_imapx_server_new (imapx_store);
+ server->tagprefix = 'Z';
if (!imapx_connect_to_server (server, cancellable, error))
goto exit;
@@ -989,6 +993,7 @@ event:
camel_store_summary_save (imapx_store->summary);
fi = imapx_store_build_folder_info (imapx_store, folder_path, 0);
+ camel_subscribable_folder_unsubscribed (CAMEL_SUBSCRIBABLE (imapx_store), fi);
camel_store_folder_deleted (CAMEL_STORE (imapx_store), fi);
camel_folder_info_free (fi);
}
@@ -1348,10 +1353,73 @@ exit:
return success;
}
+static void
+imapx_store_mark_mailbox_unknown_cb (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ CamelIMAPXMailbox *mailbox = value;
+
+ g_return_if_fail (mailbox != NULL);
+
+ camel_imapx_mailbox_set_state (mailbox, CAMEL_IMAPX_MAILBOX_STATE_UNKNOWN);
+}
+
+static gboolean
+imapx_store_remove_unknown_mailboxes_cb (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ CamelIMAPXMailbox *mailbox = value;
+ CamelIMAPXStore *imapx_store = user_data;
+ CamelStoreInfo *si;
+
+ g_return_val_if_fail (mailbox != NULL, FALSE);
+ g_return_val_if_fail (CAMEL_IS_IMAPX_STORE (imapx_store), FALSE);
+
+ if (camel_imapx_mailbox_get_state (mailbox) == CAMEL_IMAPX_MAILBOX_STATE_CREATED) {
+ CamelFolderInfo *fi;
+ gchar *folder_path;
+
+ folder_path = camel_imapx_mailbox_dup_folder_path (mailbox);
+ fi = imapx_store_build_folder_info (imapx_store, folder_path,
+ imapx_store_mailbox_attributes_to_flags (mailbox));
+ camel_store_folder_created (CAMEL_STORE (imapx_store), fi);
+ camel_subscribable_folder_subscribed (CAMEL_SUBSCRIBABLE (imapx_store), fi);
+ camel_folder_info_free (fi);
+ g_free (folder_path);
+ }
+
+ if (camel_imapx_mailbox_get_state (mailbox) != CAMEL_IMAPX_MAILBOX_STATE_UNKNOWN) {
+ return FALSE;
+ }
+
+ si = (CamelStoreInfo *) camel_imapx_store_summary_mailbox (imapx_store->summary, camel_imapx_mailbox_get_name (mailbox));
+ if (si) {
+ const gchar *si_path;
+ gchar *dup_folder_path;
+
+ si_path = camel_store_info_path (imapx_store->summary, si);
+ dup_folder_path = g_strdup (si_path);
+
+ if (dup_folder_path != NULL) {
+ imapx_delete_folder_from_cache (imapx_store, dup_folder_path);
+ g_free (dup_folder_path);
+ } else {
+ camel_store_summary_remove (imapx_store->summary, si);
+ }
+
+ camel_store_summary_info_unref (imapx_store->summary, si);
+ }
+
+ return TRUE;
+}
+
static gboolean
sync_folders (CamelIMAPXStore *imapx_store,
const gchar *root_folder_path,
CamelStoreGetFolderInfoFlags flags,
+ gboolean initial_setup,
GCancellable *cancellable,
GError **error)
{
@@ -1376,6 +1444,12 @@ sync_folders (CamelIMAPXStore *imapx_store,
* in imapx_store_process_mailbox_attributes(). */
g_atomic_int_inc (&imapx_store->priv->syncing_folders);
+ if (!initial_setup && (!root_folder_path || !*root_folder_path)) {
+ g_mutex_lock (&imapx_store->priv->mailboxes_lock);
+ g_hash_table_foreach (imapx_store->priv->mailboxes, imapx_store_mark_mailbox_unknown_cb, imapx_store);
+ g_mutex_unlock (&imapx_store->priv->mailboxes_lock);
+ }
+
if (root_folder_path != NULL && *root_folder_path != '\0') {
success = fetch_folder_info_from_folder_path (
imapx_store, server, root_folder_path, flags,
@@ -1406,6 +1480,12 @@ sync_folders (CamelIMAPXStore *imapx_store,
if (!success)
goto exit;
+ if (!initial_setup && (!root_folder_path || !*root_folder_path)) {
+ g_mutex_lock (&imapx_store->priv->mailboxes_lock);
+ g_hash_table_foreach_remove (imapx_store->priv->mailboxes, imapx_store_remove_unknown_mailboxes_cb, imapx_store);
+ g_mutex_unlock (&imapx_store->priv->mailboxes_lock);
+ }
+
array = camel_store_summary_array (imapx_store->summary);
for (ii = 0; ii < array->len; ii++) {
@@ -1479,7 +1559,7 @@ imapx_refresh_finfo (CamelSession *session,
CAMEL_SERVICE (store), cancellable, error))
goto exit;
- sync_folders (store, NULL, 0, cancellable, error);
+ sync_folders (store, NULL, 0, FALSE, cancellable, error);
camel_store_summary_save (store->summary);
@@ -1720,7 +1800,7 @@ imapx_store_get_folder_info_sync (CamelStore *store,
goto exit;
}
- if (!sync_folders (imapx_store, top, flags, cancellable, error))
+ if (!sync_folders (imapx_store, top, flags, initial_setup, cancellable, error))
goto exit;
camel_store_summary_save (imapx_store->summary);
@@ -2674,12 +2754,19 @@ camel_imapx_store_ref_server (CamelIMAPXStore *store,
GError **error)
{
CamelIMAPXServer *server = NULL;
+ CamelSession *session;
GError *local_error = NULL;
g_return_val_if_fail (CAMEL_IS_IMAPX_STORE (store), NULL);
- server = camel_imapx_conn_manager_get_connection (
- store->priv->con_man, folder_name, for_expensive_job, cancellable, &local_error);
+ session = camel_service_ref_session (CAMEL_SERVICE (store));
+
+ if (camel_offline_store_get_online (CAMEL_OFFLINE_STORE (store)) &&
+ camel_session_get_online (session))
+ server = camel_imapx_conn_manager_get_connection (
+ store->priv->con_man, folder_name, for_expensive_job, cancellable, &local_error);
+
+ g_clear_object (&session);
if (!server && (!local_error || local_error->domain == G_RESOLVER_ERROR)) {
if (!local_error) {
@@ -3177,14 +3264,20 @@ camel_imapx_store_handle_list_response (CamelIMAPXStore *imapx_store,
mailbox = imapx_store_rename_mailbox_unlocked (
imapx_store, old_mailbox_name, mailbox_name);
emit_mailbox_renamed = (mailbox != NULL);
+ if (mailbox && camel_imapx_mailbox_get_state (mailbox) == CAMEL_IMAPX_MAILBOX_STATE_UNKNOWN)
+ camel_imapx_mailbox_set_state (mailbox, CAMEL_IMAPX_MAILBOX_STATE_RENAMED);
}
if (mailbox == NULL) {
mailbox = imapx_store_ref_mailbox_unlocked (imapx_store, mailbox_name);
emit_mailbox_updated = (mailbox != NULL);
+ if (mailbox && camel_imapx_mailbox_get_state (mailbox) == CAMEL_IMAPX_MAILBOX_STATE_UNKNOWN)
+ camel_imapx_mailbox_set_state (mailbox, CAMEL_IMAPX_MAILBOX_STATE_UPDATED);
}
if (mailbox == NULL) {
mailbox = imapx_store_create_mailbox_unlocked (imapx_store, response);
emit_mailbox_created = (mailbox != NULL);
+ if (mailbox)
+ camel_imapx_mailbox_set_state (mailbox, CAMEL_IMAPX_MAILBOX_STATE_CREATED);
} else {
camel_imapx_mailbox_handle_list_response (mailbox, response);
}
@@ -3239,6 +3332,8 @@ camel_imapx_store_handle_lsub_response (CamelIMAPXStore *imapx_store,
mailbox = imapx_store_ref_mailbox_unlocked (imapx_store, mailbox_name);
if (mailbox != NULL) {
camel_imapx_mailbox_handle_lsub_response (mailbox, response);
+ if (camel_imapx_mailbox_get_state (mailbox) == CAMEL_IMAPX_MAILBOX_STATE_UNKNOWN)
+ camel_imapx_mailbox_set_state (mailbox, CAMEL_IMAPX_MAILBOX_STATE_UPDATED);
emit_mailbox_updated = TRUE;
}
g_mutex_unlock (&imapx_store->priv->mailboxes_lock);
diff --git a/camel/providers/imapx/camel-imapx-utils.c b/camel/providers/imapx/camel-imapx-utils.c
index f2d1f7d..bb231ba 100644
--- a/camel/providers/imapx/camel-imapx-utils.c
+++ b/camel/providers/imapx/camel-imapx-utils.c
@@ -781,24 +781,23 @@ imapx_parse_param_list (CamelIMAPXInputStream *stream,
stream, &token, &len, cancellable, NULL);
if (tok == '(') {
while (1) {
- tok = camel_imapx_input_stream_token (
- stream, &token, &len, cancellable, NULL);
+ tok = camel_imapx_input_stream_token (stream, &token, &len, cancellable, error);
- if (tok == ')')
+ if (tok == ')' || tok == IMAPX_TOK_ERROR)
break;
camel_imapx_input_stream_ungettoken (
stream, tok, token, len);
- camel_imapx_input_stream_astring (
- stream, &token, cancellable, NULL);
+ if (!camel_imapx_input_stream_astring (stream, &token, cancellable, error))
+ break;
param_len = strlen ((gchar *) token) + 1;
param = alloca (param_len);
g_strlcpy (param, (gchar *) token, param_len);
- camel_imapx_input_stream_astring (
- stream, &token, cancellable, NULL);
+ if (!camel_imapx_input_stream_astring (stream, &token, cancellable, error))
+ break;
camel_header_set_param (plist, param, (gchar *) token);
}
@@ -1014,14 +1013,17 @@ imapx_parse_address_list (CamelIMAPXInputStream *stream,
tok = camel_imapx_input_stream_token (
stream, &token, &len, cancellable, &local_error);
+ if (local_error) {
+ g_propagate_error (error, local_error);
+ return NULL;
+ }
if (tok == '(') {
struct _camel_header_address *addr, *group = NULL;
while (1) {
/* address ::= "(" addr_name SPACE addr_adl SPACE addr_mailbox
* SPACE addr_host ")" */
- tok = camel_imapx_input_stream_token (
- stream, &token, &len, cancellable, &local_error);
+ tok = camel_imapx_input_stream_token (stream, &token, &len, cancellable, &local_error);
if (tok == ')')
break;
@@ -1036,12 +1038,15 @@ imapx_parse_address_list (CamelIMAPXInputStream *stream,
addr = camel_header_address_new ();
addr->type = CAMEL_HEADER_ADDRESS_NAME;
- camel_imapx_input_stream_nstring (
- stream, &token, cancellable, &local_error);
+ camel_imapx_input_stream_nstring (stream, &token, cancellable, &local_error);
+ if (local_error)
+ goto error;
+
addr->name = g_strdup ((gchar *) token);
/* we ignore the route, nobody uses it in the real world */
- camel_imapx_input_stream_nstring (
- stream, &token, cancellable, &local_error);
+ camel_imapx_input_stream_nstring (stream, &token, cancellable, &local_error);
+ if (local_error)
+ goto error;
/* [RFC-822] group syntax is indicated by a special
* form of address structure in which the host name
@@ -1051,14 +1056,15 @@ imapx_parse_address_list (CamelIMAPXInputStream *stream,
* non-NIL, this is a start of group marker, and the
* mailbox name field holds the group name phrase. */
- camel_imapx_input_stream_nstring (
- stream, (guchar **) &mbox,
- cancellable, &local_error);
+ camel_imapx_input_stream_nstring (stream, (guchar **) &mbox, cancellable, &local_error);
+ if (local_error)
+ goto error;
mbox = g_strdup (mbox);
- camel_imapx_input_stream_nstring (
- stream, &host, cancellable, &local_error);
+ camel_imapx_input_stream_nstring (stream, &host, cancellable, &local_error);
+ if (local_error)
+ goto error;
if (host == NULL) {
if (mbox == NULL) {
@@ -1081,16 +1087,21 @@ imapx_parse_address_list (CamelIMAPXInputStream *stream,
camel_header_address_list_append (&list, addr);
}
do {
- tok = camel_imapx_input_stream_token (
- stream, &token, &len,
- cancellable, &local_error);
- } while (tok != ')');
+ tok = camel_imapx_input_stream_token (stream, &token, &len, cancellable, &local_error);
+ if (local_error)
+ goto error;
+ } while (tok != ')' && tok != IMAPX_TOK_ERROR);
}
}
+ error:
/* CHEN TODO handle exception at required places */
- if (local_error != NULL)
+ if (local_error != NULL) {
g_propagate_error (error, local_error);
+ if (list)
+ camel_header_address_list_clear (&list);
+ return NULL;
+ }
return list;
}
@@ -1105,7 +1116,7 @@ imapx_parse_envelope (CamelIMAPXInputStream *stream,
guchar *token;
struct _camel_header_address *addr, *addr_from;
gchar *addrstr;
- struct _CamelMessageInfoBase *minfo;
+ struct _CamelMessageInfoBase *minfo = NULL;
GError *local_error = NULL;
/* envelope ::= "(" env_date SPACE env_subject SPACE env_from
@@ -1118,6 +1129,9 @@ imapx_parse_envelope (CamelIMAPXInputStream *stream,
tok = camel_imapx_input_stream_token (
stream, &token, &len, cancellable, &local_error);
+ if (local_error)
+ goto error;
+
if (tok != '(') {
g_clear_error (&local_error);
camel_message_info_unref (minfo);
@@ -1126,22 +1140,31 @@ imapx_parse_envelope (CamelIMAPXInputStream *stream,
}
/* env_date ::= nstring */
- camel_imapx_input_stream_nstring (
- stream, &token, cancellable, &local_error);
+ camel_imapx_input_stream_nstring (stream, &token, cancellable, &local_error);
+ if (local_error)
+ goto error;
+
minfo->date_sent = camel_header_decode_date ((gchar *) token, NULL);
/* env_subject ::= nstring */
- camel_imapx_input_stream_nstring (
- stream, &token, cancellable, &local_error);
+ camel_imapx_input_stream_nstring (stream, &token, cancellable, &local_error);
+ if (local_error)
+ goto error;
+
minfo->subject = camel_pstring_strdup ((gchar *) token);
/* we merge from/sender into from, append should probably merge more smartly? */
/* env_from ::= "(" 1*address ")" / nil */
addr_from = imapx_parse_address_list (stream, cancellable, &local_error);
+ if (local_error)
+ goto error;
/* env_sender ::= "(" 1*address ")" / nil */
addr = imapx_parse_address_list (stream, cancellable, &local_error);
+ if (local_error)
+ goto error;
+
if (addr_from) {
camel_header_address_list_clear (&addr);
} else {
@@ -1162,6 +1185,9 @@ imapx_parse_envelope (CamelIMAPXInputStream *stream,
addr = imapx_parse_address_list (stream, cancellable, &local_error);
camel_header_address_list_clear (&addr);
+ if (local_error)
+ goto error;
+
/* env_to ::= "(" 1*address ")" / nil */
addr = imapx_parse_address_list (stream, cancellable, &local_error);
if (addr) {
@@ -1171,6 +1197,9 @@ imapx_parse_envelope (CamelIMAPXInputStream *stream,
camel_header_address_list_clear (&addr);
}
+ if (local_error)
+ goto error;
+
/* env_cc ::= "(" 1*address ")" / nil */
addr = imapx_parse_address_list (stream, cancellable, &local_error);
if (addr) {
@@ -1180,26 +1209,35 @@ imapx_parse_envelope (CamelIMAPXInputStream *stream,
camel_header_address_list_clear (&addr);
}
+ if (local_error)
+ goto error;
+
/* we dont keep bcc either */
/* env_bcc ::= "(" 1*address ")" / nil */
addr = imapx_parse_address_list (stream, cancellable, &local_error);
camel_header_address_list_clear (&addr);
+ if (local_error)
+ goto error;
+
/* FIXME: need to put in-reply-to into references hash list */
/* env_in_reply_to ::= nstring */
- camel_imapx_input_stream_nstring (
- stream, &token, cancellable, &local_error);
+ camel_imapx_input_stream_nstring (stream, &token, cancellable, &local_error);
+ if (local_error)
+ goto error;
/* FIXME: need to put message-id into message-id hash */
/* env_message_id ::= nstring */
- camel_imapx_input_stream_nstring (
- stream, &token, cancellable, &local_error);
+ camel_imapx_input_stream_nstring (stream, &token, cancellable, &local_error);
+ if (local_error)
+ goto error;
- tok = camel_imapx_input_stream_token (
- stream, &token, &len, cancellable, &local_error);
+ tok = camel_imapx_input_stream_token (stream, &token, &len, cancellable, &local_error);
+ if (local_error)
+ goto error;
if (tok != ')') {
g_clear_error (&local_error);
@@ -1208,9 +1246,14 @@ imapx_parse_envelope (CamelIMAPXInputStream *stream,
return NULL;
}
+ error:
/* CHEN TODO handle exceptions better */
- if (local_error != NULL)
+ if (local_error != NULL) {
g_propagate_error (error, local_error);
+ if (minfo)
+ camel_message_info_unref (minfo);
+ return NULL;
+ }
return (CamelMessageInfo *) minfo;
}
@@ -1239,9 +1282,16 @@ imapx_parse_body (CamelIMAPXInputStream *stream,
return NULL;
}
+ if (local_error)
+ goto error;
+
/* 1*body (optional for multiparts) */
tok = camel_imapx_input_stream_token (
stream, &token, &len, cancellable, &local_error);
+
+ if (local_error)
+ goto error;
+
camel_imapx_input_stream_ungettoken (stream, tok, token, len);
if (tok == '(') {
@@ -1251,14 +1301,20 @@ imapx_parse_body (CamelIMAPXInputStream *stream,
cinfo = g_malloc0 (sizeof (*cinfo));
last = (struct _CamelMessageContentInfo *) &cinfo->childs;
do {
- subinfo = imapx_parse_body (
- stream, cancellable, &local_error);
+ subinfo = imapx_parse_body (stream, cancellable, &local_error);
+ if (local_error)
+ goto error;
+
last->next = subinfo;
last = subinfo;
subinfo->parent = cinfo;
tok = camel_imapx_input_stream_token (
stream, &token, &len,
cancellable, &local_error);
+
+ if (local_error)
+ goto error;
+
camel_imapx_input_stream_ungettoken (
stream, tok, token, len);
} while (tok == '(');
@@ -1266,6 +1322,9 @@ imapx_parse_body (CamelIMAPXInputStream *stream,
camel_imapx_input_stream_astring (
stream, &token, cancellable, &local_error);
+ if (local_error)
+ goto error;
+
cinfo->type = camel_content_type_new (
"multipart", (gchar *) token);
@@ -1277,6 +1336,10 @@ imapx_parse_body (CamelIMAPXInputStream *stream,
tok = camel_imapx_input_stream_token (
stream, &token, &len, cancellable, &local_error);
+
+ if (local_error)
+ goto error;
+
camel_imapx_input_stream_ungettoken (stream, tok, token, len);
if (tok == '(') {
@@ -1284,16 +1347,26 @@ imapx_parse_body (CamelIMAPXInputStream *stream,
stream, &cinfo->type->params,
cancellable, &local_error);
+ if (local_error)
+ goto error;
+
/* body_fld_dsp ::= "(" string SPACE body_fld_param ")" / nil */
tok = camel_imapx_input_stream_token (
stream, &token, &len, cancellable, &local_error);
+
+ if (local_error)
+ goto error;
+
camel_imapx_input_stream_ungettoken (
stream, tok, token, len);
if (tok == '(' || tok == IMAPX_TOK_TOKEN) {
dinfo = imapx_parse_ext_optional (
stream, cancellable, &local_error);
+
+ if (local_error)
+ goto error;
/* other extension fields?, soaked up below */
} else {
camel_imapx_input_stream_ungettoken (
@@ -1312,9 +1385,16 @@ imapx_parse_body (CamelIMAPXInputStream *stream,
cinfo = imapx_parse_body_fields (
stream, cancellable, &local_error);
+ if (local_error)
+ goto error;
+
/* do we have an envelope following */
tok = camel_imapx_input_stream_token (
stream, &token, &len, cancellable, &local_error);
+
+ if (local_error)
+ goto error;
+
camel_imapx_input_stream_ungettoken (stream, tok, token, len);
if (tok == '(') {
struct _CamelMessageInfo * minfo = NULL;
@@ -1322,6 +1402,10 @@ imapx_parse_body (CamelIMAPXInputStream *stream,
/* what do we do with the envelope?? */
minfo = imapx_parse_envelope (
stream, cancellable, &local_error);
+
+ if (local_error)
+ goto error;
+
/* what do we do with the message content info?? */
//((CamelMessageInfoBase *) minfo)->content = imapx_parse_body (stream);
camel_message_info_unref (minfo);
@@ -1331,9 +1415,16 @@ imapx_parse_body (CamelIMAPXInputStream *stream,
/* do we have fld_lines following? */
tok = camel_imapx_input_stream_token (
stream, &token, &len, cancellable, &local_error);
+
+ if (local_error)
+ goto error;
+
if (tok == IMAPX_TOK_INT) {
tok = camel_imapx_input_stream_token (
stream, &token, &len, cancellable, &local_error);
+
+ if (local_error)
+ goto error;
}
camel_imapx_input_stream_ungettoken (stream, tok, token, len);
@@ -1347,15 +1438,25 @@ imapx_parse_body (CamelIMAPXInputStream *stream,
camel_imapx_input_stream_nstring (
stream, &token, cancellable, &local_error);
+ if (local_error)
+ goto error;
+
/* body_fld_dsp ::= "(" string SPACE body_fld_param ")" / nil */
tok = camel_imapx_input_stream_token (
stream, &token, &len, cancellable, &local_error);
+
+ if (local_error)
+ goto error;
+
camel_imapx_input_stream_ungettoken (
stream, tok, token, len);
if (tok == '(' || tok == IMAPX_TOK_TOKEN) {
dinfo = imapx_parse_ext_optional (
stream, cancellable, &local_error);
+
+ if (local_error)
+ goto error;
/* then other extension fields, soaked up below */
}
}
@@ -1366,8 +1467,12 @@ imapx_parse_body (CamelIMAPXInputStream *stream,
do {
tok = camel_imapx_input_stream_token (
stream, &token, &len, cancellable, &local_error);
- } while (tok != ')');
+ if (local_error)
+ goto error;
+ } while (tok != ')' && tok != IMAPX_TOK_ERROR);
+
+ error:
/* CHEN TODO handle exceptions better */
if (local_error != NULL) {
g_propagate_error (error, local_error);
@@ -1483,7 +1588,7 @@ imapx_parse_modseq (CamelIMAPXInputStream *stream,
tok = camel_imapx_input_stream_token (
stream, &token, &len, cancellable, error);
- if (tok == CAMEL_IMAPX_ERROR)
+ if (tok == IMAPX_TOK_ERROR)
return 0;
if (tok != '(') {
@@ -1502,7 +1607,7 @@ imapx_parse_modseq (CamelIMAPXInputStream *stream,
tok = camel_imapx_input_stream_token (
stream, &token, &len, cancellable, error);
- if (tok == CAMEL_IMAPX_ERROR)
+ if (tok == IMAPX_TOK_ERROR)
return 0;
if (tok != ')') {
@@ -2135,7 +2240,7 @@ imapx_parse_status_newname (CamelIMAPXInputStream *stream,
static gboolean
imapx_parse_status_permanentflags (CamelIMAPXInputStream *stream,
- struct _status_info *sinfo,
+ CamelIMAPXMailbox *mailbox,
GCancellable *cancellable,
GError **error)
{
@@ -2145,7 +2250,7 @@ imapx_parse_status_permanentflags (CamelIMAPXInputStream *stream,
if (!imapx_parse_flags (stream, &flags, NULL, cancellable, error))
return FALSE;
- sinfo->u.permanentflags = flags;
+ camel_imapx_mailbox_set_permanentflags (mailbox, flags);
return TRUE;
}
@@ -2313,7 +2418,7 @@ imapx_parse_status (CamelIMAPXInputStream *stream,
case IMAPX_PERMANENTFLAGS:
success = imapx_parse_status_permanentflags (
- stream, sinfo, cancellable, error);
+ stream, mailbox, cancellable, error);
break;
case IMAPX_UIDNEXT:
diff --git a/camel/providers/imapx/camel-imapx-utils.h b/camel/providers/imapx/camel-imapx-utils.h
index 7b6bb48..a6d85b7 100644
--- a/camel/providers/imapx/camel-imapx-utils.h
+++ b/camel/providers/imapx/camel-imapx-utils.h
@@ -281,7 +281,6 @@ struct _status_info {
gchar *oldname;
gchar *newname;
} newname;
- guint32 permanentflags;
struct {
guint64 uidvalidity;
guint32 uid;
diff --git a/camel/providers/pop3/camel-pop3-store.c b/camel/providers/pop3/camel-pop3-store.c
index a341324..b618cc3 100644
--- a/camel/providers/pop3/camel-pop3-store.c
+++ b/camel/providers/pop3/camel-pop3-store.c
@@ -684,6 +684,15 @@ pop3_store_authenticate_sync (CamelService *service,
pcu = camel_pop3_engine_command_new (
pop3_engine, 0, NULL, NULL, cancellable, error,
"USER %s\r\n", user);
+ if (error && *error) {
+ g_prefix_error (
+ error,
+ _("Unable to connect to POP server %s.\n"
+ "Error sending password: "), host);
+ result = CAMEL_AUTHENTICATION_ERROR;
+ goto exit;
+ }
+
pcp = camel_pop3_engine_command_new (
pop3_engine, 0, NULL, NULL, cancellable, error,
"PASS %s\r\n", password);
diff --git a/configure.ac b/configure.ac
index f0bc991..81edd58 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,10 +2,10 @@
dnl Evolution-Data-Server version
m4_define([eds_major_version], [3])
m4_define([eds_minor_version], [12])
-m4_define([eds_micro_version], [7])
+m4_define([eds_micro_version], [9])
m4_define([eds_version],
- [eds_major_version.eds_minor_version.eds_micro_version.1])
+ [eds_major_version.eds_minor_version.eds_micro_version])
dnl Base Version: This is for API/version tracking for things like
dnl Bonobo server files. This should always be the major/minor of
diff --git a/evolution-data-server.doap b/evolution-data-server.doap
index a04bf63..5df9b65 100644
--- a/evolution-data-server.doap
+++ b/evolution-data-server.doap
@@ -6,50 +6,16 @@
<name xml:lang="en">evolution-data-server</name>
<shortdesc xml:lang="en">Centralized access to appointments and contacts</shortdesc>
+ <description>Centralized access to appointments and contacts</description>
<homepage rdf:resource="https://wiki.gnome.org/Apps/Evolution" />
<mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/evolution-list" />
<category rdf:resource="http://api.gnome.org/doap-extensions#desktop" />
- <!-- Project Leads -->
<maintainer>
<foaf:Person>
- <foaf:name>Chenthill Palanisamy</foaf:name>
- <foaf:mbox rdf:resource="mailto:pchenthill@novell.com" />
- <gnome:userid>pchen</gnome:userid>
- </foaf:Person>
- </maintainer>
-
- <maintainer>
- <foaf:Person>
- <foaf:name>Matthew Barnes</foaf:name>
- <foaf:mbox rdf:resource="mailto:mbarnes@redhat.com" />
- <gnome:userid>mbarnes</gnome:userid>
- </foaf:Person>
- </maintainer>
-
- <!-- Alphabetically -->
-
- <maintainer>
- <foaf:Person>
- <foaf:name>Christian Kellner</foaf:name>
- <foaf:mbox rdf:resource="mailto:gicmo@gnome.org" />
- <gnome:userid>gicmo</gnome:userid>
- </foaf:Person>
- </maintainer>
-
- <maintainer>
- <foaf:Person>
- <foaf:name>Ross Burton</foaf:name>
- <foaf:mbox rdf:resource="mailto:ross@burtonini.com" />
- <gnome:userid>rburton</gnome:userid>
- </foaf:Person>
- </maintainer>
-
- <maintainer>
- <foaf:Person>
- <foaf:name>Srinivasa Ragavan</foaf:name>
- <foaf:mbox rdf:resource="mailto:sragavan@novell.com" />
- <gnome:userid>sragavan</gnome:userid>
+ <foaf:name>Milan Crha</foaf:name>
+ <foaf:mbox rdf:resource="mailto:mcrha@redhat.com" />
+ <gnome:userid>mcrha</gnome:userid>
</foaf:Person>
</maintainer>
diff --git a/libebackend/e-authentication-session.c b/libebackend/e-authentication-session.c
index f664a30..7c1a75a 100644
--- a/libebackend/e-authentication-session.c
+++ b/libebackend/e-authentication-session.c
@@ -134,7 +134,7 @@ authentication_session_msg (EAuthenticationSession *session,
g_string_append_vprintf (buffer, format, args);
va_end (args);
- g_print ("%s\n", buffer->str);
+ e_source_registry_debug_print ("%s\n", buffer->str);
g_string_free (buffer, TRUE);
}
@@ -389,7 +389,7 @@ authentication_session_execute_sync (EAuthenticationSession *session,
ESourceRegistryServer *server;
ESource *source = NULL;
GcrPrompt *prompt;
- GString *password_string;
+ GString *password_string = NULL;
const gchar *label;
const gchar *source_uid;
const gchar *prompt_password;
@@ -397,6 +397,7 @@ authentication_session_execute_sync (EAuthenticationSession *session,
gboolean success;
gboolean allow_auth_prompt = TRUE;
gboolean remember_password = TRUE;
+ gboolean first_prompt = TRUE;
GError *local_error = NULL;
/* XXX I moved the execute() operation into a class method thinking
@@ -513,6 +514,8 @@ authentication_session_execute_sync (EAuthenticationSession *session,
/* Configure a system prompt. */
+ try_again:
+
prompt = gcr_system_prompt_open (
SYSTEM_PROMPT_TIMEOUT, cancellable, error);
@@ -540,7 +543,10 @@ authentication_session_execute_sync (EAuthenticationSession *session,
gcr_prompt_set_choice_label (prompt, label);
gcr_prompt_set_choice_chosen (prompt, remember_password);
-try_again:
+ if (!first_prompt)
+ gcr_prompt_set_warning (prompt, _("Password was incorrect"));
+ else
+ first_prompt = FALSE;
/* Prompt the user for a password. */
@@ -560,6 +566,29 @@ try_again:
goto close_prompt;
}
+ if (password_string)
+ g_string_free (password_string, TRUE);
+ password_string = g_string_new (prompt_password);
+ prompt_password = NULL;
+
+ remember_password = gcr_prompt_get_choice_chosen (prompt);
+
+ /* Failure here does not affect the outcome of this
+ * operation, but leave a breadcrumb as evidence that
+ * something went wrong. */
+
+ gcr_system_prompt_close (
+ GCR_SYSTEM_PROMPT (prompt),
+ cancellable, &local_error);
+
+ if (local_error != NULL) {
+ g_warning ("%s: %s", G_STRFUNC, local_error->message);
+ g_clear_error (&local_error);
+ }
+
+ g_object_unref (prompt);
+ prompt = NULL;
+
if (source != NULL) {
ESourceExtension *extension;
const gchar *extension_name;
@@ -569,59 +598,33 @@ try_again:
e_source_authentication_set_remember_password (
E_SOURCE_AUTHENTICATION (extension),
- gcr_prompt_get_choice_chosen (prompt));
+ remember_password);
}
/* Attempt authentication with the provided password. */
- password_string = g_string_new (prompt_password);
-
auth_result = e_source_authenticator_try_password_sync (
authenticator, password_string, cancellable, error);
- g_string_free (password_string, TRUE);
- password_string = NULL;
-
if (auth_result == E_SOURCE_AUTHENTICATION_ERROR) {
session_result = E_AUTHENTICATION_SESSION_ERROR;
- goto close_prompt;
+ goto exit;
}
if (auth_result == E_SOURCE_AUTHENTICATION_ACCEPTED) {
- gboolean permanently;
gchar *password_copy;
- permanently = gcr_prompt_get_choice_chosen (prompt);
session_result = E_AUTHENTICATION_SESSION_SUCCESS;
- /* Close our prompt before storing the password in
- * the keyring. If the keyring is locked, it will
- * need to prompt the user for a keyring password,
- * but it can't do that if our password prompt is
- * still open since both prompts are system-modal.
- * Not sure what would happen next; probably the
- * store operation would either fail or deadlock. */
-
/* XXX Not sure if it's safe to use the prompt's
* password string after closing the prompt,
* so make a copy here just to be safe. */
- password_copy = gcr_secure_memory_strdup (prompt_password);
+ password_copy = gcr_secure_memory_strdup (password_string->str);
/* Failure here does not affect the outcome of this
* operation, but leave a breadcrumb as evidence that
* something went wrong. */
- gcr_system_prompt_close (
- GCR_SYSTEM_PROMPT (prompt),
- cancellable, &local_error);
-
- if (local_error != NULL) {
- g_warning ("%s: %s", G_STRFUNC, local_error->message);
- g_clear_error (&local_error);
- }
-
- g_object_unref (prompt);
-
/* Create a phony "scratch" source if necessary. */
if (source == NULL) {
source = e_source_new_with_uid (
@@ -630,7 +633,7 @@ try_again:
if (source != NULL) {
e_source_store_password_sync (
- source, password_copy, permanently,
+ source, password_copy, remember_password,
cancellable, &local_error);
}
@@ -646,8 +649,6 @@ try_again:
g_warn_if_fail (auth_result == E_SOURCE_AUTHENTICATION_REJECTED);
- gcr_prompt_set_warning (prompt, _("Password was incorrect"));
-
goto try_again;
close_prompt:
@@ -693,6 +694,11 @@ exit:
g_clear_object (&source);
+ if (password_string) {
+ g_string_free (password_string, TRUE);
+ password_string = NULL;
+ }
+
return session_result;
}
diff --git a/libebackend/e-backend.c b/libebackend/e-backend.c
index d3189d5..46045c4 100644
--- a/libebackend/e-backend.c
+++ b/libebackend/e-backend.c
@@ -126,11 +126,16 @@ backend_network_monitor_can_reach_cb (GObject *source_object,
}
static gboolean
-backend_update_online_state_idle_cb (gpointer user_data)
+backend_update_online_state_timeout_cb (gpointer user_data)
{
EBackend *backend;
GSocketConnectable *connectable;
GCancellable *cancellable;
+ GSource *current_source;
+
+ current_source = g_main_current_source ();
+ if (current_source && g_source_is_destroyed (current_source))
+ return FALSE;
backend = E_BACKEND (user_data);
connectable = e_backend_ref_connectable (backend);
@@ -188,23 +193,29 @@ backend_update_online_state (EBackend *backend)
{
g_mutex_lock (&backend->priv->update_online_state_lock);
+ if (backend->priv->update_online_state) {
+ g_source_destroy (backend->priv->update_online_state);
+ g_source_unref (backend->priv->update_online_state);
+ backend->priv->update_online_state = NULL;
+ }
+
if (backend->priv->update_online_state == NULL) {
GMainContext *main_context;
- GSource *idle_source;
+ GSource *timeout_source;
main_context = e_backend_ref_main_context (backend);
- idle_source = g_idle_source_new ();
- g_source_set_priority (idle_source, G_PRIORITY_LOW);
+ timeout_source = g_timeout_source_new_seconds (5);
+ g_source_set_priority (timeout_source, G_PRIORITY_LOW);
g_source_set_callback (
- idle_source,
- backend_update_online_state_idle_cb,
+ timeout_source,
+ backend_update_online_state_timeout_cb,
g_object_ref (backend),
(GDestroyNotify) g_object_unref);
- g_source_attach (idle_source, main_context);
+ g_source_attach (timeout_source, main_context);
backend->priv->update_online_state =
- g_source_ref (idle_source);
- g_source_unref (idle_source);
+ g_source_ref (timeout_source);
+ g_source_unref (timeout_source);
g_main_context_unref (main_context);
}
diff --git a/libebackend/e-collection-backend.c b/libebackend/e-collection-backend.c
index d41998d..4d30dd7 100644
--- a/libebackend/e-collection-backend.c
+++ b/libebackend/e-collection-backend.c
@@ -71,6 +71,7 @@ struct _ECollectionBackendPrivate {
gulong source_added_handler_id;
gulong source_removed_handler_id;
+ gulong notify_enabled_handler_id;
};
enum {
@@ -478,6 +479,28 @@ collection_backend_source_removed_cb (ESourceRegistryServer *server,
g_object_unref (parent_source);
}
+static void
+collection_backend_source_enabled_cb (ESource *source,
+ GParamSpec *spec,
+ EBackend *backend)
+{
+ ESource *collection_source;
+ GObject *collection;
+
+ g_return_if_fail (E_IS_COLLECTION_BACKEND (backend));
+
+ collection_source = e_backend_get_source (E_BACKEND (backend));
+ collection = e_source_get_extension (collection_source, E_SOURCE_EXTENSION_COLLECTION);
+
+ /* Some child sources depend on both sub-part enabled and the main
+ ESource::enabled state, thus if the main's ESource::enabled
+ changes, then also notify the change of the sub-parts, thus
+ child's enabled property is properly recalculated. */
+ g_object_notify (collection, "calendar-enabled");
+ g_object_notify (collection, "contacts-enabled");
+ g_object_notify (collection, "mail-enabled");
+}
+
static gboolean
collection_backend_populate_idle_cb (gpointer user_data)
{
@@ -630,6 +653,15 @@ collection_backend_dispose (GObject *object)
g_object_unref (server);
}
+ if (priv->notify_enabled_handler_id) {
+ ESource *source = e_backend_get_source (E_BACKEND (object));
+
+ if (source)
+ g_signal_handler_disconnect (source, priv->notify_enabled_handler_id);
+
+ priv->notify_enabled_handler_id = 0;
+ }
+
g_mutex_lock (&priv->children_lock);
g_hash_table_remove_all (priv->children);
g_mutex_unlock (&priv->children_lock);
@@ -742,6 +774,9 @@ collection_backend_constructed (GObject *object)
g_object_unref (server);
+ backend->priv->notify_enabled_handler_id = g_signal_connect (source, "notify::enabled",
+ G_CALLBACK (collection_backend_source_enabled_cb), backend);
+
/* Populate the newly-added collection from an idle callback
* so persistent child sources have a chance to be added first. */
@@ -1145,7 +1180,7 @@ e_collection_backend_new_child (ECollectionBackend *backend,
collection_source = e_backend_get_source (E_BACKEND (backend));
- g_print (
+ e_source_registry_debug_print (
"%s: Pairing %s with resource %s\n",
e_source_get_display_name (collection_source),
e_source_get_uid (child_source), resource_id);
diff --git a/libebackend/e-dbus-server.c b/libebackend/e-dbus-server.c
index e2f58db..83bce3f 100644
--- a/libebackend/e-dbus-server.c
+++ b/libebackend/e-dbus-server.c
@@ -111,7 +111,7 @@ dbus_server_hang_up_cb (gpointer user_data)
{
EDBusServer *server = E_DBUS_SERVER (user_data);
- g_print ("Received hang up signal.\n");
+ e_source_registry_debug_print ("Received hang up signal.\n");
e_dbus_server_quit (server, E_DBUS_SERVER_EXIT_RELOAD);
return FALSE;
@@ -122,7 +122,7 @@ dbus_server_terminate_cb (gpointer user_data)
{
EDBusServer *server = E_DBUS_SERVER (user_data);
- g_print ("Received terminate signal.\n");
+ e_source_registry_debug_print ("Received terminate signal.\n");
e_dbus_server_quit (server, E_DBUS_SERVER_EXIT_NORMAL);
return FALSE;
@@ -187,7 +187,7 @@ dbus_server_bus_name_acquired (EDBusServer *server,
class = E_DBUS_SERVER_GET_CLASS (server);
g_return_if_fail (class->bus_name != NULL);
- g_print ("Bus name '%s' acquired.\n", class->bus_name);
+ e_source_registry_debug_print ("Bus name '%s' acquired.\n", class->bus_name);
}
static void
@@ -199,7 +199,7 @@ dbus_server_bus_name_lost (EDBusServer *server,
class = E_DBUS_SERVER_GET_CLASS (server);
g_return_if_fail (class->bus_name != NULL);
- g_print ("Bus name '%s' lost.\n", class->bus_name);
+ e_source_registry_debug_print ("Bus name '%s' lost.\n", class->bus_name);
e_dbus_server_quit (server, E_DBUS_SERVER_EXIT_NORMAL);
}
diff --git a/libebackend/e-server-side-source.c b/libebackend/e-server-side-source.c
index 90afc71..82b82e7 100644
--- a/libebackend/e-server-side-source.c
+++ b/libebackend/e-server-side-source.c
@@ -149,7 +149,10 @@ server_side_source_print_diff (ESource *source,
guint new_length = 0;
guint ii;
- g_print ("Saving %s\n", e_source_get_uid (source));
+ if (!e_source_registry_debug_enabled ())
+ return;
+
+ e_source_registry_debug_print ("Saving %s\n", e_source_get_uid (source));
if (old_data != NULL) {
old_strv = g_strsplit (old_data, "\n", 0);
@@ -163,18 +166,18 @@ server_side_source_print_diff (ESource *source,
for (ii = 0; ii < MIN (old_length, new_length); ii++) {
if (g_strcmp0 (old_strv[ii], new_strv[ii]) != 0) {
- g_print (" - : %s\n", old_strv[ii]);
- g_print (" + : %s\n", new_strv[ii]);
+ e_source_registry_debug_print (" - : %s\n", old_strv[ii]);
+ e_source_registry_debug_print (" + : %s\n", new_strv[ii]);
} else {
- g_print (" : %s\n", old_strv[ii]);
+ e_source_registry_debug_print (" : %s\n", old_strv[ii]);
}
}
for (; ii < old_length; ii++)
- g_print (" - : %s\n", old_strv[ii]);
+ e_source_registry_debug_print (" - : %s\n", old_strv[ii]);
for (; ii < new_length; ii++)
- g_print (" + : %s\n", new_strv[ii]);
+ e_source_registry_debug_print (" + : %s\n", new_strv[ii]);
g_strfreev (old_strv);
g_strfreev (new_strv);
diff --git a/libebackend/e-source-registry-server.c b/libebackend/e-source-registry-server.c
index 7525b8b..362c23f 100644
--- a/libebackend/e-source-registry-server.c
+++ b/libebackend/e-source-registry-server.c
@@ -1228,7 +1228,7 @@ source_registry_server_source_removed (ESourceRegistryServer *server,
object_path = g_dbus_object_get_object_path (dbus_object);
object_name = strrchr (object_path, '/') + 1;
- g_print ("Removing %s ('%s')\n", uid, object_name);
+ e_source_registry_debug_print ("Removing %s ('%s')\n", uid, object_name);
g_dbus_object_manager_server_unexport (
server->priv->object_manager, object_path);
@@ -2497,4 +2497,3 @@ e_source_registry_server_authenticate_finish (ESourceRegistryServer *server,
/* Assume success unless a GError is set. */
return !g_simple_async_result_propagate_error (simple, error);
}
-
diff --git a/libebackend/e-sqlite3-vfs.c b/libebackend/e-sqlite3-vfs.c
index 9b09534..cf49682 100644
--- a/libebackend/e-sqlite3-vfs.c
+++ b/libebackend/e-sqlite3-vfs.c
@@ -152,6 +152,19 @@ e_sqlite3_file_ ## _nm _params \
g_return_val_if_fail (cFile->old_vfs_file->pMethods != NULL, SQLITE_ERROR); \
return cFile->old_vfs_file->pMethods->_nm _call; \
}
+#define def_subclassed_void(_nm, _params, _call) \
+static void \
+e_sqlite3_file_ ## _nm _params \
+{ \
+ ESqlite3File *cFile; \
+ \
+ g_return_if_fail (old_vfs != NULL); \
+ g_return_if_fail (pFile != NULL); \
+ \
+ cFile = (ESqlite3File *) pFile; \
+ g_return_if_fail (cFile->old_vfs_file->pMethods != NULL); \
+ cFile->old_vfs_file->pMethods->_nm _call; \
+}
def_subclassed (xRead, (sqlite3_file *pFile, gpointer pBuf, gint iAmt, sqlite3_int64 iOfst), (cFile->old_vfs_file, pBuf, iAmt, iOfst))
def_subclassed (xWrite, (sqlite3_file *pFile, gconstpointer pBuf, gint iAmt, sqlite3_int64 iOfst), (cFile->old_vfs_file, pBuf, iAmt, iOfst))
@@ -162,6 +175,12 @@ def_subclassed (xUnlock, (sqlite3_file *pFile, gint lockType), (cFile->old_vfs_f
def_subclassed (xFileControl, (sqlite3_file *pFile, gint op, gpointer pArg), (cFile->old_vfs_file, op, pArg))
def_subclassed (xSectorSize, (sqlite3_file *pFile), (cFile->old_vfs_file))
def_subclassed (xDeviceCharacteristics, (sqlite3_file *pFile), (cFile->old_vfs_file))
+def_subclassed (xShmMap, (sqlite3_file *pFile, gint iPg, gint pgsz, gint n, void volatile **arr), (cFile->old_vfs_file, iPg, pgsz, n, arr))
+def_subclassed (xShmLock, (sqlite3_file *pFile, gint offset, gint n, gint flags), (cFile->old_vfs_file, offset, n, flags))
+def_subclassed_void (xShmBarrier, (sqlite3_file *pFile), (cFile->old_vfs_file))
+def_subclassed (xShmUnmap, (sqlite3_file *pFile, gint deleteFlag), (cFile->old_vfs_file, deleteFlag))
+def_subclassed (xFetch, (sqlite3_file *pFile, sqlite3_int64 iOfst, gint iAmt, void **pp), (cFile->old_vfs_file, iOfst, iAmt, pp))
+def_subclassed (xUnfetch, (sqlite3_file *pFile, sqlite3_int64 iOfst, void *p), (cFile->old_vfs_file, iOfst, p))
#undef def_subclassed
@@ -306,6 +325,24 @@ e_sqlite3_vfs_xOpen (sqlite3_vfs *pVfs,
use_subclassed (xFileControl);
use_subclassed (xSectorSize);
use_subclassed (xDeviceCharacteristics);
+
+ if (io_methods.iVersion > 1) {
+ use_subclassed (xShmMap);
+ use_subclassed (xShmLock);
+ use_subclassed (xShmBarrier);
+ use_subclassed (xShmUnmap);
+ }
+
+ if (io_methods.iVersion > 2) {
+ use_subclassed (xFetch);
+ use_subclassed (xUnfetch);
+ }
+
+ if (io_methods.iVersion > 3) {
+ g_warning ("%s: Unchecked IOMethods version %d, downgrading to version 3", G_STRFUNC, io_methods.iVersion);
+ io_methods.iVersion = 3;
+ }
+
#undef use_subclassed
}
diff --git a/libebackend/e-user-prompter-server.c b/libebackend/e-user-prompter-server.c
index 5348327..2884b9b 100644
--- a/libebackend/e-user-prompter-server.c
+++ b/libebackend/e-user-prompter-server.c
@@ -576,7 +576,7 @@ e_user_prompter_server_register (EUserPrompterServer *server,
return FALSE;
}
- g_print (
+ e_source_registry_debug_print (
"Registering %s for dialog '%s'\n",
G_OBJECT_TYPE_NAME (extension), dialog_name);
g_hash_table_insert (
diff --git a/libedataserver/e-data-server-util.c b/libedataserver/e-data-server-util.c
index 935d835..2a956fd 100644
--- a/libedataserver/e-data-server-util.c
+++ b/libedataserver/e-data-server-util.c
@@ -2255,3 +2255,52 @@ e_timeout_add_seconds_with_name (gint priority,
return tag;
}
+/**
+ * e_source_registry_debug_enabled:
+ *
+ * Returns: Whether debugging is enabled, that is,
+ * whether e_source_registry_debug_print() will produce any output.
+ *
+ * Since: 3.12.9
+ **/
+gboolean
+e_source_registry_debug_enabled (void)
+{
+ static gint esr_debug = -1;
+
+ if (esr_debug == -1)
+ esr_debug = g_strcmp0 (g_getenv ("ESR_DEBUG"), "1") == 0 ? 1 : 0;
+
+ return esr_debug == 1;
+}
+
+/**
+ * e_source_registry_debug_print:
+ * @format: a format string to print
+ * @...: other arguments for the format
+ *
+ * Prints the text only if a debugging is enabled with an environment
+ * variable ESR_DEBUG=1.
+ *
+ * Since: 3.12.9
+ **/
+void
+e_source_registry_debug_print (const gchar *format,
+ ...)
+{
+ GString *str;
+ va_list args;
+
+ if (!e_source_registry_debug_enabled ())
+ return;
+
+ str = g_string_new ("");
+
+ va_start (args, format);
+ g_string_vprintf (str, format, args);
+ va_end (args);
+
+ g_print ("%s", str->str);
+
+ g_string_free (str, TRUE);
+}
diff --git a/libedataserver/e-data-server-util.h b/libedataserver/e-data-server-util.h
index ab6c4f2..d496a96 100644
--- a/libedataserver/e-data-server-util.h
+++ b/libedataserver/e-data-server-util.h
@@ -212,6 +212,10 @@ void e_data_server_util_set_dbus_call_timeout
#endif /* EDS_DISABLE_DEPRECATED */
+gboolean e_source_registry_debug_enabled (void);
+void e_source_registry_debug_print (const gchar *format,
+ ...) G_GNUC_PRINTF (1, 2);
+
G_END_DECLS
#endif /* E_DATA_SERVER_UTIL_H */
diff --git a/modules/gnome-online-accounts/e-goa-client.c b/modules/gnome-online-accounts/e-goa-client.c
index a6cf7d5..8a99fb9 100644
--- a/modules/gnome-online-accounts/e-goa-client.c
+++ b/modules/gnome-online-accounts/e-goa-client.c
@@ -15,6 +15,12 @@
*
*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <libedataserver/libedataserver.h>
+
#include "e-goa-client.h"
#define E_GOA_CLIENT_GET_PRIVATE(obj) \
@@ -76,7 +82,7 @@ e_goa_client_stash_orphan (EGoaClient *client,
goa_account_id = goa_account_get_id (goa_account);
g_return_if_fail (goa_account_id != NULL);
- g_print ("GOA: Stashing orphaned account '%s'\n", goa_account_id);
+ e_source_registry_debug_print ("GOA: Stashing orphaned account '%s'\n", goa_account_id);
g_mutex_lock (&client->priv->orphans_lock);
@@ -117,7 +123,7 @@ e_goa_client_claim_one_orphan (EGoaClient *client,
g_mutex_unlock (&client->priv->orphans_lock);
if (old_goa_object != NULL)
- g_print (
+ e_source_registry_debug_print (
"GOA: Claiming orphaned account '%s'\n",
goa_account_id);
@@ -138,7 +144,7 @@ e_goa_client_claim_all_orphans (EGoaClient *client)
g_mutex_unlock (&client->priv->orphans_lock);
if (list != NULL)
- g_print ("GOA: Claiming orphaned account(s)\n");
+ e_source_registry_debug_print ("GOA: Claiming orphaned account(s)\n");
return list;
}
@@ -217,9 +223,9 @@ e_goa_client_notify_name_owner_cb (GDBusObjectManager *manager,
G_DBUS_OBJECT_MANAGER_CLIENT (manager));
if (name_owner != NULL)
- g_print ("GOA: 'org.gnome.OnlineAccounts' name appeared\n");
+ e_source_registry_debug_print ("GOA: 'org.gnome.OnlineAccounts' name appeared\n");
else
- g_print ("GOA: 'org.gnome.OnlineAccounts' name vanished\n");
+ e_source_registry_debug_print ("GOA: 'org.gnome.OnlineAccounts' name vanished\n");
if (name_owner != NULL) {
GList *list, *link;
diff --git a/modules/ubuntu-online-accounts/e-signon-session-password.c b/modules/ubuntu-online-accounts/e-signon-session-password.c
index 3475b02..1242676 100644
--- a/modules/ubuntu-online-accounts/e-signon-session-password.c
+++ b/modules/ubuntu-online-accounts/e-signon-session-password.c
@@ -95,7 +95,7 @@ signon_session_password_msg (EAuthenticationSession *session,
g_string_append_vprintf (buffer, format, args);
va_end (args);
- g_print ("%s\n", buffer->str);
+ e_source_registry_debug_print ("%s\n", buffer->str);
g_string_free (buffer, TRUE);
}
diff --git a/po/gu.po b/po/gu.po
index ee81cf9..bf7ad47 100644
diff --git a/po/nb.po b/po/nb.po
index e96f760..e69a9db 100644
diff --git a/po/pt.po b/po/pt.po
index 29e2ca0..01c02d2 100644
diff --git a/po/zh_CN.po b/po/zh_CN.po
index 61fb283..60b3c83 100644
diff --git a/services/evolution-source-registry/evolution-scan-gconf-tree-xml.c b/services/evolution-source-registry/evolution-scan-gconf-tree-xml.c
index 7664d24..27659cf 100644
--- a/services/evolution-source-registry/evolution-scan-gconf-tree-xml.c
+++ b/services/evolution-source-registry/evolution-scan-gconf-tree-xml.c
@@ -22,6 +22,8 @@
#include <glib.h>
+#include <libedataserver/libedataserver.h>
+
#define PROGRAM_SUMMARY \
"Extracts Evolution accounts from a merged GConf tree file."
@@ -51,7 +53,7 @@ main (gint argc,
}
if (argc != 2) {
- g_print (
+ e_source_registry_debug_print (
"Usage: %s /path/to/%%gconf-tree.xml\n\n",
g_get_prgname ());
exit (0);
diff --git a/services/evolution-source-registry/evolution-source-registry-migrate-basedir.c b/services/evolution-source-registry/evolution-source-registry-migrate-basedir.c
index f88767e..a26faaf 100644
--- a/services/evolution-source-registry/evolution-source-registry-migrate-basedir.c
+++ b/services/evolution-source-registry/evolution-source-registry-migrate-basedir.c
@@ -38,7 +38,7 @@ migrate_rename (const gchar *old_filename,
if (!old_filename_exists)
return TRUE;
- g_print (" mv %s %s\n", old_filename, new_filename);
+ e_source_registry_debug_print (" mv %s %s\n", old_filename, new_filename);
/* It's safe to go ahead and move directories because rename()
* will fail if the new directory already exists with content.
@@ -64,7 +64,7 @@ migrate_rmdir (const gchar *dirname)
gboolean success = TRUE;
if (g_file_test (dirname, G_FILE_TEST_IS_DIR)) {
- g_print (" rmdir %s\n", dirname);
+ e_source_registry_debug_print (" rmdir %s\n", dirname);
if (g_rmdir (dirname) < 0) {
g_printerr (" FAILED: %s", g_strerror (errno));
if (errno == ENOTEMPTY) {
@@ -82,7 +82,7 @@ migrate_rmdir (const gchar *dirname)
/* Align the filenames beneath the error message. */
while ((basename = g_dir_read_name (dir)) != NULL)
- g_print (" %s\n", basename);
+ e_source_registry_debug_print (" %s\n", basename);
g_dir_close (dir);
}
@@ -281,7 +281,7 @@ migrate_to_user_cache_dir (const gchar *old_base_dir)
old_cache_dir = g_build_filename (old_base_dir, "cache", NULL);
new_cache_dir = e_get_user_cache_dir ();
- g_print ("Migrating cached backend data\n");
+ e_source_registry_debug_print ("Migrating cached backend data\n");
/* We don't want to move the source directory directly because the
* destination directory may already exist with content. Instead
@@ -354,7 +354,7 @@ migrate_to_user_data_dir (const gchar *old_base_dir)
new_data_dir = e_get_user_data_dir ();
- g_print ("Migrating local backend data\n");
+ e_source_registry_debug_print ("Migrating local backend data\n");
/* We don't want to move the source directory directly because the
* destination directory may already exist with content. Instead
diff --git a/services/evolution-source-registry/evolution-source-registry-migrate-imap-to-imapx.c b/services/evolution-source-registry/evolution-source-registry-migrate-imap-to-imapx.c
index a2e0e3d..a0ce795 100644
--- a/services/evolution-source-registry/evolution-source-registry-migrate-imap-to-imapx.c
+++ b/services/evolution-source-registry/evolution-source-registry-migrate-imap-to-imapx.c
@@ -70,7 +70,7 @@ evolution_source_registry_migrate_imap_to_imapx (ESourceRegistryServer *server,
if (!backend_is_imap)
return FALSE;
- g_print ("Converting %s from IMAP to IMAPX\n", uid);
+ e_source_registry_debug_print ("Converting %s from IMAP to IMAPX\n", uid);
g_key_file_set_string (key_file, group_name, "BackendName", "imapx");
diff --git a/services/evolution-source-registry/evolution-source-registry-migrate-sources.c b/services/evolution-source-registry/evolution-source-registry-migrate-sources.c
index f9cf7ae..ff41e95 100644
--- a/services/evolution-source-registry/evolution-source-registry-migrate-sources.c
+++ b/services/evolution-source-registry/evolution-source-registry-migrate-sources.c
@@ -353,9 +353,9 @@ migrate_parse_commit_changes (ParseType parse_type,
if (uid == NULL)
return FALSE;
- g_print (" * Source: %s\n", uid);
+ e_source_registry_debug_print (" * Source: %s\n", uid);
- g_print (" Writing key file...\n");
+ e_source_registry_debug_print (" Writing key file...\n");
/* Save the key file contents to disk. */
contents = g_key_file_to_data (key_file, &length, NULL);
@@ -400,21 +400,21 @@ migrate_parse_commit_changes (ParseType parse_type,
old_directory_exists = g_file_test (old_directory, G_FILE_TEST_EXISTS);
new_directory_exists = g_file_test (new_directory, G_FILE_TEST_EXISTS);
- g_print (
+ e_source_registry_debug_print (
" Checking for old cache dir '%s'... %s\n",
old_directory,
old_directory_exists ? "found" : "not found");
if (old_directory_exists) {
- g_print (
+ e_source_registry_debug_print (
" Checking for new cache dir '%s'... %s\n",
new_directory,
new_directory_exists ? "found" : "not found");
if (new_directory_exists)
- g_print (" Skipping cache directory rename.\n");
+ e_source_registry_debug_print (" Skipping cache directory rename.\n");
else {
- g_print (" Renaming old cache directory...\n");
+ e_source_registry_debug_print (" Renaming old cache directory...\n");
if (g_rename (old_directory, new_directory) < 0) {
g_set_error (
error, G_FILE_ERROR,
@@ -444,21 +444,21 @@ migrate_parse_commit_changes (ParseType parse_type,
old_directory_exists = g_file_test (old_directory, G_FILE_TEST_EXISTS);
new_directory_exists = g_file_test (new_directory, G_FILE_TEST_EXISTS);
- g_print (
+ e_source_registry_debug_print (
" Checking for old data dir '%s'... %s\n",
old_directory,
old_directory_exists ? "found" : "not found");
if (old_directory_exists) {
- g_print (
+ e_source_registry_debug_print (
" Checking for new data dir '%s'... %s\n",
new_directory,
new_directory_exists ? "found" : "not found");
if (new_directory_exists)
- g_print (" Skipping data directory rename.\n");
+ e_source_registry_debug_print (" Skipping data directory rename.\n");
else {
- g_print (" Renaming old data directory...\n");
+ e_source_registry_debug_print (" Renaming old data directory...\n");
if (g_rename (old_directory, new_directory) < 0) {
g_set_error (
error, G_FILE_ERROR,
@@ -3678,7 +3678,7 @@ migrate_and_remove_key (const gchar *filename,
filename, &contents, &length, &local_error);
if (contents != NULL) {
- g_print ("Migrating %s from GConf...\n", migrate_type_name);
+ e_source_registry_debug_print ("Migrating %s from GConf...\n", migrate_type_name);
migrate_parse_gconf_xml (
parse_type, contents, length, &local_error);
diff --git a/services/evolution-source-registry/evolution-source-registry.c b/services/evolution-source-registry/evolution-source-registry.c
index b258c81..51965d3 100644
--- a/services/evolution-source-registry/evolution-source-registry.c
+++ b/services/evolution-source-registry/evolution-source-registry.c
@@ -216,7 +216,7 @@ reload:
const gchar *config_dir;
gchar *dirname;
- g_print ("Reloading...\n");
+ e_source_registry_debug_print ("Reloading...\n");
/* It's possible the Reload is called after restore, where
* the ~/.config/evolution/sources directory can be missing,
--- End Message ---