[evolution-mapi] Bug #601483 - Support for quota message service



commit 3e7de4893a369282903bcd3e86f57f22b0c281f5
Author: Milan Crha <mcrha redhat com>
Date:   Wed Feb 1 20:36:10 2012 +0100

    Bug #601483 - Support for quota message service

 src/camel/camel-mapi-folder.c           |   50 +++++++++++
 src/camel/camel-mapi-store.c            |   35 ++++++++-
 src/libexchangemapi/e-mapi-connection.c |  136 ++++++++++++++++++++++++++++---
 src/libexchangemapi/e-mapi-connection.h |    8 ++
 4 files changed, 218 insertions(+), 11 deletions(-)
---
diff --git a/src/camel/camel-mapi-folder.c b/src/camel/camel-mapi-folder.c
index 819475c..b9c3330 100644
--- a/src/camel/camel-mapi-folder.c
+++ b/src/camel/camel-mapi-folder.c
@@ -1855,6 +1855,55 @@ mapi_folder_transfer_messages_to_sync (CamelFolder *source,
 	return success;
 }
 
+static CamelFolderQuotaInfo *
+mapi_folder_get_quota_info_sync (CamelFolder *folder,
+				 GCancellable *cancellable,
+				 GError **error)
+{
+	CamelMapiStore *mapi_store;
+	CamelFolderQuotaInfo *quota_info = NULL;
+	EMapiConnection *conn;
+	uint64_t current_size = -1, receive_quota = -1, send_quota = -1;
+
+	g_return_val_if_fail (folder != NULL, NULL);
+	g_return_val_if_fail (CAMEL_IS_MAPI_FOLDER (folder), NULL);
+
+	mapi_store = CAMEL_MAPI_STORE (camel_folder_get_parent_store (folder));
+	g_return_val_if_fail (mapi_store != NULL, NULL);
+	
+	/* check for offline operation */
+	if (!camel_offline_store_get_online (CAMEL_OFFLINE_STORE (mapi_store)))
+		return NULL;
+
+	conn = camel_mapi_store_get_connection (mapi_store);
+	if (conn && e_mapi_connection_get_store_quotas (
+		conn, NULL,
+		&current_size, &receive_quota, &send_quota,
+		cancellable, error)) {
+		if (current_size != -1) {
+			if (receive_quota != -1) {
+				quota_info = camel_folder_quota_info_new (_("Receive quota"), current_size, receive_quota);
+			}
+
+			if (send_quota != -1) {
+				CamelFolderQuotaInfo *qi;
+
+				qi = camel_folder_quota_info_new (_("Send quota"), current_size, send_quota);
+				if (quota_info)
+					quota_info->next = qi;
+				else
+					quota_info = qi;
+			}
+		}
+	}
+
+	if (!quota_info)
+		g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+			_("No quota information available"));
+
+	return quota_info;
+}
+
 static void
 camel_mapi_folder_class_init (CamelMapiFolderClass *class)
 {
@@ -1881,6 +1930,7 @@ camel_mapi_folder_class_init (CamelMapiFolderClass *class)
 	folder_class->refresh_info_sync = mapi_folder_refresh_info_sync;
 	folder_class->synchronize_sync = mapi_folder_synchronize_sync;
 	folder_class->transfer_messages_to_sync = mapi_folder_transfer_messages_to_sync;
+	folder_class->get_quota_info_sync = mapi_folder_get_quota_info_sync;
 }
 
 static void
diff --git a/src/camel/camel-mapi-store.c b/src/camel/camel-mapi-store.c
index 826ddbe..62f1815 100644
--- a/src/camel/camel-mapi-store.c
+++ b/src/camel/camel-mapi-store.c
@@ -2042,6 +2042,7 @@ mapi_connect_sync (CamelService *service,
 	CamelMapiStore *store = CAMEL_MAPI_STORE (service);
 	CamelServiceConnectionStatus status;
 	CamelSession *session;
+	uint64_t current_size = -1, receive_quota = -1, send_quota = -1;
 	gchar *name;
 
 	if (!camel_offline_store_get_online (CAMEL_OFFLINE_STORE (store))) {
@@ -2066,12 +2067,12 @@ mapi_connect_sync (CamelService *service,
 
 	name = camel_service_get_name (service, TRUE);
 	camel_operation_push_message (cancellable, _("Connecting to '%s'"), name);
-	g_free (name);
 
 	if (!camel_session_authenticate_sync (session, service, NULL, cancellable, error)) {
 		camel_operation_pop_message (cancellable);
 		camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 		camel_service_disconnect_sync (service, TRUE, NULL);
+		g_free (name);
 		return FALSE;
 	}
 
@@ -2082,6 +2083,38 @@ mapi_connect_sync (CamelService *service,
 
 	camel_store_summary_save (store->summary);
 
+	if (e_mapi_connection_get_store_quotas (
+		store->priv->conn, NULL,
+		&current_size, &receive_quota, &send_quota,
+		cancellable, NULL)) {
+
+		if (current_size != -1) {
+			gchar *msg = NULL;
+
+			/* warn/alert when the last 1% lefts from the size quota */
+			if (send_quota != -1 && current_size * 0.95 >= send_quota) {
+				if (send_quota != -1 && current_size >= send_quota) {
+					msg = g_strdup_printf (_("Mailbox '%s' is full, no new messages will be received or sent."), name);
+				} else {
+					msg = g_strdup_printf (_("Mailbox '%s' is near its size limit, message send will be disabled soon."), name);
+				}
+			} else if (receive_quota != -1 && current_size * 0.95 >= receive_quota) {
+				if (current_size >= receive_quota) {
+					msg = g_strdup_printf (_("Mailbox '%s' is full, no new messages will be received."), name);
+				} else {
+					msg = g_strdup_printf (_("Mailbox '%s' is near its size limit."), name);
+				}
+			}
+
+			if (msg) {
+				camel_session_alert_user (session, CAMEL_SESSION_ALERT_WARNING, msg, NULL);
+				g_free (msg);
+			}
+		}
+	}
+
+	g_free (name);
+
 	camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 
 	return TRUE;
diff --git a/src/libexchangemapi/e-mapi-connection.c b/src/libexchangemapi/e-mapi-connection.c
index 3063e53..6e42c3b 100644
--- a/src/libexchangemapi/e-mapi-connection.c
+++ b/src/libexchangemapi/e-mapi-connection.c
@@ -130,6 +130,7 @@ make_mapi_error (GError **perror, const gchar *context, enum MAPISTATUS mapi_sta
 	err (MAPI_E_END_OF_SESSION,			_("End of session"));
 	err (MAPI_E_NOT_INITIALIZED,			_("MAPI is not initialized or connected"));
 	err (MAPI_E_NO_ACCESS,				_("Permission denied"));
+	err (ecShutoffQuotaExceeded,			_("Mailbox quota exceeded"));
 
 	#undef err
 
@@ -891,6 +892,105 @@ e_mapi_connection_peek_store (EMapiConnection *conn,
 	return TRUE;
 }
 
+/* sets quotas and current_size to -1 when not available, but still can return TRUE */
+gboolean
+e_mapi_connection_get_store_quotas (EMapiConnection *conn,
+				    mapi_object_t *obj_store, /* can be NULL, for mailbox store */
+				    uint64_t *current_size, /* out */
+				    uint64_t *receive_quota, /* out */
+				    uint64_t *send_quota, /* out */
+				    GCancellable *cancellable,
+				    GError **perror)
+{
+	enum MAPISTATUS ms = MAPI_E_RESERVED;
+	TALLOC_CTX *mem_ctx;
+	struct SPropTagArray *spropTagArray = NULL;
+	struct SPropValue *lpProps = NULL;
+	mapi_object_t *use_store;
+
+	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (current_size != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (receive_quota != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (send_quota != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+
+	use_store = obj_store;
+	if (!use_store)
+		use_store = &priv->msg_store;
+
+	*current_size = -1;
+	*receive_quota = -1;
+	*send_quota = -1;
+
+	LOCK ();
+	mem_ctx = talloc_new (priv->session);
+
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+		ms = MAPI_E_USER_CANCEL;
+		goto cleanup;
+	}
+
+	spropTagArray = set_SPropTagArray (mem_ctx, 4,
+		PidTagMessageSize,
+		PidTagMessageSizeExtended,
+		PidTagProhibitReceiveQuota,
+		PidTagProhibitSendQuota);
+
+	if (spropTagArray && spropTagArray->cValues) {
+		uint32_t prop_count = 0;
+		const uint32_t *pmessage_size, *preceive_quota, *psend_quota;
+		const uint64_t *pmessage_size_ex;
+
+		ms = GetProps (use_store, MAPI_PROPS_SKIP_NAMEDID_CHECK | MAPI_UNICODE, spropTagArray, &lpProps, &prop_count);
+		if (ms != MAPI_E_SUCCESS) {
+			make_mapi_error (perror, "GetProps", ms);
+			goto cleanup;
+		} else if (!lpProps) {
+			ms = MAPI_E_CALL_FAILED;
+			make_mapi_error (perror, "GetProps", ms);
+			goto cleanup;
+		}
+
+		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+			ms = MAPI_E_USER_CANCEL;
+			goto cleanup;
+		}
+
+		pmessage_size = e_mapi_util_find_SPropVal_array_propval (lpProps, PidTagMessageSize);
+		pmessage_size_ex = e_mapi_util_find_SPropVal_array_propval (lpProps, PidTagMessageSizeExtended);
+		preceive_quota = e_mapi_util_find_SPropVal_array_propval (lpProps, PidTagProhibitReceiveQuota);
+		psend_quota = e_mapi_util_find_SPropVal_array_propval (lpProps, PidTagProhibitSendQuota);
+
+		if (pmessage_size && *pmessage_size != -1)
+			*current_size = *pmessage_size;
+		else if (pmessage_size_ex && *pmessage_size_ex)
+			*current_size = *pmessage_size_ex;
+
+		if (*current_size != -1) {
+			if (preceive_quota && *preceive_quota != -1) {
+				*receive_quota = *preceive_quota;
+				*receive_quota *= 1024;
+			}
+
+			if (psend_quota && *psend_quota != -1) {
+				*send_quota = *psend_quota;
+				*send_quota *= 1024;
+			}
+		}
+	} else {
+		ms = MAPI_E_NOT_ENOUGH_RESOURCES;
+		make_mapi_error (perror, "set_SPropTagArray", ms);
+	}
+
+ cleanup:
+	talloc_free (spropTagArray);
+	talloc_free (lpProps);
+	talloc_free (mem_ctx);
+	UNLOCK();
+
+	return ms == MAPI_E_SUCCESS;
+}
+
 gboolean
 e_mapi_connection_open_default_folder (EMapiConnection *conn,
 				       uint32_t olFolderIdentifier,
@@ -1140,6 +1240,7 @@ e_mapi_connection_get_folder_properties (EMapiConnection *conn,
 	TALLOC_CTX *mem_ctx;
 	struct SPropTagArray *spropTagArray = NULL;
 	struct mapi_SPropValue_array *properties = NULL;
+	struct SPropValue *lpProps = NULL;
 	gboolean res = FALSE;
 
 	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
@@ -1165,14 +1266,11 @@ e_mapi_connection_get_folder_properties (EMapiConnection *conn,
 
 	properties = talloc_zero (mem_ctx, struct mapi_SPropValue_array);
 	if (spropTagArray && spropTagArray->cValues) {
-		struct SPropValue *lpProps;
 		uint32_t prop_count = 0, k, ll;
 		EResolveNamedIDsData *named_ids_list = NULL;
 		guint named_ids_len = 0;
 		GHashTable *replace_hash = NULL;
 
-		lpProps = talloc_zero (mem_ctx, struct SPropValue);
-
 		for (k = 0; k < spropTagArray->cValues; k++) {
 			uint32_t proptag = spropTagArray->aulPropTag[k];
 
@@ -1217,6 +1315,11 @@ e_mapi_connection_get_folder_properties (EMapiConnection *conn,
 			make_mapi_error (perror, "GetProps", ms);
 			g_free (named_ids_list);
 			goto cleanup;
+		} else if (!lpProps) {
+			ms = MAPI_E_CALL_FAILED;
+			make_mapi_error (perror, "GetProps", ms);
+			g_free (named_ids_list);
+			goto cleanup;
 		}
 
 		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
@@ -1263,6 +1366,7 @@ e_mapi_connection_get_folder_properties (EMapiConnection *conn,
  cleanup:
 	talloc_free (spropTagArray);
 	talloc_free (properties);
+	talloc_free (lpProps);
 	talloc_free (mem_ctx);
 	UNLOCK();
 
@@ -2895,6 +2999,8 @@ e_mapi_connection_transfer_summary (EMapiConnection *conn,
 							ms = MAPI_E_USER_CANCEL;
 							e_mapi_object_free (object);
 							mapi_object_release (&obj_message);
+							talloc_free (lpProps);
+							talloc_free (tags);
 							goto cleanup;
 						}
 
@@ -2917,11 +3023,14 @@ e_mapi_connection_transfer_summary (EMapiConnection *conn,
 				if (ms != MAPI_E_SUCCESS) {
 					make_mapi_error (perror, "transfer_object", ms);
 					mapi_object_release (&obj_message);
+					talloc_free (lpProps);
+					talloc_free (tags);
 					goto cleanup;
 				}
 			}
 
 			mapi_object_release (&obj_message);
+			talloc_free (lpProps);
 			talloc_free (tags);
 		}
 
@@ -5522,7 +5631,7 @@ mapi_get_ren_additional_fids (TALLOC_CTX *mem_ctx,
 	mapi_id_t inbox_id, fid;
 	mapi_object_t obj_folder_inbox;
 	struct SPropTagArray *SPropTagArray;
-	struct SPropValue *lpProps;
+	struct SPropValue *lpProps = NULL;
 	struct SRow aRow;
 	const struct BinaryArray_r *entryids;
 	struct Binary_r entryid;
@@ -5569,11 +5678,14 @@ mapi_get_ren_additional_fids (TALLOC_CTX *mem_ctx,
 	/* GetProps on Inbox for PR_ADDITIONAL_REN_ENTRYIDS */
 	SPropTagArray = set_SPropTagArray(mem_ctx, 0x1, PR_ADDITIONAL_REN_ENTRYIDS);
 
-	lpProps = talloc_zero(mem_ctx, struct SPropValue);
 	ms = GetProps (&obj_folder_inbox, MAPI_PROPS_SKIP_NAMEDID_CHECK | MAPI_UNICODE, SPropTagArray, &lpProps, &count);
 	if (ms != MAPI_E_SUCCESS) {
 		make_mapi_error (perror, "GetProps", ms);
 		goto cleanup;
+	} else if (!lpProps) {
+		ms = MAPI_E_CALL_FAILED;
+		make_mapi_error (perror, "GetProps", ms);
+		goto cleanup;
 	}
 
 	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
@@ -5608,6 +5720,7 @@ mapi_get_ren_additional_fids (TALLOC_CTX *mem_ctx,
 
  cleanup:
 	mapi_object_release (&obj_folder_inbox);
+	talloc_free (lpProps);
 
 	return ms == MAPI_E_SUCCESS;
 }
@@ -5679,8 +5792,8 @@ e_mapi_connection_get_folders_list (EMapiConnection *conn,
 {
 	enum MAPISTATUS	ms;
 	TALLOC_CTX		*mem_ctx;
-	struct SPropTagArray	*SPropTagArray;
-	struct SPropValue	*lpProps;
+	struct SPropTagArray	*SPropTagArray = NULL;
+	struct SPropValue	*lpProps = NULL;
 	struct SRow		aRow;
 	gboolean		result = FALSE;
 	mapi_id_t		mailbox_id;
@@ -5712,13 +5825,14 @@ e_mapi_connection_get_folders_list (EMapiConnection *conn,
 		goto cleanup;
 	}
 
-	lpProps = talloc_zero(mem_ctx, struct SPropValue);
 	ms = GetProps (&priv->msg_store, MAPI_PROPS_SKIP_NAMEDID_CHECK | MAPI_UNICODE, SPropTagArray, &lpProps, &count);
-	talloc_free (SPropTagArray);
-
 	if (ms != MAPI_E_SUCCESS) {
 		make_mapi_error (perror, "GetProps", ms);
 		goto cleanup;
+	} else if (!lpProps) {
+		ms = MAPI_E_CALL_FAILED;
+		make_mapi_error (perror, "GetProps", ms);
+		goto cleanup;
 	}
 
 	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
@@ -5771,6 +5885,8 @@ e_mapi_connection_get_folders_list (EMapiConnection *conn,
 	g_slist_foreach (*mapi_folders, (GFunc) set_user_name, (gpointer) mailbox_user_name);
 
  cleanup:
+	talloc_free (SPropTagArray);
+	talloc_free (lpProps);
 	talloc_free (mem_ctx);
 
 	UNLOCK ();
diff --git a/src/libexchangemapi/e-mapi-connection.h b/src/libexchangemapi/e-mapi-connection.h
index 6c03899..a32e2e7 100644
--- a/src/libexchangemapi/e-mapi-connection.h
+++ b/src/libexchangemapi/e-mapi-connection.h
@@ -229,6 +229,14 @@ gboolean		e_mapi_connection_peek_store		(EMapiConnection *conn,
 								 GCancellable *cancellable,
 								 GError **perror);
 
+gboolean		e_mapi_connection_get_store_quotas	(EMapiConnection *conn,
+								 mapi_object_t *obj_store, /* can be NULL */
+								 uint64_t *current_size, /* out */
+								 uint64_t *receive_quota, /* out */
+								 uint64_t *send_quota, /* out */
+								 GCancellable *cancellable,
+								 GError **perror);
+
 gboolean		e_mapi_connection_open_default_folder	(EMapiConnection *conn,
 								 uint32_t olFolderIdentifier,
 								 mapi_object_t *obj_folder, /* out */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]