e_ews_connection_set_folder_permissions (EEwsConnection *cnc,
                                         gint pri,
                                         EwsFolderId *folder_id,
                                         EEwsFolderType folder_type,
                                         const GSList *permissions,
                                         GCancellable *cancellable,
                                         GAsyncReadyCallback callback,
                                         gpointer user_data)
{
	ESoapMessage *msg;
	GSimpleAsyncResult *simple;
	EwsAsyncData *async_data;
	const GSList *iter;

	g_return_if_fail (cnc != NULL);
	g_return_if_fail (folder_id != NULL);
	g_return_if_fail (permissions != NULL);

	msg = e_ews_message_new_with_header (
			cnc->priv->settings,
			cnc->priv->uri,
			cnc->priv->impersonate_user,
			"UpdateFolder",
			NULL,
			NULL,
			cnc->priv->version,
			E_EWS_EXCHANGE_2007_SP1,
			FALSE,
			TRUE);

	e_soap_message_start_element (msg, "FolderChanges", "messages", NULL);
	e_ews_message_start_folder_change (msg, cnc->priv->email, folder_id);

	e_soap_message_start_element (msg, "SetFolderField", NULL, NULL);
	e_ews_message_write_string_parameter_with_attribute (msg, "FieldURI", NULL, NULL, "FieldURI", "folder:PermissionSet");

	switch (folder_type) {
	default:
	case E_EWS_FOLDER_TYPE_MAILBOX:
		e_soap_message_start_element (msg, "Folder", NULL, NULL);
		break;
	case E_EWS_FOLDER_TYPE_CALENDAR:
		e_soap_message_start_element (msg, "CalendarFolder", NULL, NULL);
		break;
	case E_EWS_FOLDER_TYPE_CONTACTS:
		e_soap_message_start_element (msg, "ContactsFolder", NULL, NULL);
		break;
	case E_EWS_FOLDER_TYPE_SEARCH:
		e_soap_message_start_element (msg, "SearchFolder", NULL, NULL);
		break;
	case E_EWS_FOLDER_TYPE_TASKS:
		e_soap_message_start_element (msg, "TasksFolder", NULL, NULL);
		break;
	}

	e_soap_message_start_element (msg, "PermissionSet", NULL, NULL);
	if (folder_type == E_EWS_FOLDER_TYPE_CALENDAR)
		e_soap_message_start_element (msg, "CalendarPermissions", NULL, NULL);
	else
		e_soap_message_start_element (msg, "Permissions", NULL, NULL);

	for (iter = permissions; iter; iter = iter->next) {
		EEwsPermission *perm = iter->data;
		const gchar *perm_level_name;

		if (!perm)
			continue;

		if (folder_type == E_EWS_FOLDER_TYPE_CALENDAR)
			e_soap_message_start_element (msg, "CalendarPermission", NULL, NULL);
		else
			e_soap_message_start_element (msg, "Permission", NULL, NULL);

		e_soap_message_start_element (msg, "UserId", NULL, NULL);

		switch (perm->user_type) {
		case E_EWS_PERMISSION_USER_TYPE_NONE:
			g_return_if_reached ();
			break;
		case E_EWS_PERMISSION_USER_TYPE_ANONYMOUS:
			e_ews_message_write_string_parameter (msg, "DistinguishedUser", NULL, "Anonymous");
			break;
		case E_EWS_PERMISSION_USER_TYPE_DEFAULT:
			e_ews_message_write_string_parameter (msg, "DistinguishedUser", NULL, "Default");
			break;
		case E_EWS_PERMISSION_USER_TYPE_REGULAR:
			e_ews_message_write_string_parameter (msg, "PrimarySmtpAddress", NULL, perm->primary_smtp);
			break;
		}

		e_soap_message_end_element (msg); /* UserId */

		e_ews_permission_rights_to_level_name (perm->rights);

		perm_level_name = e_ews_permission_rights_to_level_name (perm->rights);

		if (g_strcmp0 (perm_level_name, "Custom") == 0) {
			e_ews_message_write_string_parameter (
				msg, "CanCreateItems", NULL,
				(perm->rights & E_EWS_PERMISSION_BIT_CREATE) != 0 ? "true" : "false");
			e_ews_message_write_string_parameter (
				msg, "CanCreateSubFolders", NULL,
				(perm->rights & E_EWS_PERMISSION_BIT_CREATE_SUBFOLDER) != 0 ? "true" : "false");
			e_ews_message_write_string_parameter (
				msg, "IsFolderOwner", NULL,
				(perm->rights & E_EWS_PERMISSION_BIT_FOLDER_OWNER) != 0 ? "true" : "false");
			e_ews_message_write_string_parameter (
				msg, "IsFolderVisible", NULL,
				(perm->rights & E_EWS_PERMISSION_BIT_FOLDER_VISIBLE) != 0 ? "true" : "false");
			e_ews_message_write_string_parameter (
				msg, "IsFolderContact", NULL,
				(perm->rights & E_EWS_PERMISSION_BIT_FOLDER_CONTACT) != 0 ? "true" : "false");
			e_ews_message_write_string_parameter (
				msg, "EditItems", NULL,
				(perm->rights & E_EWS_PERMISSION_BIT_EDIT_ANY) != 0 ? "All" :
				(perm->rights & E_EWS_PERMISSION_BIT_EDIT_OWNED) != 0 ? "Owned" : "None");
			e_ews_message_write_string_parameter (
				msg, "DeleteItems", NULL,
				(perm->rights & E_EWS_PERMISSION_BIT_DELETE_ANY) != 0 ? "All" :
				(perm->rights & E_EWS_PERMISSION_BIT_DELETE_OWNED) != 0 ? "Owned" : "None");
			if (folder_type == E_EWS_FOLDER_TYPE_CALENDAR)
				e_ews_message_write_string_parameter (
					msg, "ReadItems", NULL,
					(perm->rights & E_EWS_PERMISSION_BIT_READ_ANY) != 0 ? "FullDetails" :
					(perm->rights & E_EWS_PERMISSION_BIT_FREE_BUSY_DETAILED) != 0 ? "TimeAndSubjectAndLocation" :
					(perm->rights & E_EWS_PERMISSION_BIT_FREE_BUSY_SIMPLE) != 0 ? "TimeOnly" : "None");
			else
				e_ews_message_write_string_parameter (
					msg, "ReadItems", NULL,
					(perm->rights & E_EWS_PERMISSION_BIT_READ_ANY) != 0 ? "FullDetails" : "None");
		}

		e_ews_message_write_string_parameter (
			msg,
			folder_type == E_EWS_FOLDER_TYPE_CALENDAR ? "CalendarPermissionLevel" : "PermissionLevel", NULL,
			perm_level_name);

		e_soap_message_end_element (msg); /* Permission/CalendarPermission */
	}

	e_soap_message_end_element (msg); /* Permissions */
	e_soap_message_end_element (msg); /* PermissionSet */
	e_soap_message_end_element (msg); /* Folder/CalendarFolder/... */
	e_soap_message_end_element (msg); /* SetFolderField */

	e_ews_message_end_item_change (msg);

	e_ews_message_write_footer (msg);

	simple = g_simple_async_result_new (
		G_OBJECT (cnc), callback, user_data,
		e_ews_connection_set_folder_permissions);

	async_data = g_new0 (EwsAsyncData, 1);
	g_simple_async_result_set_op_res_gpointer (
		simple, async_data, (GDestroyNotify) async_data_free);

	e_ews_connection_queue_request (
		cnc, msg, update_folder_response_cb,
		pri, cancellable, simple);

	g_object_unref (simple);
}