aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar DINH Viet Hoa <dinh.viet.hoa@gmail.com>2013-03-07 00:40:55 -0800
committerGravatar DINH Viet Hoa <dinh.viet.hoa@gmail.com>2013-03-07 00:40:55 -0800
commit3288fbac4090ecf5ea490ba72e5c3c01a4233e21 (patch)
treeddbb1a5a7f88380c6d53d662c173d48f67ba9990 /src/core
parentd6c89c5effc7fed91e3ccb129bacc22c5d3c8d38 (diff)
Implemented QRESYNC. Implemented IndexSet. Implemented CAPABILITY.
Diffstat (limited to 'src/core')
-rw-r--r--src/core/basetypes/MCBaseTypes.h1
-rw-r--r--src/core/basetypes/MCIndexSet.cpp261
-rw-r--r--src/core/basetypes/MCIndexSet.h57
-rw-r--r--src/core/basetypes/MCRange.cc4
-rw-r--r--src/core/basetypes/MCRange.h8
-rw-r--r--src/core/basetypes/MCString.cc18
-rw-r--r--src/core/imap/MCIMAPMessage.cc13
-rw-r--r--src/core/imap/MCIMAPMessage.h4
-rw-r--r--src/core/imap/MCIMAPSession.cc248
-rw-r--r--src/core/imap/MCIMAPSession.h43
-rw-r--r--src/core/imap/MCIMAPSyncResult.cpp46
-rw-r--r--src/core/imap/MCIMAPSyncResult.h38
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__) */