summaryrefslogtreecommitdiffstats
path: root/comm/mailnews/db/msgdb/src/nsMsgOfflineImapOperation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mailnews/db/msgdb/src/nsMsgOfflineImapOperation.cpp')
-rw-r--r--comm/mailnews/db/msgdb/src/nsMsgOfflineImapOperation.cpp385
1 files changed, 385 insertions, 0 deletions
diff --git a/comm/mailnews/db/msgdb/src/nsMsgOfflineImapOperation.cpp b/comm/mailnews/db/msgdb/src/nsMsgOfflineImapOperation.cpp
new file mode 100644
index 0000000000..96410654d8
--- /dev/null
+++ b/comm/mailnews/db/msgdb/src/nsMsgOfflineImapOperation.cpp
@@ -0,0 +1,385 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "msgCore.h"
+#include "nsMsgOfflineImapOperation.h"
+#include "nsMsgUtils.h"
+#include "mozilla/Logging.h"
+
+using namespace mozilla;
+
+LazyLogModule IMAPOffline("IMAPOffline");
+
+/* Implementation file */
+NS_IMPL_ISUPPORTS(nsMsgOfflineImapOperation, nsIMsgOfflineImapOperation)
+
+// property names for offine imap operation fields.
+#define PROP_OPERATION "op"
+#define PROP_OPERATION_FLAGS "opFlags"
+#define PROP_NEW_FLAGS "newFlags"
+#define PROP_MESSAGE_KEY "msgKey"
+#define PROP_SRC_MESSAGE_KEY "srcMsgKey"
+#define PROP_SRC_FOLDER_URI "srcFolderURI"
+#define PROP_MOVE_DEST_FOLDER_URI "moveDest"
+#define PROP_NUM_COPY_DESTS "numCopyDests"
+#define PROP_COPY_DESTS \
+ "copyDests" // how to delimit these? Or should we do the "dest1","dest2" etc
+ // trick? But then we'd need to shuffle them around since we
+ // delete off the front first.
+#define PROP_KEYWORD_ADD "addedKeywords"
+#define PROP_KEYWORD_REMOVE "removedKeywords"
+#define PROP_MSG_SIZE "msgSize"
+#define PROP_PLAYINGBACK "inPlayback"
+
+nsMsgOfflineImapOperation::nsMsgOfflineImapOperation(nsMsgDatabase* db,
+ nsIMdbRow* row) {
+ NS_ASSERTION(db, "can't have null db");
+ NS_ASSERTION(row, "can't have null row");
+ m_operation = 0;
+ m_operationFlags = 0;
+ m_messageKey = nsMsgKey_None;
+ m_sourceMessageKey = nsMsgKey_None;
+ m_mdb = db;
+ NS_ADDREF(m_mdb);
+ m_mdbRow = row;
+ m_newFlags = 0;
+ m_mdb->GetUint32Property(m_mdbRow, PROP_OPERATION, (uint32_t*)&m_operation,
+ 0);
+ m_mdb->GetUint32Property(m_mdbRow, PROP_MESSAGE_KEY, &m_messageKey, 0);
+ m_mdb->GetUint32Property(m_mdbRow, PROP_OPERATION_FLAGS, &m_operationFlags,
+ 0);
+ m_mdb->GetUint32Property(m_mdbRow, PROP_NEW_FLAGS, (uint32_t*)&m_newFlags, 0);
+}
+
+nsMsgOfflineImapOperation::~nsMsgOfflineImapOperation() {
+ // clear the row first, in case we're holding the last reference
+ // to the db.
+ m_mdbRow = nullptr;
+ NS_IF_RELEASE(m_mdb);
+}
+
+/* attribute nsOfflineImapOperationType operation; */
+NS_IMETHODIMP nsMsgOfflineImapOperation::GetOperation(
+ nsOfflineImapOperationType* aOperation) {
+ NS_ENSURE_ARG(aOperation);
+ *aOperation = m_operation;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgOfflineImapOperation::SetOperation(
+ nsOfflineImapOperationType aOperation) {
+ if (MOZ_LOG_TEST(IMAPOffline, LogLevel::Info))
+ MOZ_LOG(IMAPOffline, LogLevel::Info,
+ ("msg id %x setOperation was %x add %x", m_messageKey, m_operation,
+ aOperation));
+
+ m_operation |= aOperation;
+ return m_mdb->SetUint32Property(m_mdbRow, PROP_OPERATION, m_operation);
+}
+
+/* void clearOperation (in nsOfflineImapOperationType operation); */
+NS_IMETHODIMP nsMsgOfflineImapOperation::ClearOperation(
+ nsOfflineImapOperationType aOperation) {
+ if (MOZ_LOG_TEST(IMAPOffline, LogLevel::Info))
+ MOZ_LOG(IMAPOffline, LogLevel::Info,
+ ("msg id %x clearOperation was %x clear %x", m_messageKey,
+ m_operation, aOperation));
+ m_operation &= ~aOperation;
+ switch (aOperation) {
+ case kMsgMoved:
+ case kAppendTemplate:
+ case kAppendDraft:
+ m_moveDestination.Truncate();
+ break;
+ case kMsgCopy:
+ m_copyDestinations.RemoveElementAt(0);
+ break;
+ }
+ return m_mdb->SetUint32Property(m_mdbRow, PROP_OPERATION, m_operation);
+}
+
+/* attribute nsMsgKey messageKey; */
+NS_IMETHODIMP nsMsgOfflineImapOperation::GetMessageKey(nsMsgKey* aMessageKey) {
+ NS_ENSURE_ARG(aMessageKey);
+ *aMessageKey = m_messageKey;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgOfflineImapOperation::SetMessageKey(nsMsgKey aMessageKey) {
+ m_messageKey = aMessageKey;
+ return m_mdb->SetUint32Property(m_mdbRow, PROP_MESSAGE_KEY, m_messageKey);
+}
+
+/* attribute nsMsgKey srcMessageKey; */
+NS_IMETHODIMP nsMsgOfflineImapOperation::GetSrcMessageKey(
+ nsMsgKey* aMessageKey) {
+ NS_ENSURE_ARG(aMessageKey);
+ return m_mdb->GetUint32Property(m_mdbRow, PROP_SRC_MESSAGE_KEY, aMessageKey,
+ nsMsgKey_None);
+}
+
+NS_IMETHODIMP nsMsgOfflineImapOperation::SetSrcMessageKey(
+ nsMsgKey aMessageKey) {
+ m_messageKey = aMessageKey;
+ return m_mdb->SetUint32Property(m_mdbRow, PROP_SRC_MESSAGE_KEY, m_messageKey);
+}
+
+/* attribute imapMessageFlagsType flagOperation; */
+NS_IMETHODIMP nsMsgOfflineImapOperation::GetFlagOperation(
+ imapMessageFlagsType* aFlagOperation) {
+ NS_ENSURE_ARG(aFlagOperation);
+ *aFlagOperation = m_operationFlags;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgOfflineImapOperation::SetFlagOperation(
+ imapMessageFlagsType aFlagOperation) {
+ if (MOZ_LOG_TEST(IMAPOffline, LogLevel::Info))
+ MOZ_LOG(IMAPOffline, LogLevel::Info,
+ ("msg id %x setFlagOperation was %x add %x", m_messageKey,
+ m_operationFlags, aFlagOperation));
+ SetOperation(kFlagsChanged);
+ nsresult rv = SetNewFlags(aFlagOperation);
+ NS_ENSURE_SUCCESS(rv, rv);
+ m_operationFlags |= aFlagOperation;
+ return m_mdb->SetUint32Property(m_mdbRow, PROP_OPERATION_FLAGS,
+ m_operationFlags);
+}
+
+/* attribute imapMessageFlagsType flagOperation; */
+NS_IMETHODIMP nsMsgOfflineImapOperation::GetNewFlags(
+ imapMessageFlagsType* aNewFlags) {
+ NS_ENSURE_ARG(aNewFlags);
+ uint32_t flags;
+ nsresult rv = m_mdb->GetUint32Property(m_mdbRow, PROP_NEW_FLAGS, &flags, 0);
+ *aNewFlags = m_newFlags = (imapMessageFlagsType)flags;
+ return rv;
+}
+
+NS_IMETHODIMP nsMsgOfflineImapOperation::SetNewFlags(
+ imapMessageFlagsType aNewFlags) {
+ if (MOZ_LOG_TEST(IMAPOffline, LogLevel::Info) && m_newFlags != aNewFlags)
+ MOZ_LOG(IMAPOffline, LogLevel::Info,
+ ("msg id %x SetNewFlags was %x to %x", m_messageKey, m_newFlags,
+ aNewFlags));
+ m_newFlags = aNewFlags;
+ return m_mdb->SetUint32Property(m_mdbRow, PROP_NEW_FLAGS, m_newFlags);
+}
+
+/* attribute string destinationFolderURI; */
+NS_IMETHODIMP nsMsgOfflineImapOperation::GetDestinationFolderURI(
+ nsACString& aDestinationFolderURI) {
+ (void)m_mdb->GetProperty(m_mdbRow, PROP_MOVE_DEST_FOLDER_URI,
+ getter_Copies(m_moveDestination));
+ aDestinationFolderURI = m_moveDestination;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgOfflineImapOperation::SetDestinationFolderURI(
+ const nsACString& aDestinationFolderURI) {
+ if (MOZ_LOG_TEST(IMAPOffline, LogLevel::Info))
+ MOZ_LOG(IMAPOffline, LogLevel::Info,
+ ("msg id %x SetDestinationFolderURI to %s", m_messageKey,
+ PromiseFlatCString(aDestinationFolderURI).get()));
+ m_moveDestination = aDestinationFolderURI;
+ return m_mdb->SetProperty(m_mdbRow, PROP_MOVE_DEST_FOLDER_URI,
+ PromiseFlatCString(aDestinationFolderURI).get());
+}
+
+/* attribute string sourceFolderURI; */
+NS_IMETHODIMP nsMsgOfflineImapOperation::GetSourceFolderURI(
+ nsACString& aSourceFolderURI) {
+ nsresult rv = m_mdb->GetProperty(m_mdbRow, PROP_SRC_FOLDER_URI,
+ getter_Copies(m_sourceFolder));
+ aSourceFolderURI = m_sourceFolder;
+ return rv;
+}
+
+NS_IMETHODIMP nsMsgOfflineImapOperation::SetSourceFolderURI(
+ const nsACString& aSourceFolderURI) {
+ m_sourceFolder = aSourceFolderURI;
+ SetOperation(kMoveResult);
+
+ return m_mdb->SetProperty(m_mdbRow, PROP_SRC_FOLDER_URI,
+ PromiseFlatCString(aSourceFolderURI).get());
+}
+
+/* attribute string keyword; */
+NS_IMETHODIMP nsMsgOfflineImapOperation::GetKeywordsToAdd(char** aKeywords) {
+ NS_ENSURE_ARG(aKeywords);
+ nsresult rv = m_mdb->GetProperty(m_mdbRow, PROP_KEYWORD_ADD,
+ getter_Copies(m_keywordsToAdd));
+ *aKeywords = ToNewCString(m_keywordsToAdd);
+ return rv;
+}
+
+NS_IMETHODIMP nsMsgOfflineImapOperation::AddKeywordToAdd(const char* aKeyword) {
+ SetOperation(kAddKeywords);
+ return AddKeyword(aKeyword, m_keywordsToAdd, PROP_KEYWORD_ADD,
+ m_keywordsToRemove, PROP_KEYWORD_REMOVE);
+}
+
+NS_IMETHODIMP nsMsgOfflineImapOperation::GetKeywordsToRemove(char** aKeywords) {
+ NS_ENSURE_ARG(aKeywords);
+ nsresult rv = m_mdb->GetProperty(m_mdbRow, PROP_KEYWORD_REMOVE,
+ getter_Copies(m_keywordsToRemove));
+ *aKeywords = ToNewCString(m_keywordsToRemove);
+ return rv;
+}
+
+nsresult nsMsgOfflineImapOperation::AddKeyword(const char* aKeyword,
+ nsCString& addList,
+ const char* addProp,
+ nsCString& removeList,
+ const char* removeProp) {
+ int32_t startOffset, keywordLength;
+ if (!MsgFindKeyword(nsDependentCString(aKeyword), addList, &startOffset,
+ &keywordLength)) {
+ if (!addList.IsEmpty()) addList.Append(' ');
+ addList.Append(aKeyword);
+ }
+ // if the keyword we're removing was in the list of keywords to add,
+ // cut it from that list.
+ if (MsgFindKeyword(nsDependentCString(aKeyword), removeList, &startOffset,
+ &keywordLength)) {
+ removeList.Cut(startOffset, keywordLength);
+ m_mdb->SetProperty(m_mdbRow, removeProp, removeList.get());
+ }
+ return m_mdb->SetProperty(m_mdbRow, addProp, addList.get());
+}
+
+NS_IMETHODIMP nsMsgOfflineImapOperation::AddKeywordToRemove(
+ const char* aKeyword) {
+ SetOperation(kRemoveKeywords);
+ return AddKeyword(aKeyword, m_keywordsToRemove, PROP_KEYWORD_REMOVE,
+ m_keywordsToAdd, PROP_KEYWORD_ADD);
+}
+
+NS_IMETHODIMP nsMsgOfflineImapOperation::AddMessageCopyOperation(
+ const nsACString& destinationBox) {
+ SetOperation(kMsgCopy);
+ nsresult rv = GetCopiesFromDB();
+ NS_ENSURE_SUCCESS(rv, rv);
+ m_copyDestinations.AppendElement(destinationBox);
+ return SetCopiesToDB();
+}
+
+// we write out the folders as one string, separated by 0x1.
+#define FOLDER_SEP_CHAR '\001'
+
+nsresult nsMsgOfflineImapOperation::GetCopiesFromDB() {
+ nsCString copyDests;
+ m_copyDestinations.Clear();
+ nsresult rv =
+ m_mdb->GetProperty(m_mdbRow, PROP_COPY_DESTS, getter_Copies(copyDests));
+ // use 0x1 as the delimiter between folder names since it's not a legal
+ // character
+ if (NS_SUCCEEDED(rv) && !copyDests.IsEmpty()) {
+ int32_t curCopyDestStart = 0;
+ int32_t nextCopyDestPos = 0;
+
+ while (nextCopyDestPos != -1) {
+ nsCString curDest;
+ nextCopyDestPos = copyDests.FindChar(FOLDER_SEP_CHAR, curCopyDestStart);
+ if (nextCopyDestPos > 0)
+ curDest = Substring(copyDests, curCopyDestStart,
+ nextCopyDestPos - curCopyDestStart);
+ else
+ curDest = Substring(copyDests, curCopyDestStart,
+ copyDests.Length() - curCopyDestStart);
+ curCopyDestStart = nextCopyDestPos + 1;
+ m_copyDestinations.AppendElement(curDest);
+ }
+ }
+ return rv;
+}
+
+nsresult nsMsgOfflineImapOperation::SetCopiesToDB() {
+ nsAutoCString copyDests;
+
+ // use 0x1 as the delimiter between folders
+ for (uint32_t i = 0; i < m_copyDestinations.Length(); i++) {
+ if (i > 0) copyDests.Append(FOLDER_SEP_CHAR);
+ copyDests.Append(m_copyDestinations.ElementAt(i));
+ }
+ return m_mdb->SetProperty(m_mdbRow, PROP_COPY_DESTS, copyDests.get());
+}
+
+/* attribute long numberOfCopies; */
+NS_IMETHODIMP nsMsgOfflineImapOperation::GetNumberOfCopies(
+ int32_t* aNumberOfCopies) {
+ NS_ENSURE_ARG(aNumberOfCopies);
+ nsresult rv = GetCopiesFromDB();
+ NS_ENSURE_SUCCESS(rv, rv);
+ *aNumberOfCopies = m_copyDestinations.Length();
+ return NS_OK;
+}
+
+/* string getCopyDestination (in long copyIndex); */
+NS_IMETHODIMP nsMsgOfflineImapOperation::GetCopyDestination(int32_t copyIndex,
+ char** retval) {
+ NS_ENSURE_ARG(retval);
+ nsresult rv = GetCopiesFromDB();
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (copyIndex >= (int32_t)m_copyDestinations.Length())
+ return NS_ERROR_ILLEGAL_VALUE;
+ *retval = ToNewCString(m_copyDestinations.ElementAt(copyIndex));
+ return (*retval) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/* attribute unsigned log msgSize; */
+NS_IMETHODIMP nsMsgOfflineImapOperation::GetMsgSize(uint32_t* aMsgSize) {
+ NS_ENSURE_ARG(aMsgSize);
+ return m_mdb->GetUint32Property(m_mdbRow, PROP_MSG_SIZE, aMsgSize, 0);
+}
+
+NS_IMETHODIMP nsMsgOfflineImapOperation::SetMsgSize(uint32_t aMsgSize) {
+ return m_mdb->SetUint32Property(m_mdbRow, PROP_MSG_SIZE, aMsgSize);
+}
+
+NS_IMETHODIMP nsMsgOfflineImapOperation::SetPlayingBack(bool aPlayingBack) {
+ return m_mdb->SetBooleanProperty(m_mdbRow, PROP_PLAYINGBACK, aPlayingBack);
+}
+
+NS_IMETHODIMP nsMsgOfflineImapOperation::GetPlayingBack(bool* aPlayingBack) {
+ NS_ENSURE_ARG(aPlayingBack);
+ return m_mdb->GetBooleanProperty(m_mdbRow, PROP_PLAYINGBACK, aPlayingBack);
+}
+
+void nsMsgOfflineImapOperation::Log() {
+ if (!MOZ_LOG_TEST(IMAPOffline, LogLevel::Info)) return;
+ // const long kMoveResult = 0x8;
+ // const long kAppendDraft = 0x10;
+ // const long kAddedHeader = 0x20;
+ // const long kDeletedMsg = 0x40;
+ // const long kMsgMarkedDeleted = 0x80;
+ // const long kAppendTemplate = 0x100;
+ // const long kDeleteAllMsgs = 0x200;
+ if (m_operation & nsIMsgOfflineImapOperation::kFlagsChanged)
+ MOZ_LOG(IMAPOffline, LogLevel::Info,
+ ("msg id %x changeFlag:%x", m_messageKey, m_newFlags));
+ if (m_operation & nsIMsgOfflineImapOperation::kMsgMoved) {
+ nsCString moveDestFolder;
+ GetDestinationFolderURI(moveDestFolder);
+ MOZ_LOG(IMAPOffline, LogLevel::Info,
+ ("msg id %x moveTo:%s", m_messageKey, moveDestFolder.get()));
+ }
+ if (m_operation & nsIMsgOfflineImapOperation::kMsgCopy) {
+ nsCString copyDests;
+ m_mdb->GetProperty(m_mdbRow, PROP_COPY_DESTS, getter_Copies(copyDests));
+ MOZ_LOG(IMAPOffline, LogLevel::Info,
+ ("msg id %x moveTo:%s", m_messageKey, copyDests.get()));
+ }
+ if (m_operation & nsIMsgOfflineImapOperation::kAppendDraft)
+ MOZ_LOG(IMAPOffline, LogLevel::Info,
+ ("msg id %x append draft", m_messageKey));
+ if (m_operation & nsIMsgOfflineImapOperation::kAddKeywords)
+ MOZ_LOG(IMAPOffline, LogLevel::Info,
+ ("msg id %x add keyword:%s", m_messageKey, m_keywordsToAdd.get()));
+ if (m_operation & nsIMsgOfflineImapOperation::kRemoveKeywords)
+ MOZ_LOG(IMAPOffline, LogLevel::Info,
+ ("msg id %x remove keyword:%s", m_messageKey,
+ m_keywordsToRemove.get()));
+}