[evolution-patches] Exchange, offline-online and other fixes.
- From: Arunprakash <arunp novell com>
- To: evolution-patches <evolution-patches lists ximian com>
- Subject: [evolution-patches] Exchange, offline-online and other fixes.
- Date: Thu, 18 Aug 2005 15:17:38 +0530
Hi,
Attached patch fixes,
* Not entering offline mode problem. (#313637)
* Deleting items in public folder. (#272751)
* Deleting/moving/copying test* folders. (#310726, #310437)
* Folder creation problem. (#313071)
* Offline crash while starting Evolution. (#313797)
Please review it.
Thanks,
Arunprakash.
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution-exchange/ChangeLog,v
retrieving revision 1.379
diff -u -p -r1.379 ChangeLog
--- ChangeLog 18 Aug 2005 04:31:54 -0000 1.379
+++ ChangeLog 18 Aug 2005 09:30:44 -0000
@@ -1,3 +1,34 @@
+2005-08-17 Arunprakash <arunp novell com>
+
+ * camel/camel-exchange-store.c (camel_exchange_store_connected) :
+ Newly added to ensure that we are connected when the camel session
+ is too online.
+ * camel/camel-exchange-folder.c : Updated to make use of the new
+ function camel_exchange_store_connected.
+ (camel_exchange_folder_update_message_flags_ex) : Newly added to
+ selectively set and unset message flags.
+ * camel/camel-exchange-store.c : Updated to use
+ camel_exchange_store_connected.
+ (exchange_folder_subscribed) (exchange_subscribe_folder)
+ (exchange_unsubscribe_folder) : Changed the type of data for folder
+ name from string to folder type while sending to backend. Because the
+ other side expects folder type.
+ (stub_notification) : Modified to include new retval for setting and
+ unsetting specific flags.
+ * mail/mail-stub-exchange.c (folder_from_name) : Try using create
+ permission for shared folders.
+ (get_folder_online) : Newly added by removing the online code from
+ get_folder.
+ (get_folder) : Updated to use get_folder_online. Also set the readonly
+ flag only if it fails for modify and create permissions.
+ (expunge_uids) : Report the error in case of failure.
+ (process_flags) : Do an expunge for mails in non-personal folders.
+ If fails, undo the delete.
+ (get_folder_info) : Ensure the top is exactly equal to the path. Also
+ added some extra checks.
+ (folder_update_linestatus) : Updated to use get_folder_online.
+ Fixes #313637, #272751, #310726, #310437, #313797, #313071.
+
2005-08-17 Not Zed <NotZed Ximian com>
** See bug #312668.
Index: camel/camel-exchange-folder.c
===================================================================
RCS file: /cvs/gnome/evolution-exchange/camel/camel-exchange-folder.c,v
retrieving revision 1.18
diff -u -p -r1.18 camel-exchange-folder.c
--- camel/camel-exchange-folder.c 25 Jul 2005 11:03:16 -0000 1.18
+++ camel/camel-exchange-folder.c 18 Aug 2005 09:30:45 -0000
@@ -197,9 +197,9 @@ static void
refresh_info (CamelFolder *folder, CamelException *ex)
{
CamelExchangeFolder *exch = CAMEL_EXCHANGE_FOLDER (folder);
- CamelOfflineStore *store = CAMEL_OFFLINE_STORE (folder->parent_store);
+ CamelExchangeStore *store = CAMEL_EXCHANGE_STORE (folder->parent_store);
- if (store->state != CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
+ if (camel_exchange_store_connected (store, ex)) {
camel_offline_journal_replay (exch->journal, NULL);
camel_stub_send (exch->stub, ex, CAMEL_STUB_CMD_REFRESH_FOLDER,
@@ -276,9 +276,9 @@ append_message (CamelFolder *folder, Cam
CamelException *ex)
{
CamelStream *stream_mem;
- CamelOfflineStore *offline = (CamelOfflineStore *) folder->parent_store;
+ CamelExchangeStore *store = CAMEL_EXCHANGE_STORE (folder->parent_store);
- if (offline->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
+ if (!camel_exchange_store_connected (store, ex)) {
camel_exchange_journal_append ((CamelExchangeJournal *) ((CamelExchangeFolder *)folder)->journal, message, info, appended_uid, ex);
return;
}
@@ -352,7 +352,7 @@ static GByteArray *
get_message_data (CamelFolder *folder, const char *uid, CamelException *ex)
{
CamelExchangeFolder *exch = CAMEL_EXCHANGE_FOLDER (folder);
- CamelOfflineStore *offline = (CamelOfflineStore *) folder->parent_store;
+ CamelExchangeStore *store = CAMEL_EXCHANGE_STORE (folder->parent_store);
CamelStream *stream, *stream_mem;
GByteArray *ba;
@@ -369,7 +369,7 @@ get_message_data (CamelFolder *folder, c
return ba;
}
- if (offline->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
+ if (!camel_exchange_store_connected (store, ex)) {
camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
_("This message is not available in offline mode."));
return NULL;
@@ -555,7 +555,7 @@ transfer_messages_the_hard_way (CamelFol
}
if (delete_originals) {
- camel_stub_send (exch_source->stub, NULL,
+ camel_stub_send (exch_source->stub, ex,
CAMEL_STUB_CMD_EXPUNGE_UIDS,
CAMEL_STUB_ARG_FOLDER, source->full_name,
CAMEL_STUB_ARG_STRINGARRAY, uids,
@@ -601,7 +601,7 @@ transfer_messages_to (CamelFolder *sourc
{
CamelExchangeFolder *exch_source = CAMEL_EXCHANGE_FOLDER (source);
CamelExchangeFolder *exch_dest = CAMEL_EXCHANGE_FOLDER (dest);
- CamelOfflineStore *offline = (CamelOfflineStore *) source->parent_store;
+ CamelExchangeStore *store = CAMEL_EXCHANGE_STORE (source->parent_store);
CamelMessageInfo *info;
GPtrArray *ret_uids = NULL;
int hier_len, i;
@@ -610,7 +610,7 @@ transfer_messages_to (CamelFolder *sourc
_("Copying messages"));
/* Check for offline operation */
- if (offline->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
+ if (!camel_exchange_store_connected (store, ex)) {
CamelExchangeJournal *journal = (CamelExchangeJournal *) exch_dest->journal;
CamelMimeMessage *message;
@@ -854,6 +854,47 @@ camel_exchange_folder_update_message_fla
if (info->flags != flags) {
info->flags = flags;
+ camel_folder_summary_touch (folder->summary);
+
+ changes = camel_folder_change_info_new ();
+ camel_folder_change_info_change_uid (changes, uid);
+ camel_object_trigger_event (CAMEL_OBJECT (exch),
+ "folder_changed", changes);
+ camel_folder_change_info_free (changes);
+ }
+}
+
+/**
+ * camel_exchange_folder_update_message_flags_ex:
+ * @exch: the folder
+ * @uid: the message
+ * @flags: new message flags
+ * @mask: the flag mask
+ *
+ * Update the message flags of @uid in @exch's summary based on @flags and @mask.
+ * Only the bits in the mask %CAMEL_EXCHANGE_SERVER_FLAGS are valid to be set or unset.
+ **/
+void
+camel_exchange_folder_update_message_flags_ex (CamelExchangeFolder *exch,
+ const char *uid, guint32 flags,
+ guint32 mask)
+{
+ CamelFolder *folder = CAMEL_FOLDER (exch);
+ CamelMessageInfoBase *info;
+ CamelFolderChangeInfo *changes;
+
+ info = (CamelMessageInfoBase *)camel_folder_summary_uid (folder->summary, uid);
+ if (!info)
+ return;
+
+ mask &= CAMEL_EXCHANGE_SERVER_FLAGS;
+ if (!mask) {
+ return;
+ }
+
+ if ((info->flags & mask) != (flags & mask)) {
+ info->flags &= ~mask;
+ info->flags |= (flags & mask);
camel_folder_summary_touch (folder->summary);
changes = camel_folder_change_info_new ();
Index: camel/camel-exchange-folder.h
===================================================================
RCS file: /cvs/gnome/evolution-exchange/camel/camel-exchange-folder.h,v
retrieving revision 1.7
diff -u -p -r1.7 camel-exchange-folder.h
--- camel/camel-exchange-folder.h 26 Feb 2005 14:19:15 -0000 1.7
+++ camel/camel-exchange-folder.h 18 Aug 2005 09:30:45 -0000
@@ -70,6 +70,11 @@ void camel_exchange_folder_update_me
const char *uid,
guint32 flags);
+void camel_exchange_folder_update_message_flags_ex (CamelExchangeFolder *exch,
+ const char *uid,
+ guint32 flags,
+ guint32 mask);
+
void camel_exchange_folder_update_message_tag (CamelExchangeFolder *exch,
const char *uid,
const char *name,
Index: camel/camel-exchange-store.c
===================================================================
RCS file: /cvs/gnome/evolution-exchange/camel/camel-exchange-store.c,v
retrieving revision 1.21
diff -u -p -r1.21 camel-exchange-store.c
--- camel/camel-exchange-store.c 6 Aug 2005 11:36:50 -0000 1.21
+++ camel/camel-exchange-store.c 18 Aug 2005 09:30:46 -0000
@@ -158,6 +158,28 @@ camel_exchange_store_get_type (void)
return camel_exchange_store_type;
}
+/* Use this to ensure that the camel session is online and we are connected
+ too. Also returns the current status of the store */
+gboolean
+camel_exchange_store_connected (CamelExchangeStore *store, CamelException *ex)
+{
+ CamelService *service;
+ CamelSession *session;
+
+ g_return_val_if_fail (CAMEL_IS_EXCHANGE_STORE (store), FALSE);
+
+ service = CAMEL_SERVICE (store);
+ session = service->session;
+
+ if (service->status != CAMEL_SERVICE_CONNECTED &&
+ camel_session_is_online (session) &&
+ !camel_service_connect (service, ex)) {
+ return FALSE;
+ }
+
+ return CAMEL_OFFLINE_STORE (store)->state != CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL;
+}
+
/* This has been now removed from evolution/e-util. So implemented this here.
* Also note that this is similar to the call in e2k-path.c. The name of the
* function has been changed to avoid any conflicts.
@@ -359,8 +381,11 @@ exchange_disconnect (CamelService *servi
return TRUE;
}
-#define RETURN_VAL_IF_NOT_CONNECTED(service, ex, val)\
- if (!exchange_connect((CamelService *)service, ex))\
+/* Even if we are disconnected, we need to exchange_connect
+ to get the offline data */
+#define RETURN_VAL_IF_NOT_CONNECTED(store, ex, val)\
+ if (!camel_exchange_store_connected(store, ex) && \
+ !exchange_connect (CAMEL_SERVICE (store), ex)) \
return val;
static CamelFolder *
@@ -371,11 +396,11 @@ exchange_get_folder (CamelStore *store,
CamelFolder *folder;
char *folder_dir;
- RETURN_VAL_IF_NOT_CONNECTED(store, ex, NULL);
+ RETURN_VAL_IF_NOT_CONNECTED (exch, ex, NULL);
folder_dir = exchange_path_to_physical (exch->storage_path, folder_name);
- if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
+ if (!camel_exchange_store_connected (exch, ex)) {
if (!folder_dir || access (folder_dir, F_OK) != 0) {
g_free (folder_dir);
camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
@@ -430,7 +455,7 @@ exchange_folder_subscribed (CamelStore *
}
if (!camel_stub_send (exch->stub, NULL, CAMEL_STUB_CMD_IS_SUBSCRIBED_FOLDER,
- CAMEL_STUB_ARG_STRING, folder_name,
+ CAMEL_STUB_ARG_FOLDER, folder_name,
CAMEL_STUB_ARG_RETURN,
CAMEL_STUB_ARG_UINT32, &is_subscribed,
CAMEL_STUB_ARG_END)) {
@@ -447,13 +472,13 @@ exchange_subscribe_folder (CamelStore *s
d(printf ("subscribe folder : %s\n", folder_name));
CamelExchangeStore *exch = CAMEL_EXCHANGE_STORE (store);
- if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
+ if (!camel_exchange_store_connected (exch, ex)) {
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot subscribe folder in offline mode."));
return;
}
camel_stub_send (exch->stub, ex, CAMEL_STUB_CMD_SUBSCRIBE_FOLDER,
- CAMEL_STUB_ARG_STRING, folder_name,
+ CAMEL_STUB_ARG_FOLDER, folder_name,
CAMEL_STUB_ARG_END);
}
@@ -464,13 +489,13 @@ exchange_unsubscribe_folder (CamelStore
d(printf ("unsubscribe folder : %s\n", folder_name));
CamelExchangeStore *exch = CAMEL_EXCHANGE_STORE (store);
- if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
+ if (!camel_exchange_store_connected (exch, ex)) {
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot unsubscribe folder in offline mode."));
return;
}
camel_stub_send (exch->stub, ex, CAMEL_STUB_CMD_UNSUBSCRIBE_FOLDER,
- CAMEL_STUB_ARG_STRING, folder_name,
+ CAMEL_STUB_ARG_FOLDER, folder_name,
CAMEL_STUB_ARG_END);
}
@@ -480,7 +505,7 @@ get_trash (CamelStore *store, CamelExcep
{
CamelExchangeStore *exch = CAMEL_EXCHANGE_STORE (store);
- RETURN_VAL_IF_NOT_CONNECTED(store, ex, NULL);
+ RETURN_VAL_IF_NOT_CONNECTED (exch, ex, NULL);
if (!exch->trash_name) {
if (!camel_stub_send (exch->stub, ex, CAMEL_STUB_CMD_GET_TRASH_NAME,
@@ -579,7 +604,7 @@ exchange_get_folder_info (CamelStore *st
* each time auto-send/recv runs.
*/
- RETURN_VAL_IF_NOT_CONNECTED(store, ex, NULL);
+ RETURN_VAL_IF_NOT_CONNECTED (exch, ex, NULL);
if (camel_stub_marshal_eof (exch->stub->cmd))
return NULL;
@@ -640,7 +665,7 @@ exchange_create_folder (CamelStore *stor
guint32 unread_count, flags;
CamelFolderInfo *info;
- if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
+ if (!camel_exchange_store_connected (exch, ex)) {
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create folder in offline mode."));
return NULL;
}
@@ -667,7 +692,7 @@ exchange_delete_folder (CamelStore *stor
{
CamelExchangeStore *exch = CAMEL_EXCHANGE_STORE (store);
- if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
+ if (!camel_exchange_store_connected (exch, ex)) {
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot delete folder in offline mode."));
return;
}
@@ -683,7 +708,7 @@ exchange_rename_folder (CamelStore *stor
{
CamelExchangeStore *exch = CAMEL_EXCHANGE_STORE (store);
- if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
+ if (!camel_exchange_store_connected (exch, ex)) {
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot rename folder in offline mode."));
return;
}
@@ -788,6 +813,31 @@ stub_notification (CamelObject *object,
g_mutex_unlock (exch->folders_lock);
if (folder)
camel_exchange_folder_update_message_flags (folder, uid, flags);
+
+ g_free (folder_name);
+ g_free (uid);
+ break;
+ }
+
+ case CAMEL_STUB_RETVAL_CHANGED_FLAGS_EX:
+ {
+ CamelExchangeFolder *folder;
+ char *folder_name, *uid;
+ guint32 flags;
+ guint32 mask;
+
+ if (camel_stub_marshal_decode_folder (stub->status, &folder_name) == -1 ||
+ camel_stub_marshal_decode_string (stub->status, &uid) == -1 ||
+ camel_stub_marshal_decode_uint32 (stub->status, &flags) == -1 ||
+ camel_stub_marshal_decode_uint32 (stub->status, &mask) == -1)
+ break;
+
+ g_mutex_lock (exch->folders_lock);
+ folder = g_hash_table_lookup (exch->folders, folder_name);
+ g_mutex_unlock (exch->folders_lock);
+ if (folder)
+ camel_exchange_folder_update_message_flags_ex (folder, uid,
+ flags, mask);
g_free (folder_name);
g_free (uid);
Index: camel/camel-exchange-store.h
===================================================================
RCS file: /cvs/gnome/evolution-exchange/camel/camel-exchange-store.h,v
retrieving revision 1.3
diff -u -p -r1.3 camel-exchange-store.h
--- camel/camel-exchange-store.h 11 Jan 2005 07:06:01 -0000 1.3
+++ camel/camel-exchange-store.h 18 Aug 2005 09:30:46 -0000
@@ -42,6 +42,8 @@ typedef struct {
/* Standard Camel function */
CamelType camel_exchange_store_get_type (void);
+gboolean camel_exchange_store_connected (CamelExchangeStore *store, CamelException *ex);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
Index: camel/camel-stub-constants.h
===================================================================
RCS file: /cvs/gnome/evolution-exchange/camel/camel-stub-constants.h,v
retrieving revision 1.5
diff -u -p -r1.5 camel-stub-constants.h
--- camel/camel-stub-constants.h 28 Jun 2005 09:20:46 -0000 1.5
+++ camel/camel-stub-constants.h 18 Aug 2005 09:30:46 -0000
@@ -55,6 +55,10 @@ typedef enum {
CAMEL_STUB_RETVAL_REMOVED_MESSAGE,
CAMEL_STUB_RETVAL_CHANGED_MESSAGE,
CAMEL_STUB_RETVAL_CHANGED_FLAGS,
+
+ /* This is used to undelete a message for which the operation failed.
+ But can also be used to specifically set or unset a flag. */
+ CAMEL_STUB_RETVAL_CHANGED_FLAGS_EX,
CAMEL_STUB_RETVAL_CHANGED_TAG,
CAMEL_STUB_RETVAL_PROGRESS,
CAMEL_STUB_RETVAL_FREEZE_FOLDER,
Index: mail/mail-stub-exchange.c
===================================================================
RCS file: /cvs/gnome/evolution-exchange/mail/mail-stub-exchange.c,v
retrieving revision 1.23
diff -u -p -r1.23 mail-stub-exchange.c
--- mail/mail-stub-exchange.c 6 Aug 2005 11:36:50 -0000 1.23
+++ mail/mail-stub-exchange.c 18 Aug 2005 09:30:48 -0000
@@ -133,6 +133,7 @@ static void linestatus_listener (Exchang
gpointer data);
static void folder_update_linestatus (gpointer key, gpointer value, gpointer data);
static void free_folder (gpointer value);
+static void get_folder_online (MailStubExchangeFolder *mfld, gboolean background);
static void
class_init (GObjectClass *object_class)
@@ -267,6 +268,12 @@ folder_from_name (MailStubExchange *mse,
sync_deletions (mse, mfld);
}
+ if ((perms == MAPI_ACCESS_MODIFY || perms == MAPI_ACCESS_DELETE) &&
+ !(mfld->access & perms)) {
+ /* try with MAPI_ACCESS_CREATE_CONTENTS */
+ perms = MAPI_ACCESS_CREATE_CONTENTS;
+ }
+
if (perms && !(mfld->access & perms)) {
if (!background)
mail_stub_return_error (MAIL_STUB (mse), _("Permission denied"));
@@ -544,15 +551,10 @@ static const char *open_folder_props[] =
static const int n_open_folder_props = sizeof (open_folder_props) / sizeof (open_folder_props[0]);
static void
-get_folder (MailStub *stub, const char *name, gboolean create,
- GPtrArray *uids, GByteArray *flags)
+get_folder_online (MailStubExchangeFolder *mfld, gboolean background)
{
- MailStubExchange *mse = MAIL_STUB_EXCHANGE (stub);
- MailStubExchangeFolder *mfld;
MailStubExchangeMessage *mmsg;
- EFolder *folder;
- char *path;
- const char *outlook_class;
+ MailStub *stub = MAIL_STUB (mfld->mse);
E2kHTTPStatus status;
E2kResult *results;
int nresults;
@@ -562,7 +564,177 @@ get_folder (MailStub *stub, const char *
E2kResult *result;
const char *prop, *uid;
guint32 article_num, camel_flags;
- int i, m, total = -1, mode;
+ int i, m, total = -1;
+
+ mfld->changed_messages = g_ptr_array_new ();
+
+ status = e_folder_exchange_propfind (mfld->folder, NULL,
+ open_folder_props,
+ n_open_folder_props,
+ &results, &nresults);
+ if (status == E2K_HTTP_UNAUTHORIZED) {
+ if (!background) {
+ got_folder_error (mfld, _("Could not open folder: Permission denied"));
+ }
+ return;
+ } else if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
+ g_warning ("got_folder_props: %d", status);
+ if (!background) {
+ got_folder_error (mfld, _("Could not open folder"));
+ }
+ return;
+ }
+
+ if (nresults) {
+ prop = e2k_properties_get_prop (results[0].props, PR_ACCESS);
+ if (prop)
+ mfld->access = atoi (prop);
+ else
+ mfld->access = ~0;
+ } else
+ mfld->access = ~0;
+
+ if (!(mfld->access & MAPI_ACCESS_READ)) {
+ if (!background) {
+ got_folder_error (mfld, _("Could not open folder: Permission denied"));
+ }
+ return;
+ }
+ readonly = (mfld->access & (MAPI_ACCESS_MODIFY | MAPI_ACCESS_CREATE_CONTENTS)) == 0;
+
+ prop = e2k_properties_get_prop (results[0].props, PR_DELETED_COUNT_TOTAL);
+ if (prop)
+ mfld->deleted_count = atoi (prop);
+
+ rn = e2k_restriction_andv (
+ e2k_restriction_prop_bool (E2K_PR_DAV_IS_COLLECTION,
+ E2K_RELOP_EQ, FALSE),
+ e2k_restriction_prop_bool (E2K_PR_DAV_IS_HIDDEN,
+ E2K_RELOP_EQ, FALSE),
+ NULL);
+
+ iter = e_folder_exchange_search_start (mfld->folder, NULL,
+ open_folder_sync_props,
+ n_open_folder_sync_props,
+ rn, E2K_PR_DAV_CREATION_DATE,
+ TRUE);
+ e2k_restriction_unref (rn);
+
+ m = 0;
+ total = e2k_result_iter_get_total (iter);
+ while ((result = e2k_result_iter_next (iter)) && m < mfld->messages->len) {
+ prop = e2k_properties_get_prop (result->props,
+ PR_INTERNET_ARTICLE_NUMBER);
+ if (!prop)
+ continue;
+ article_num = strtoul (prop, NULL, 10);
+
+ prop = e2k_properties_get_prop (result->props,
+ E2K_PR_REPL_UID);
+ if (!prop)
+ continue;
+ uid = uidstrip (prop);
+
+ camel_flags = mail_util_props_to_camel_flags (result->props,
+ !readonly);
+
+ mmsg = mfld->messages->pdata[m];
+ while (strcmp (uid, mmsg->uid)) {
+ message_remove_at_index (stub, mfld, m);
+ if (m == mfld->messages->len) {
+ mmsg = NULL;
+ if (article_num < mfld->high_article_num)
+ mfld->high_article_num = article_num - 1;
+ break;
+ }
+ mmsg = mfld->messages->pdata[m];
+ }
+ if (!mmsg)
+ break;
+
+ mmsg->href = g_strdup (result->href);
+ g_hash_table_insert (mfld->messages_by_href, mmsg->href, mmsg);
+ if (article_num > mfld->high_article_num)
+ mfld->high_article_num = article_num;
+ if (mmsg->flags != camel_flags)
+ change_flags (mfld, mmsg, camel_flags);
+
+ prop = e2k_properties_get_prop (result->props, E2K_PR_HTTPMAIL_MESSAGE_FLAG);
+ if (prop)
+ return_tag (mfld, mmsg->uid, "follow-up", prop);
+ prop = e2k_properties_get_prop (result->props, E2K_PR_MAILHEADER_REPLY_BY);
+ if (prop)
+ return_tag (mfld, mmsg->uid, "due-by", prop);
+ prop = e2k_properties_get_prop (result->props, E2K_PR_MAILHEADER_COMPLETED);
+ if (prop)
+ return_tag (mfld, mmsg->uid, "completed-on", prop);
+
+ m++;
+ if (!background) {
+ mail_stub_return_progress (stub, (m * 100) / total);
+ }
+ }
+
+ /* If there are further messages beyond mfld->messages->len,
+ * then that means camel doesn't know about them yet, and so
+ * we need to ignore them for a while. But if any of them have
+ * an article number lower than the highest article number
+ * we've seen, bump high_article_num down so that that message
+ * gets caught by refresh_info later too.
+ */
+ while ((result = e2k_result_iter_next (iter))) {
+ prop = e2k_properties_get_prop (result->props,
+ PR_INTERNET_ARTICLE_NUMBER);
+ if (prop) {
+ article_num = strtoul (prop, NULL, 10);
+ if (article_num < mfld->high_article_num)
+ mfld->high_article_num = article_num - 1;
+ }
+
+ m++;
+ if (!background) {
+ mail_stub_return_progress (stub, (m * 100) / total);
+ }
+ }
+
+ status = e2k_result_iter_free (iter);
+ if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
+ g_warning ("got_folder: %d", status);
+ if (!background) {
+ got_folder_error (mfld, _("Could not open folder"));
+ }
+ return;
+ }
+
+ /* Discard remaining messages that no longer exist. */
+ for (i = 0; i < mfld->messages->len; i++) {
+ mmsg = mfld->messages->pdata[i];
+ if (!mmsg->href)
+ message_remove_at_index (stub, mfld, i--);
+ }
+ e_folder_exchange_subscribe (mfld->folder,
+ E2K_CONTEXT_OBJECT_ADDED, 30,
+ notify_cb, mfld);
+ e_folder_exchange_subscribe (mfld->folder,
+ E2K_CONTEXT_OBJECT_REMOVED, 30,
+ notify_cb, mfld);
+ e_folder_exchange_subscribe (mfld->folder,
+ E2K_CONTEXT_OBJECT_MOVED, 30,
+ notify_cb, mfld);
+}
+
+static void
+get_folder (MailStub *stub, const char *name, gboolean create,
+ GPtrArray *uids, GByteArray *flags)
+{
+ MailStubExchange *mse = MAIL_STUB_EXCHANGE (stub);
+ MailStubExchangeFolder *mfld;
+ MailStubExchangeMessage *mmsg;
+ EFolder *folder;
+ char *path;
+ const char *outlook_class;
+ guint32 camel_flags;
+ int i, mode;
ExchangeHierarchy *hier;
path = g_strdup_printf ("/%s", name);
@@ -618,150 +790,8 @@ get_folder (MailStub *stub, const char *
}
exchange_component_is_offline (global_exchange_component, &mode);
if (mode == ONLINE_MODE) {
- mfld->changed_messages = g_ptr_array_new ();
-
- status = e_folder_exchange_propfind (mfld->folder, NULL,
- open_folder_props,
- n_open_folder_props,
- &results, &nresults);
- if (status == E2K_HTTP_UNAUTHORIZED) {
- got_folder_error (mfld, _("Could not open folder: Permission denied"));
- return;
- } else if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
- g_warning ("got_folder_props: %d", status);
- got_folder_error (mfld, _("Could not open folder"));
- return;
- }
-
- if (nresults) {
- prop = e2k_properties_get_prop (results[0].props, PR_ACCESS);
- if (prop)
- mfld->access = atoi (prop);
- else
- mfld->access = ~0;
- } else
- mfld->access = ~0;
-
- if (!(mfld->access & MAPI_ACCESS_READ)) {
- got_folder_error (mfld, _("Could not open folder: Permission denied"));
- return;
- }
- readonly = (mfld->access & MAPI_ACCESS_MODIFY) == 0;
-
- prop = e2k_properties_get_prop (results[0].props, PR_DELETED_COUNT_TOTAL);
- if (prop)
- mfld->deleted_count = atoi (prop);
-
- rn = e2k_restriction_andv (
- e2k_restriction_prop_bool (E2K_PR_DAV_IS_COLLECTION,
- E2K_RELOP_EQ, FALSE),
- e2k_restriction_prop_bool (E2K_PR_DAV_IS_HIDDEN,
- E2K_RELOP_EQ, FALSE),
- NULL);
-
- iter = e_folder_exchange_search_start (mfld->folder, NULL,
- open_folder_sync_props,
- n_open_folder_sync_props,
- rn, E2K_PR_DAV_CREATION_DATE,
- TRUE);
- e2k_restriction_unref (rn);
-
- m = 0;
- total = e2k_result_iter_get_total (iter);
- while ((result = e2k_result_iter_next (iter)) && m < mfld->messages->len) {
- prop = e2k_properties_get_prop (result->props,
- PR_INTERNET_ARTICLE_NUMBER);
- if (!prop)
- continue;
- article_num = strtoul (prop, NULL, 10);
-
- prop = e2k_properties_get_prop (result->props,
- E2K_PR_REPL_UID);
- if (!prop)
- continue;
- uid = uidstrip (prop);
-
- camel_flags = mail_util_props_to_camel_flags (result->props,
- !readonly);
-
- mmsg = mfld->messages->pdata[m];
- while (strcmp (uid, mmsg->uid)) {
- message_remove_at_index (stub, mfld, m);
- if (m == mfld->messages->len) {
- mmsg = NULL;
- if (article_num < mfld->high_article_num)
- mfld->high_article_num = article_num - 1;
- break;
- }
- mmsg = mfld->messages->pdata[m];
- }
- if (!mmsg)
- break;
-
- mmsg->href = g_strdup (result->href);
- g_hash_table_insert (mfld->messages_by_href, mmsg->href, mmsg);
- if (article_num > mfld->high_article_num)
- mfld->high_article_num = article_num;
- if (mmsg->flags != camel_flags)
- change_flags (mfld, mmsg, camel_flags);
-
- prop = e2k_properties_get_prop (result->props, E2K_PR_HTTPMAIL_MESSAGE_FLAG);
- if (prop)
- return_tag (mfld, mmsg->uid, "follow-up", prop);
- prop = e2k_properties_get_prop (result->props, E2K_PR_MAILHEADER_REPLY_BY);
- if (prop)
- return_tag (mfld, mmsg->uid, "due-by", prop);
- prop = e2k_properties_get_prop (result->props, E2K_PR_MAILHEADER_COMPLETED);
- if (prop)
- return_tag (mfld, mmsg->uid, "completed-on", prop);
-
- m++;
- mail_stub_return_progress (stub, (m * 100) / total);
- }
-
- /* If there are further messages beyond mfld->messages->len,
- * then that means camel doesn't know about them yet, and so
- * we need to ignore them for a while. But if any of them have
- * an article number lower than the highest article number
- * we've seen, bump high_article_num down so that that message
- * gets caught by refresh_info later too.
- */
- while ((result = e2k_result_iter_next (iter))) {
- prop = e2k_properties_get_prop (result->props,
- PR_INTERNET_ARTICLE_NUMBER);
- if (prop) {
- article_num = strtoul (prop, NULL, 10);
- if (article_num < mfld->high_article_num)
- mfld->high_article_num = article_num - 1;
- }
-
- m++;
- mail_stub_return_progress (stub, (m * 100) / total);
- }
-
- status = e2k_result_iter_free (iter);
- if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
- g_warning ("got_folder: %d", status);
- got_folder_error (mfld, _("Could not open folder"));
- return;
- }
-
- /* Discard remaining messages that no longer exist. */
- for (i = 0; i < mfld->messages->len; i++) {
- mmsg = mfld->messages->pdata[i];
- if (!mmsg->href)
- message_remove_at_index (stub, mfld, i--);
- }
- e_folder_exchange_subscribe (mfld->folder,
- E2K_CONTEXT_OBJECT_ADDED, 30,
- notify_cb, mfld);
- e_folder_exchange_subscribe (mfld->folder,
- E2K_CONTEXT_OBJECT_REMOVED, 30,
- notify_cb, mfld);
- e_folder_exchange_subscribe (mfld->folder,
- E2K_CONTEXT_OBJECT_MOVED, 30,
- notify_cb, mfld);
- } // end online work
+ get_folder_online (mfld, FALSE);
+ }
g_signal_connect (mfld->folder, "changed",
G_CALLBACK (storage_folder_changed), mfld);
@@ -769,7 +799,7 @@ get_folder (MailStub *stub, const char *
folder_changed (mfld);
camel_flags = 0;
- if ((mfld->access & MAPI_ACCESS_MODIFY) == 0)
+ if ((mfld->access & (MAPI_ACCESS_MODIFY | MAPI_ACCESS_CREATE_CONTENTS)) == 0)
camel_flags |= CAMEL_STUB_FOLDER_READONLY;
if (mse->account->filter_inbox && (mfld->folder == mse->inbox))
camel_flags |= CAMEL_STUB_FOLDER_FILTER;
@@ -1283,6 +1313,7 @@ expunge_uids (MailStub *stub, const char
E2kResult *result;
E2kHTTPStatus status;
int i, ndeleted;
+ gboolean some_error = FALSE;
if (!uids->len) {
mail_stub_return_ok (stub);
@@ -1318,6 +1349,10 @@ expunge_uids (MailStub *stub, const char
hrefs->len);
ndeleted = 0;
while ((result = e2k_result_iter_next (iter))) {
+ if (result->status == E2K_HTTP_UNAUTHORIZED) {
+ some_error = TRUE;
+ continue;
+ }
message_removed (stub, mfld, result->href);
mfld->deleted_count++;
ndeleted++;
@@ -1333,8 +1368,13 @@ expunge_uids (MailStub *stub, const char
if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
g_warning ("expunged: %d", status);
mail_stub_return_error (stub, _("Could not empty Deleted Items folder"));
- } else
+ } else if (some_error) {
+ /* FIXME: should be this, but string freeze freezes me to do so.
+ mail_stub_return_error (stub, _("Permission denied. Could not delete certain mails.")); */
+ mail_stub_return_error (stub, _("Permission denied"));
+ } else {
mail_stub_return_ok (stub);
+ }
g_ptr_array_free (hrefs, TRUE);
}
@@ -1558,6 +1598,7 @@ process_flags (gpointer user_data)
MailStubExchangeMessage *mmsg;
GPtrArray *seen = NULL, *unseen = NULL, *deleted = NULL;
int i;
+ guint32 hier_type = e_folder_exchange_get_hierarchy (mfld->folder)->type;
for (i = 0; i < mfld->changed_messages->len; i++) {
mmsg = mfld->changed_messages->pdata[i];
@@ -1633,13 +1674,32 @@ process_flags (gpointer user_data)
CAMEL_STUB_ARG_FOLDER, mfld->name,
CAMEL_STUB_ARG_END);
- iter = e_folder_exchange_transfer_start (mfld->folder, NULL,
- mse->deleted_items,
- deleted, TRUE);
- g_ptr_array_free (deleted, TRUE);
+ if (hier_type == EXCHANGE_HIERARCHY_PERSONAL) {
+ iter = e_folder_exchange_transfer_start (mfld->folder, NULL,
+ mse->deleted_items,
+ deleted, TRUE);
+ } else {
+ iter = e_folder_exchange_bdelete_start (mfld->folder, NULL,
+ (const char **)deleted->pdata,
+ deleted->len);
+ }
+ g_ptr_array_free (deleted, FALSE);
while ((result = e2k_result_iter_next (iter))) {
- if (!e2k_properties_get_prop (result->props, E2K_PR_DAV_LOCATION))
+ if (hier_type == EXCHANGE_HIERARCHY_PERSONAL) {
+ if (!e2k_properties_get_prop (result->props,
+ E2K_PR_DAV_LOCATION)) {
+ continue;
+ }
+ } else if (result->status == E2K_HTTP_UNAUTHORIZED) {
+ mail_stub_return_data (MAIL_STUB (mfld->mse),
+ CAMEL_STUB_RETVAL_CHANGED_FLAGS_EX,
+ CAMEL_STUB_ARG_FOLDER, mfld->name,
+ CAMEL_STUB_ARG_STRING, mmsg->uid,
+ CAMEL_STUB_ARG_UINT32, 0,
+ CAMEL_STUB_ARG_UINT32, MAIL_STUB_MESSAGE_DELETED,
+ CAMEL_STUB_ARG_END);
continue;
+ }
message_removed (stub, mfld, result->href);
mfld->deleted_count++;
@@ -1719,6 +1779,12 @@ set_message_flags (MailStub *stub, const
* hierarchy, we ignore it (which will cause camel to delete
* it the hard way next time it syncs).
*/
+
+#if 0
+ /* If we allow camel stub to delete these messages hard way, it may
+ fail to delete a mail because of permissions, but will append
+ a mail in deleted items */
+
if (mask & flags & MAIL_STUB_MESSAGE_DELETED) {
ExchangeHierarchy *hier;
@@ -1726,6 +1792,7 @@ set_message_flags (MailStub *stub, const
if (hier->type != EXCHANGE_HIERARCHY_PERSONAL)
mask &= ~MAIL_STUB_MESSAGE_DELETED;
}
+#endif
/* If there's nothing left to change, return. */
if (!mask)
@@ -2184,7 +2251,7 @@ get_folder_info (MailStub *stub, const c
GArray *unread, *flags;
ExchangeHierarchy *hier;
EFolder *folder;
- const char *type, *name, *uri, *path, *inbox_uri;
+ const char *type, *name, *uri, *path, *inbox_uri = NULL;
int unread_count, i, toplen = top ? strlen (top) : 0;
guint32 folder_flags;
gboolean recursive, subscribed, single_folder = FALSE;
@@ -2221,7 +2288,10 @@ get_folder_info (MailStub *stub, const c
uris = g_ptr_array_new ();
unread = g_array_new (FALSE, FALSE, sizeof (int));
flags = g_array_new (FALSE, FALSE, sizeof (int));
- inbox_uri = e_folder_get_physical_uri (mse->inbox);
+ /* Can be NULL if started in offline mode */
+ if (mse->inbox) {
+ inbox_uri = e_folder_get_physical_uri (mse->inbox);
+ }
if (folders) {
for (i = 0; i < folders->len; i++) {
@@ -2245,7 +2315,8 @@ get_folder_info (MailStub *stub, const c
if (recursive && toplen) {
path = e_folder_exchange_get_path (folder);
- if (strncmp (path + 1, top, toplen) != 0)
+ if (strncmp (path + 1, top, toplen) != 0 ||
+ path[toplen + 1] != '\0')
continue;
}
return_data:
@@ -2288,7 +2359,7 @@ return_data:
break;
}
- if (!strcmp (uri, inbox_uri))
+ if (inbox_uri && !strcmp (uri, inbox_uri))
folder_flags |= CAMEL_STUB_FOLDER_SYSTEM|CAMEL_STUB_FOLDER_TYPE_INBOX;
g_ptr_array_add (names, (char *)name);
@@ -2715,44 +2786,10 @@ static void
folder_update_linestatus (gpointer key, gpointer value, gpointer data)
{
MailStubExchangeFolder *mfld = (MailStubExchangeFolder *) value;
- E2kResult *results;
- int nresults = 0;
- E2kHTTPStatus status;
- const char *prop;
gint linestatus = GPOINTER_TO_INT (data);
if (linestatus == ONLINE_MODE) {
- status = e_folder_exchange_propfind (mfld->folder, NULL,
- open_folder_props,
- n_open_folder_props,
- &results, &nresults);
-
- if (status == E2K_HTTP_UNAUTHORIZED) {
- got_folder_error (mfld, _("Could not open folder: Permission denied"));
- return;
- } else if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
- g_warning ("got_folder_props: %d", status);
- got_folder_error (mfld, _("Could not open folder"));
- return;
- }
-
- if (nresults) {
- prop = e2k_properties_get_prop (results[0].props, PR_ACCESS);
- if (prop)
- mfld->access = atoi (prop);
- else
- mfld->access = ~0;
- } else
- mfld->access = ~0;
-
- if (!(mfld->access & MAPI_ACCESS_READ)) {
- got_folder_error (mfld, _("Could not open folder: Permission denied"));
- return;
- }
-
- prop = e2k_properties_get_prop (results[0].props, PR_DELETED_COUNT_TOTAL);
- if (prop)
- mfld->deleted_count = atoi (prop);
+ get_folder_online (mfld, TRUE);
}
else {
/* FIXME: need any undo for offline */ ;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]