Package: release.debian.org Severity: normal User: release.debian....@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 <j...@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 <mbar...@redhat.com> Milan Crha <mc...@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:pchenth...@novell.com" /> - <gnome:userid>pchen</gnome:userid> - </foaf:Person> - </maintainer> - - <maintainer> - <foaf:Person> - <foaf:name>Matthew Barnes</foaf:name> - <foaf:mbox rdf:resource="mailto:mbar...@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:gi...@gnome.org" /> - <gnome:userid>gicmo</gnome:userid> - </foaf:Person> - </maintainer> - - <maintainer> - <foaf:Person> - <foaf:name>Ross Burton</foaf:name> - <foaf:mbox rdf:resource="mailto:r...@burtonini.com" /> - <gnome:userid>rburton</gnome:userid> - </foaf:Person> - </maintainer> - - <maintainer> - <foaf:Person> - <foaf:name>Srinivasa Ragavan</foaf:name> - <foaf:mbox rdf:resource="mailto:sraga...@novell.com" /> - <gnome:userid>sragavan</gnome:userid> + <foaf:name>Milan Crha</foaf:name> + <foaf:mbox rdf:resource="mailto:mc...@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,