diff options
author | 2013-03-07 00:40:55 -0800 | |
---|---|---|
committer | 2013-03-07 00:40:55 -0800 | |
commit | 3288fbac4090ecf5ea490ba72e5c3c01a4233e21 (patch) | |
tree | ddbb1a5a7f88380c6d53d662c173d48f67ba9990 /src/core | |
parent | d6c89c5effc7fed91e3ccb129bacc22c5d3c8d38 (diff) |
Implemented QRESYNC. Implemented IndexSet. Implemented CAPABILITY.
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/basetypes/MCBaseTypes.h | 1 | ||||
-rw-r--r-- | src/core/basetypes/MCIndexSet.cpp | 261 | ||||
-rw-r--r-- | src/core/basetypes/MCIndexSet.h | 57 | ||||
-rw-r--r-- | src/core/basetypes/MCRange.cc | 4 | ||||
-rw-r--r-- | src/core/basetypes/MCRange.h | 8 | ||||
-rw-r--r-- | src/core/basetypes/MCString.cc | 18 | ||||
-rw-r--r-- | src/core/imap/MCIMAPMessage.cc | 13 | ||||
-rw-r--r-- | src/core/imap/MCIMAPMessage.h | 4 | ||||
-rw-r--r-- | src/core/imap/MCIMAPSession.cc | 248 | ||||
-rw-r--r-- | src/core/imap/MCIMAPSession.h | 43 | ||||
-rw-r--r-- | src/core/imap/MCIMAPSyncResult.cpp | 46 | ||||
-rw-r--r-- | src/core/imap/MCIMAPSyncResult.h | 38 |
12 files changed, 694 insertions, 47 deletions
diff --git a/src/core/basetypes/MCBaseTypes.h b/src/core/basetypes/MCBaseTypes.h index 84deb42f..d5b12083 100644 --- a/src/core/basetypes/MCBaseTypes.h +++ b/src/core/basetypes/MCBaseTypes.h @@ -15,6 +15,7 @@ #include <mailcore/MCAssert.h> #include <mailcore/MCUtils.h> #include <mailcore/MCRange.h> +#include <mailcore/MCIndexSet.h> #include <mailcore/MCOperation.h> #include <mailcore/MCOperationQueue.h> #include <mailcore/MCOperationCallback.h> diff --git a/src/core/basetypes/MCIndexSet.cpp b/src/core/basetypes/MCIndexSet.cpp new file mode 100644 index 00000000..7fd6cd6d --- /dev/null +++ b/src/core/basetypes/MCIndexSet.cpp @@ -0,0 +1,261 @@ +// +// MCIndexSet.cpp +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/4/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIndexSet.h" + +#include "MCString.h" + +using namespace mailcore; + +void IndexSet::init() +{ + mRanges = NULL; + mAllocated = 0; + mCount = 0; +} + +IndexSet::IndexSet() +{ + init(); +} + +IndexSet::IndexSet(IndexSet * o) +{ + init(); + mRanges = new Range[o->mAllocated]; + for(unsigned int i = 0 ; i < o->mCount ; i ++) { + mRanges[i] = o->mRanges[i]; + } + mAllocated = o->mAllocated; + mCount = o->mCount; +} + +IndexSet::~IndexSet() +{ + removeAllIndexes(); +} + +IndexSet * IndexSet::indexSet() +{ + IndexSet * result = new IndexSet(); + result->autorelease(); + return result; +} + +unsigned int IndexSet::count() +{ + unsigned int total = 0; + for(unsigned int i = 0 ; i < mCount ; i ++) { + total += mRanges[i].length; + } + return total; +} + +int IndexSet::rangeIndexForIndexWithBounds(uint64_t idx, unsigned int left, unsigned int right) +{ + unsigned int middle = (left + right) / 2; + + Range middleRange = mRanges[middle]; + + if (left == right) { + if ((idx >= middleRange.location) && (idx <= middleRange.location + middleRange.length)) { + return left; + } + return -1; + } + + if ((idx >= middleRange.location) && (idx <= middleRange.location + middleRange.length)) { + return middle; + } + if (idx < middleRange.location) { + return rangeIndexForIndexWithBounds(idx, left, middle); + } + else { + return rangeIndexForIndexWithBounds(idx, middle + 1, right); + } +} + +int IndexSet::rangeIndexForIndex(uint64_t idx) +{ + if (mCount == 0) + return -1; + + return rangeIndexForIndexWithBounds(idx, 0, mCount - 1); +} + +int IndexSet::rightRangeIndexForIndexWithBounds(uint64_t idx, unsigned int left, unsigned int right) +{ + unsigned int middle = (left + right) / 2; + + Range middleRange = mRanges[middle]; + + if (left == right) { + if (idx > middleRange.location + middleRange.length) { + return left + 1; + } + else { + return left; + } + } + + if (idx < middleRange.location + middleRange.length) { + return rightRangeIndexForIndexWithBounds(idx, left, middle); + } + else { + return rightRangeIndexForIndexWithBounds(idx, middle + 1, right); + } +} + +int IndexSet::rightRangeIndexForIndex(uint64_t idx) +{ + if (mCount == 0) + return 0; + + return rightRangeIndexForIndexWithBounds(idx, 0, mCount - 1); +} + +void IndexSet::addRangeIndex(unsigned int rangeIndex) +{ + if (mAllocated < mCount + 1) { + while (mAllocated < mCount + 1) { + if (mAllocated == 0) { + mAllocated = 4; + } + mAllocated *= 2; + } + + Range * rangesReplacement = new Range[mAllocated]; + for(unsigned int i = 0 ; i < rangeIndex ; i ++) { + rangesReplacement[i] = mRanges[i]; + } + for(unsigned int i = rangeIndex ; i < mCount ; i ++) { + rangesReplacement[i + 1] = mRanges[i]; + } + rangesReplacement[rangeIndex].location = 0; + rangesReplacement[rangeIndex].length = 0; + delete [] mRanges; + mRanges = rangesReplacement; + } + else { + for(unsigned int i = mCount - 1 ; i >= rangeIndex ; i --) { + mRanges[i + 1] = mRanges[i]; + } + mRanges[rangeIndex].location = 0; + mRanges[rangeIndex].length = 0; + } +} + +void IndexSet::addIndex(uint64_t idx) +{ + int leftRangeIndex; + int rightRangeIndex; + + if (rangeIndexForIndex(idx) != -1) + return; + + leftRangeIndex = rangeIndexForIndex(idx - 1); + rightRangeIndex = rangeIndexForIndex(idx + 1); + + if ((leftRangeIndex == -1) && (rightRangeIndex == -1)) { + rightRangeIndex = rightRangeIndexForIndex(idx); + addRangeIndex(rightRangeIndex); + mRanges[rightRangeIndex].location = idx; + mRanges[rightRangeIndex].length = 0; + } + else if ((leftRangeIndex != -1) && (rightRangeIndex == -1)) { + if (mRanges[leftRangeIndex].location + mRanges[leftRangeIndex].length + 1 == idx) { + mRanges[leftRangeIndex].length ++; + } + } + else if ((leftRangeIndex == -1) && (rightRangeIndex != -1)) { + if (mRanges[rightRangeIndex].location - 1 == idx) { + mRanges[rightRangeIndex].location --; + mRanges[rightRangeIndex].length ++; + } + } +} + +void IndexSet::removeRangeIndex(unsigned int rangeIndex) +{ + for(unsigned int i = rangeIndex + 1 ; i < mCount ; i --) { + mRanges[i - 1] = mRanges[i]; + } + mCount --; +} + +void IndexSet::removeIndex(uint64_t idx) +{ + int rangeIndex = rangeIndexForIndex(idx); + if (rangeIndex == -1) + return; + if (idx == mRanges[rangeIndex].location) { + mRanges[rangeIndex].location ++; + mRanges[rangeIndex].length --; + if (mRanges[rangeIndex].length == 0) { + // remove range. + removeRangeIndex(rangeIndex); + } + } + else if (idx == mRanges[rangeIndex].location + mRanges[rangeIndex].length) { + mRanges[rangeIndex].length --; + if (mRanges[rangeIndex].length == 0) { + // remove range. + removeRangeIndex(rangeIndex); + } + } + else { + // split range. + addRangeIndex(rangeIndex); + mRanges[rangeIndex] = mRanges[rangeIndex + 1]; + uint64_t right = mRanges[rangeIndex].location + mRanges[rangeIndex].length; + mRanges[rangeIndex].location = mRanges[rangeIndex + 1].location; + mRanges[rangeIndex].length = idx - mRanges[rangeIndex].location; + mRanges[rangeIndex + 1].location = idx + 1; + mRanges[rangeIndex + 1].length = right - mRanges[rangeIndex + 1].location; + } +} + +bool IndexSet::containsIndex(uint64_t idx) +{ + int rangeIndex = rangeIndexForIndex(idx); + return rangeIndex != -1; +} + +Range * IndexSet::allRanges() +{ + return mRanges; +} + +void IndexSet::removeAllIndexes() +{ + if (mRanges != NULL) { + delete[] mRanges; + mRanges = NULL; + } + mAllocated = 0; + mCount = 0; +} + +String * IndexSet::description() +{ + String * result = String::string(); + for(unsigned int i = 0 ; i < mCount ; i ++) { + if (i != 0) { + result->appendUTF8Format(","); + } + result->appendUTF8Format("%llu-%llu", + (unsigned long long) mRanges[i].location, + (unsigned long long) (mRanges[i].location + mRanges[i].length)); + } + return result; +} + +Object * IndexSet::copy() +{ + return new IndexSet(this); +} diff --git a/src/core/basetypes/MCIndexSet.h b/src/core/basetypes/MCIndexSet.h new file mode 100644 index 00000000..290b9aaa --- /dev/null +++ b/src/core/basetypes/MCIndexSet.h @@ -0,0 +1,57 @@ +// +// MCIndexSet.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/4/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef __mailcore2__MCIndexSet__ +#define __mailcore2__MCIndexSet__ + +#include <mailcore/MCObject.h> +#include <mailcore/MCRange.h> +#include <inttypes.h> + +#ifdef __cplusplus + +namespace mailcore { + + class IndexSet : public Object { + public: + IndexSet(); + IndexSet(IndexSet * o); + + static IndexSet * indexSet(); + + virtual unsigned int count(); + virtual void addIndex(uint64_t idx); + virtual void removeIndex(uint64_t idx); + virtual bool containsIndex(uint64_t idx); + + virtual Range * allRanges(); + virtual void removeAllIndexes(); + + public: // subclass behavior + virtual ~IndexSet(); + virtual String * description(); + virtual Object * copy(); + + private: + Range * mRanges; + unsigned int mCount; + unsigned int mAllocated; + void init(); + int rangeIndexForIndex(uint64_t idx); + int rangeIndexForIndexWithBounds(uint64_t idx, unsigned int left, unsigned int right); + void addRangeIndex(unsigned int rangeIndex); + void removeRangeIndex(unsigned int rangeIndex); + int rightRangeIndexForIndex(uint64_t idx); + int rightRangeIndexForIndexWithBounds(uint64_t idx, unsigned int left, unsigned int right); + }; + +} + +#endif + +#endif /* defined(__mailcore2__MCIndexSet__) */ diff --git a/src/core/basetypes/MCRange.cc b/src/core/basetypes/MCRange.cc index ead5c189..48bb3d84 100644 --- a/src/core/basetypes/MCRange.cc +++ b/src/core/basetypes/MCRange.cc @@ -2,10 +2,10 @@ using namespace mailcore; -Range mailcore::RangeMake(unsigned int index, unsigned int length) +Range mailcore::RangeMake(uint64_t location, uint64_t length) { Range range; - range.index = index; + range.location = location; range.length = length; return range; } diff --git a/src/core/basetypes/MCRange.h b/src/core/basetypes/MCRange.h index 9b978bfb..7b8b497d 100644 --- a/src/core/basetypes/MCRange.h +++ b/src/core/basetypes/MCRange.h @@ -4,14 +4,16 @@ #ifdef __cplusplus +#include <inttypes.h> + namespace mailcore { struct Range { - unsigned int index; - unsigned int length; + uint64_t location; + uint64_t length; }; - Range RangeMake(unsigned int index, unsigned int length); + Range RangeMake(uint64_t location, uint64_t length); } #endif diff --git a/src/core/basetypes/MCString.cc b/src/core/basetypes/MCString.cc index d72d111d..75765c26 100644 --- a/src/core/basetypes/MCString.cc +++ b/src/core/basetypes/MCString.cc @@ -1235,15 +1235,15 @@ UChar String::characterAtIndex(unsigned int index) void String::deleteCharactersInRange(Range range) { - if (range.index > mLength) + if (range.location > mLength) return; - if (range.index + range.length > mLength) { - range.length = mLength - range.index; + if (range.location + range.length > mLength) { + range.length = mLength - range.location; } - int32_t count = mLength - (range.index + range.length); - u_memmove(&mUnicodeChars[range.index], &mUnicodeChars[range.index + range.length], count); + int32_t count = mLength - (int32_t) (range.location + range.length); + u_memmove(&mUnicodeChars[range.location], &mUnicodeChars[range.location + range.length], count); } int String::locationOfString(String * occurrence) @@ -1935,15 +1935,15 @@ String * String::substringToIndex(unsigned int idx) String * String::substringWithRange(Range range) { - if (range.index > length()) { + if (range.location > length()) { return MCSTR(""); } - if (range.index + range.length > length()) { - range.length = length() - range.index; + if (range.location + range.length > length()) { + range.length = length() - range.location; } - return stringWithCharacters(unicodeCharacters() + range.index, range.length); + return stringWithCharacters(unicodeCharacters() + range.location, range.length); } static chash * uniquedStringHash = NULL; diff --git a/src/core/imap/MCIMAPMessage.cc b/src/core/imap/MCIMAPMessage.cc index 7f5f4427..6f8a0dbb 100644 --- a/src/core/imap/MCIMAPMessage.cc +++ b/src/core/imap/MCIMAPMessage.cc @@ -14,11 +14,12 @@ static AbstractPart * partForPartIDInMessagePart(AbstractMessagePart * part, Str void IMAPMessage::init() { - mUid = NULL; + mUid = 0; mFlags = MessageFlagNone; mOriginalFlags = MessageFlagNone; mMainPart = NULL; mLabels = NULL; + mModSeqValue = 0; } IMAPMessage::IMAPMessage() @@ -90,6 +91,16 @@ MessageFlag IMAPMessage::originalFlags() return mOriginalFlags; } +void IMAPMessage::setModSeqValue(uint64_t uid) +{ + mModSeqValue = uid; +} + +uint64_t IMAPMessage::modSeqValue() +{ + return mModSeqValue; +} + void IMAPMessage::setMainPart(AbstractPart * mainPart) { MC_SAFE_REPLACE_RETAIN(AbstractPart, mMainPart, mainPart); diff --git a/src/core/imap/MCIMAPMessage.h b/src/core/imap/MCIMAPMessage.h index b1fd4647..fdf2779b 100644 --- a/src/core/imap/MCIMAPMessage.h +++ b/src/core/imap/MCIMAPMessage.h @@ -29,6 +29,9 @@ namespace mailcore { virtual void setOriginalFlags(MessageFlag flags); virtual MessageFlag originalFlags(); + virtual uint64_t modSeqValue(); + virtual void setModSeqValue(uint64_t uid); + virtual void setMainPart(AbstractPart * mainPart); virtual AbstractPart * mainPart(); @@ -50,6 +53,7 @@ namespace mailcore { virtual String * description(); private: + uint64_t mModSeqValue; uint32_t mUid; MessageFlag mFlags; MessageFlag mOriginalFlags; diff --git a/src/core/imap/MCIMAPSession.cc b/src/core/imap/MCIMAPSession.cc index f79ebc44..0d0bf64e 100644 --- a/src/core/imap/MCIMAPSession.cc +++ b/src/core/imap/MCIMAPSession.cc @@ -11,6 +11,7 @@ #include "MCAbstractPart.h" #include "MCIMAPProgressCallback.h" #include "MCIMAPNamespace.h" +#include "MCIMAPSyncResult.h" using namespace mailcore; @@ -284,12 +285,16 @@ void IMAPSession::init() mBodyProgressEnabled = true; mIdleEnabled = false; mXListEnabled = false; + mQResyncEnabled = false; + mCondstoreEnabled = false; + mIdentityEnabled = false; mWelcomeString = NULL; mNeedsMboxMailWorkaround = false; mDefaultNamespace = NULL; mTimeout = 30; mUIDValidity = 0; mUIDNext = 0; + mModSequenceValue = 0; mFolderMsgCount = 0; mLastFetchedSequenceNumber = 0; mCurrentFolder = NULL; @@ -724,6 +729,38 @@ void IMAPSession::selectIfNeeded(String * folder, ErrorCode * pError) } } +static uint64_t get_mod_sequence_value(mailimap * session) +{ + uint64_t mod_sequence_value; + clistiter * cur; + + mod_sequence_value = 0; + for(cur = clist_begin(session->imap_response_info->rsp_extension_list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_extension_data * ext_data; + struct mailimap_condstore_resptextcode * resptextcode; + + ext_data = (struct mailimap_extension_data *) clist_content(cur); + if (ext_data->ext_extension->ext_id != MAILIMAP_EXTENSION_CONDSTORE) { + continue; + } + if (ext_data->ext_type != MAILIMAP_CONDSTORE_TYPE_RESP_TEXT_CODE) { + continue; + } + + resptextcode = (struct mailimap_condstore_resptextcode *) ext_data->ext_data; + switch (resptextcode->cs_type) { + case MAILIMAP_CONDSTORE_RESPTEXTCODE_HIGHESTMODSEQ: + mod_sequence_value = resptextcode->cs_data.cs_modseq_value; + break; + case MAILIMAP_CONDSTORE_RESPTEXTCODE_NOMODSEQ: + mod_sequence_value = 0; + break; + } + } + + return mod_sequence_value; +} + void IMAPSession::select(String * folder, ErrorCode * pError) { int r; @@ -758,6 +795,8 @@ void IMAPSession::select(String * folder, ErrorCode * pError) } else { mFolderMsgCount = -1; } + + mModSequenceValue = get_mod_sequence_value(mImap); } mState = STATE_SELECTED; @@ -1572,19 +1611,21 @@ static void msg_att_handler(struct mailimap_msg_att * msg_att, void * context) msg_att_context->mLastFetchedSequenceNumber = mLastFetchedSequenceNumber; } -Array * IMAPSession::fetchMessages(String * folder, IMAPMessagesRequestKind requestKind, bool fetchByUID, - struct mailimap_set * imapset, HashMap * mapping, uint32_t startUid, - IMAPProgressCallback * progressCallback, ErrorCode * pError) +IMAPSyncResult * IMAPSession::fetchMessages(String * folder, IMAPMessagesRequestKind requestKind, bool fetchByUID, + struct mailimap_set * imapset, uint64_t modseq, HashMap * mapping, uint32_t startUid, + IMAPProgressCallback * progressCallback, ErrorCode * pError) { struct mailimap_fetch_type * fetch_type; clist * fetch_result; - Array * result; + struct mailimap_qresync_vanished * vanished; struct mailimap_fetch_att * fetch_att; int r; bool needsHeader; bool needsBody; bool needsFlags; bool needsGmailLabels; + Array * messages; + Array * vanishedMessages; selectIfNeeded(folder, pError); if (* pError != ErrorNone) @@ -1600,7 +1641,7 @@ Array * IMAPSession::fetchMessages(String * folder, IMAPMessagesRequestKind requ mProgressCallback = progressCallback; } - result = Array::array(); + messages = Array::array(); needsHeader = false; needsBody = false; @@ -1701,7 +1742,7 @@ Array * IMAPSession::fetchMessages(String * folder, IMAPMessagesRequestKind requ memset(&msg_att_data, 0, sizeof(msg_att_data)); msg_att_data.self = this; msg_att_data.fetchByUID = fetchByUID; - msg_att_data.result = result; + msg_att_data.result = messages; msg_att_data.folder = folder; msg_att_data.requestKind = requestKind; msg_att_data.mLastFetchedSequenceNumber = mLastFetchedSequenceNumber; @@ -1715,11 +1756,41 @@ Array * IMAPSession::fetchMessages(String * folder, IMAPMessagesRequestKind requ mailimap_set_msg_att_handler(mImap, msg_att_handler, &msg_att_data); mBodyProgressEnabled = false; + vanished = NULL; if (fetchByUID) { - r = mailimap_uid_fetch(mImap, imapset, fetch_type, &fetch_result); + if ((modseq != 0) && (mCondstoreEnabled || mQResyncEnabled)) { + if (mQResyncEnabled) { + r = mailimap_uid_fetch_qresync(mImap, imapset, fetch_type, modseq, + &fetch_result, &vanished); + } + else { /* condstore */ + r = mailimap_uid_fetch_changedsince(mImap, imapset, fetch_type, modseq, + &fetch_result); + } + } + else { + r = mailimap_uid_fetch(mImap, imapset, fetch_type, &fetch_result); + } } else { - r = mailimap_fetch(mImap, imapset, fetch_type, &fetch_result); + if ((modseq != 0) && (mCondstoreEnabled || mQResyncEnabled)) { + if (mQResyncEnabled) { + r = mailimap_fetch_qresync(mImap, imapset, fetch_type, modseq, + &fetch_result, &vanished); + } + else { /* condstore */ + r = mailimap_fetch_changedsince(mImap, imapset, fetch_type, modseq, + &fetch_result); + } + } + else { + r = mailimap_fetch(mImap, imapset, fetch_type, &fetch_result); + } + } + + vanishedMessages = NULL; + if (vanished != NULL) { + vanishedMessages = arrayFromSet(vanished->qr_known_uids); } mBodyProgressEnabled = true; @@ -1748,8 +1819,14 @@ Array * IMAPSession::fetchMessages(String * folder, IMAPMessagesRequestKind requ return NULL; } + IMAPSyncResult * result; + result = new IMAPSyncResult(); + result->setModifiedOrAddedMessages(messages); + result->setVanishedMessages(vanishedMessages); + result->autorelease(); + if ((requestKind & IMAPMessagesRequestKindHeaders) != 0) { - if (result->count() == 0) { + if (messages->count() == 0) { unsigned int count; count = clist_count(fetch_result); @@ -1758,9 +1835,13 @@ Array * IMAPSession::fetchMessages(String * folder, IMAPMessagesRequestKind requ requestKind = (IMAPMessagesRequestKind) (requestKind | IMAPMessagesRequestKindFullHeaders); result = fetchMessages(folder, requestKind, fetchByUID, - imapset, NULL, startUid, progressCallback, pError); - if (result->count() > 0) { - mNeedsMboxMailWorkaround = true; + imapset, modseq, NULL, startUid, progressCallback, pError); + if (result != NULL) { + if (result->modifiedOrAddedMessages() != NULL) { + if (result->modifiedOrAddedMessages()->count() > 0) { + mNeedsMboxMailWorkaround = true; + } + } } } } @@ -1769,15 +1850,19 @@ Array * IMAPSession::fetchMessages(String * folder, IMAPMessagesRequestKind requ mailimap_fetch_list_free(fetch_result); * pError = ErrorNone; - return result; + return result; } Array * IMAPSession::fetchMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, uint32_t firstUID, uint32_t lastUID, IMAPProgressCallback * progressCallback, ErrorCode * pError) { struct mailimap_set * imapset = mailimap_set_new_interval(firstUID, lastUID); - Array * result = fetchMessages(folder, requestKind, true, imapset, NULL, firstUID, - progressCallback, pError); + IMAPSyncResult * syncResult = fetchMessages(folder, requestKind, true, imapset, 0, NULL, firstUID, + progressCallback, pError); + if (syncResult == NULL) + return NULL; + Array * result = syncResult->modifiedOrAddedMessages(); + result->retain()->autorelease(); mailimap_set_free(imapset); return result; } @@ -1786,9 +1871,13 @@ Array * IMAPSession::fetchMessagesByUID(String * folder, IMAPMessagesRequestKind Array * uids, IMAPProgressCallback * progressCallback, ErrorCode * pError) { struct mailimap_set * imapset = setFromArray(uids); - Array * result = fetchMessages(folder, requestKind, true, imapset, NULL, - (uint32_t) ((Value *) uids->objectAtIndex(0))->unsignedLongValue(), - progressCallback, pError); + IMAPSyncResult * syncResult = fetchMessages(folder, requestKind, true, imapset, 0, NULL, + (uint32_t) ((Value *) uids->objectAtIndex(0))->unsignedLongValue(), + progressCallback, pError); + if (syncResult == NULL) + return NULL; + Array * result = syncResult->modifiedOrAddedMessages(); + result->retain()->autorelease(); mailimap_set_free(imapset); return result; } @@ -1797,8 +1886,12 @@ Array * IMAPSession::fetchMessagesByNumber(String * folder, IMAPMessagesRequestK uint32_t firstNumber, uint32_t lastNumber, IMAPProgressCallback * progressCallback, ErrorCode * pError) { struct mailimap_set * imapset = mailimap_set_new_interval(firstNumber, lastNumber); - Array * result = fetchMessages(folder, requestKind, false, imapset, NULL, 0, - progressCallback, pError); + IMAPSyncResult * syncResult = fetchMessages(folder, requestKind, false, imapset, 0, NULL, 0, + progressCallback, pError); + if (syncResult == NULL) + return NULL; + Array * result = syncResult->modifiedOrAddedMessages(); + result->retain()->autorelease(); mailimap_set_free(imapset); return result; } @@ -1807,8 +1900,12 @@ Array * IMAPSession::fetchMessagesByNumber(String * folder, IMAPMessagesRequestK Array * numbers, IMAPProgressCallback * progressCallback, ErrorCode * pError) { struct mailimap_set * imapset = setFromArray(numbers); - Array * result = fetchMessages(folder, requestKind, false, imapset, NULL, 0, - progressCallback, pError); + IMAPSyncResult * syncResult = fetchMessages(folder, requestKind, false, imapset, 0, NULL, 0, + progressCallback, pError); + if (syncResult == NULL) + return NULL; + Array * result = syncResult->modifiedOrAddedMessages(); + result->retain()->autorelease(); mailimap_set_free(imapset); return result; } @@ -2570,7 +2667,114 @@ uint32_t IMAPSession::uidNext() return mUIDNext; } +uint64_t IMAPSession::modSequenceValue() +{ + return mModSequenceValue; +} + unsigned int IMAPSession::lastFolderMessageCount() { return mFolderMsgCount; } + +IMAPSyncResult * IMAPSession::syncMessagesByUIDForModSeq(String * folder, IMAPMessagesRequestKind requestKind, + uint32_t firstUID, uint32_t lastUID, + uint64_t modseq, + IMAPProgressCallback * progressCallback, ErrorCode * pError) +{ + struct mailimap_set * imapset = mailimap_set_new_interval(firstUID, lastUID); + IMAPSyncResult * result = fetchMessages(folder, requestKind, true, imapset, modseq, NULL, firstUID, + progressCallback, pError); + mailimap_set_free(imapset); + return result; +} + +IMAPSyncResult * IMAPSession::syncMessagesByUIDForModSeq(String * folder, IMAPMessagesRequestKind requestKind, + Array * uids, uint64_t modseq, + IMAPProgressCallback * progressCallback, ErrorCode * pError) +{ + struct mailimap_set * imapset = setFromArray(uids); + IMAPSyncResult * result = fetchMessages(folder, requestKind, true, imapset, modseq, NULL, + (uint32_t) ((Value *) uids->objectAtIndex(0))->unsignedLongValue(), + progressCallback, pError); + mailimap_set_free(imapset); + return result; +} + +IndexSet * IMAPSession::capability(ErrorCode * pError) +{ + int r; + struct mailimap_capability_data * cap; + + loginIfNeeded(pError); + if (* pError != ErrorNone) + return NULL; + + r = mailimap_capability(mImap, &cap); + if (r == MAILIMAP_ERROR_STREAM) { + * pError = ErrorConnection; + return NULL; + } + else if (r == MAILIMAP_ERROR_PARSE) { + * pError = ErrorParse; + return NULL; + } + else if (hasError(r)) { + * pError = ErrorCapability; + return NULL; + } + + mailimap_capability_data_free(cap); + + IndexSet * result = new IndexSet(); + if (mailimap_has_id(mImap)) { + result->addIndex(IMAPCapabilityId); + mIdentityEnabled = true; + } + if (mailimap_has_xlist(mImap)) { + result->addIndex(IMAPCapabilityXList); + mXListEnabled = true; + } + if (mailimap_has_idle(mImap)) { + result->addIndex(IMAPCapabilityIdle); + mIdleEnabled = true; + } + if (mailimap_has_condstore(mImap)) { + result->addIndex(IMAPCapabilityCondstore); + mCondstoreEnabled = true; + } + if (mailimap_has_condstore(mImap)) { + result->addIndex(IMAPCapabilityQResync); + mQResyncEnabled = true; + } + + * pError = ErrorNone; + result->autorelease(); + return result; +} + +bool IMAPSession::isIdleEnabled() +{ + return mIdleEnabled; +} + +bool IMAPSession::isXListEnabled() +{ + return mXListEnabled; +} + +bool IMAPSession::isCondstoreEnabled() +{ + return mCondstoreEnabled; +} + +bool IMAPSession::isQResyncEnabled() +{ + return mQResyncEnabled; +} + +bool IMAPSession::isIdentityEnabled() +{ + return mIdentityEnabled; +} + diff --git a/src/core/imap/MCIMAPSession.h b/src/core/imap/MCIMAPSession.h index d114f0be..6239a2d7 100644 --- a/src/core/imap/MCIMAPSession.h +++ b/src/core/imap/MCIMAPSession.h @@ -18,6 +18,7 @@ namespace mailcore { class IMAPSearchExpression; class IMAPFolder; class IMAPProgressCallback; + class IMAPSyncResult; class IMAPSession : public Object { public: @@ -79,21 +80,30 @@ namespace mailcore { virtual void expunge(String * folder, ErrorCode * pError); - virtual Array * fetchMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, + virtual Array * /* IMAPMessage */ fetchMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, uint32_t firstUID, uint32_t lastUID, IMAPProgressCallback * progressCallback, ErrorCode * pError); - virtual Array * fetchMessagesByNumber(String * folder, IMAPMessagesRequestKind requestKind, + virtual Array * /* IMAPMessage */ fetchMessagesByNumber(String * folder, IMAPMessagesRequestKind requestKind, uint32_t firstNumber, uint32_t lastNumber, IMAPProgressCallback * progressCallback, ErrorCode * pError); - virtual Array * fetchMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, - Array * uids, IMAPProgressCallback * progressCallback, ErrorCode * pError); - virtual Array * fetchMessagesByNumber(String * folder, IMAPMessagesRequestKind requestKind, - Array * numbers, IMAPProgressCallback * progressCallback, ErrorCode * pError); + virtual Array * /* IMAPMessage */ fetchMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, + Array * /* Value */ uids, IMAPProgressCallback * progressCallback, ErrorCode * pError); + virtual Array * /* IMAPMessage */ fetchMessagesByNumber(String * folder, IMAPMessagesRequestKind requestKind, + Array * /* Value */ numbers, IMAPProgressCallback * progressCallback, ErrorCode * pError); virtual Data * fetchMessageByUID(String * folder, uint32_t uid, IMAPProgressCallback * progressCallback, ErrorCode * pError); virtual Data * fetchMessageAttachmentByUID(String * folder, uint32_t uid, String * partID, Encoding encoding, IMAPProgressCallback * progressCallback, ErrorCode * pError); virtual HashMap * fetchMessageNumberUIDMapping(String * folder, uint32_t fromUID, uint32_t toUID, ErrorCode * pError); - + + /* When CONDSTORE or QRESYNC is available */ + virtual IMAPSyncResult * syncMessagesByUIDForModSeq(String * folder, IMAPMessagesRequestKind requestKind, + uint32_t firstUID, uint32_t lastUID, + uint64_t modseq, + IMAPProgressCallback * progressCallback, ErrorCode * pError); + virtual IMAPSyncResult * syncMessagesByUIDForModSeq(String * folder, IMAPMessagesRequestKind requestKind, + Array * uids, uint64_t modseq, + IMAPProgressCallback * progressCallback, ErrorCode * pError); + virtual void storeFlags(String * folder, Array * uids, IMAPStoreFlagsRequestKind kind, MessageFlag flags, ErrorCode * pError); virtual void storeLabels(String * folder, Array * uids, IMAPStoreFlagsRequestKind kind, Array * labels, ErrorCode * pError); @@ -114,10 +124,19 @@ namespace mailcore { virtual HashMap * identity(String * vendor, String * name, String * version, ErrorCode * pError); + virtual IndexSet * capability(ErrorCode * pError); + virtual uint32_t uidValidity(); virtual uint32_t uidNext(); + virtual uint64_t modSequenceValue(); virtual unsigned int lastFolderMessageCount(); + virtual bool isIdleEnabled(); + virtual bool isXListEnabled(); + virtual bool isCondstoreEnabled(); + virtual bool isQResyncEnabled(); + virtual bool isIdentityEnabled(); + private: String * mHostname; unsigned int mPort; @@ -134,10 +153,14 @@ namespace mailcore { bool mBodyProgressEnabled; bool mIdleEnabled; bool mXListEnabled; + bool mCondstoreEnabled; + bool mQResyncEnabled; + bool mIdentityEnabled; String * mWelcomeString; bool mNeedsMboxMailWorkaround; uint32_t mUIDValidity; uint32_t mUIDNext; + uint64_t mModSequenceValue; unsigned int mFolderMsgCount; unsigned int mLastFetchedSequenceNumber; String * mCurrentFolder; @@ -159,9 +182,9 @@ namespace mailcore { void loginIfNeeded(ErrorCode * pError); void selectIfNeeded(String * folder, ErrorCode * pError); char fetchDelimiterIfNeeded(char defaultDelimiter, ErrorCode * pError); - Array * fetchMessages(String * folder, IMAPMessagesRequestKind requestKind, bool fetchByUID, - struct mailimap_set * imapset, HashMap * mapping, uint32_t startUid, - IMAPProgressCallback * progressCallback, ErrorCode * pError); + IMAPSyncResult * fetchMessages(String * folder, IMAPMessagesRequestKind requestKind, bool fetchByUID, + struct mailimap_set * imapset, uint64_t modseq, HashMap * mapping, uint32_t startUid, + IMAPProgressCallback * progressCallback, ErrorCode * pError); }; } diff --git a/src/core/imap/MCIMAPSyncResult.cpp b/src/core/imap/MCIMAPSyncResult.cpp new file mode 100644 index 00000000..e2d3ee9c --- /dev/null +++ b/src/core/imap/MCIMAPSyncResult.cpp @@ -0,0 +1,46 @@ +// +// MCIMAPSyncResult.cpp +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/3/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPSyncResult.h" + +#include "MCUtils.h" + +using namespace mailcore; + +IMAPSyncResult::IMAPSyncResult() +{ + mModifiedOrAddedMessages = NULL; + mVanishedMessages = NULL; +} + +IMAPSyncResult::~IMAPSyncResult() +{ + MC_SAFE_RELEASE(mModifiedOrAddedMessages); + MC_SAFE_RELEASE(mVanishedMessages); +} + +void IMAPSyncResult::setModifiedOrAddedMessages(Array * /* IMAPMessage */ messages) +{ + MC_SAFE_REPLACE_RETAIN(Array, mModifiedOrAddedMessages, messages); +} + +Array * /* IMAPMessage */ IMAPSyncResult::modifiedOrAddedMessages() +{ + return mModifiedOrAddedMessages; +} + +void IMAPSyncResult::setVanishedMessages(Array * /* IMAPMessage */ messages) +{ + MC_SAFE_REPLACE_RETAIN(Array, mVanishedMessages, messages); +} + +Array * /* Value */ IMAPSyncResult::vanishedMessages() +{ + return mVanishedMessages; +} + diff --git a/src/core/imap/MCIMAPSyncResult.h b/src/core/imap/MCIMAPSyncResult.h new file mode 100644 index 00000000..009bc65e --- /dev/null +++ b/src/core/imap/MCIMAPSyncResult.h @@ -0,0 +1,38 @@ +// +// MCIMAPSyncResult.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/3/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef __mailcore2__MCIMAPSyncResult__ +#define __mailcore2__MCIMAPSyncResult__ + +#include <mailcore/MCBaseTypes.h> + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPSyncResult : public Object { + public: + IMAPSyncResult(); + virtual ~IMAPSyncResult(); + + virtual void setModifiedOrAddedMessages(Array * /* IMAPMessage */ messages); + virtual Array * /* IMAPMessage */ modifiedOrAddedMessages(); + + virtual void setVanishedMessages(Array * /* IMAPMessage */ messages); + virtual Array * /* Value */ vanishedMessages(); + + private: + Array * /* IMAPMessage */ mModifiedOrAddedMessages; + Array * /* Value */ mVanishedMessages; + }; + +} + +#endif + +#endif /* defined(__mailcore2__MCIMAPSyncResult__) */ |