aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/imap
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/imap')
-rw-r--r--src/core/imap/MCIMAP.h1
-rw-r--r--src/core/imap/MCIMAPIdentity.cc97
-rw-r--r--src/core/imap/MCIMAPIdentity.h54
-rw-r--r--src/core/imap/MCIMAPMessage.cc2
-rw-r--r--src/core/imap/MCIMAPMessage.h2
-rw-r--r--src/core/imap/MCIMAPPart.cc2
-rwxr-xr-x[-rw-r--r--]src/core/imap/MCIMAPSession.cc472
-rwxr-xr-x[-rw-r--r--]src/core/imap/MCIMAPSession.h35
8 files changed, 577 insertions, 88 deletions
diff --git a/src/core/imap/MCIMAP.h b/src/core/imap/MCIMAP.h
index 0248882a..3faddea1 100644
--- a/src/core/imap/MCIMAP.h
+++ b/src/core/imap/MCIMAP.h
@@ -14,5 +14,6 @@
#include <MailCore/MCIMAPSession.h>
#include <MailCore/MCIMAPSyncResult.h>
#include <MailCore/MCIMAPFolderStatus.h>
+#include <MailCore/MCIMAPIdentity.h>
#endif
diff --git a/src/core/imap/MCIMAPIdentity.cc b/src/core/imap/MCIMAPIdentity.cc
new file mode 100644
index 00000000..2e22d539
--- /dev/null
+++ b/src/core/imap/MCIMAPIdentity.cc
@@ -0,0 +1,97 @@
+//
+// MCIMAPIdentity.cpp
+// mailcore2
+//
+// Created by Hoa V. DINH on 8/24/13.
+// Copyright (c) 2013 MailCore. All rights reserved.
+//
+
+#include "MCIMAPIdentity.h"
+
+using namespace mailcore;
+
+IMAPIdentity::IMAPIdentity()
+{
+ init();
+}
+
+IMAPIdentity::IMAPIdentity(IMAPIdentity * identity)
+{
+ init();
+ mc_foreachhashmapKeyAndValue(String, key, String, value, identity->mValues) {
+ mValues->setObjectForKey(key, value);
+ }
+}
+
+void IMAPIdentity::init()
+{
+ mValues = new HashMap();
+}
+
+IMAPIdentity::~IMAPIdentity()
+{
+ MC_SAFE_RELEASE(mValues);
+}
+
+void IMAPIdentity::setVendor(String * vendor)
+{
+ setInfoForKey(MCSTR("vendor"), vendor);
+}
+
+String * IMAPIdentity::vendor()
+{
+ return infoForKey(MCSTR("vendor"));
+}
+
+void IMAPIdentity::setName(String * name)
+{
+ setInfoForKey(MCSTR("name"), name);
+}
+
+String * IMAPIdentity::name()
+{
+ return infoForKey(MCSTR("name"));
+}
+
+void IMAPIdentity::setVersion(String * version)
+{
+ setInfoForKey(MCSTR("version"), version);
+}
+
+String * IMAPIdentity::version()
+{
+ return infoForKey(MCSTR("version"));
+}
+
+Array * IMAPIdentity::allInfoKeys()
+{
+ return mValues->allKeys();
+}
+
+String * IMAPIdentity::infoForKey(String * key)
+{
+ return (String *) mValues->objectForKey(key);
+}
+
+void IMAPIdentity::setInfoForKey(String * key, String * value)
+{
+ if (value != NULL) {
+ mValues->setObjectForKey(key, value->copy()->autorelease());
+ }
+ else {
+ mValues->removeObjectForKey(key);
+ }
+}
+
+Object * IMAPIdentity::copy()
+{
+ return new IMAPIdentity(this);
+}
+
+String * IMAPIdentity::description()
+{
+ return String::stringWithUTF8Format("<%s:%p %s>", className()->UTF8Characters(), this, MCUTF8DESC(mValues));
+}
+
+
+
diff --git a/src/core/imap/MCIMAPIdentity.h b/src/core/imap/MCIMAPIdentity.h
new file mode 100644
index 00000000..c2565955
--- /dev/null
+++ b/src/core/imap/MCIMAPIdentity.h
@@ -0,0 +1,54 @@
+//
+// MCIMAPIdentity.h
+// mailcore2
+//
+// Created by Hoa V. DINH on 8/24/13.
+// Copyright (c) 2013 MailCore. All rights reserved.
+//
+
+#ifndef __MAILCORE_MCIMAPIDENTITY_H
+
+#define __MAILCORE_MCIMAPIDENTITY_H
+
+#include <MailCore/MCBaseTypes.h>
+
+#ifdef __cplusplus
+
+namespace mailcore {
+
+ class IMAPIdentity : public Object {
+ public:
+
+ IMAPIdentity();
+ virtual ~IMAPIdentity();
+
+ virtual void setVendor(String * vendor);
+ virtual String * vendor();
+
+ virtual void setName(String * name);
+ virtual String * name();
+
+ virtual void setVersion(String * version);
+ virtual String * version();
+
+ virtual Array * allInfoKeys();
+ virtual String * infoForKey(String * key);
+ virtual void setInfoForKey(String * key, String * value);
+
+ public: // subclass behavior
+ IMAPIdentity(IMAPIdentity * identity);
+ virtual Object * copy();
+ virtual String * description();
+
+ private:
+ HashMap * mValues;
+
+ void init();
+ };
+
+}
+
+#endif
+
+#endif
+
diff --git a/src/core/imap/MCIMAPMessage.cc b/src/core/imap/MCIMAPMessage.cc
index d8a0d943..74b3459b 100644
--- a/src/core/imap/MCIMAPMessage.cc
+++ b/src/core/imap/MCIMAPMessage.cc
@@ -237,7 +237,7 @@ void IMAPMessage::importSerializable(HashMap * serializable)
}
String * uid = (String *) serializable->objectForKey(MCSTR("uid"));
if (uid != NULL) {
- setUid(uid->unsignedLongValue());
+ setUid((uint32_t) uid->unsignedLongValue());
}
String * flags = (String *) serializable->objectForKey(MCSTR("flags"));
if (flags != NULL) {
diff --git a/src/core/imap/MCIMAPMessage.h b/src/core/imap/MCIMAPMessage.h
index 2f72cd7b..435334c7 100644
--- a/src/core/imap/MCIMAPMessage.h
+++ b/src/core/imap/MCIMAPMessage.h
@@ -18,7 +18,7 @@ namespace mailcore {
class IMAPMessage : public AbstractMessage {
public:
IMAPMessage();
- ~IMAPMessage();
+ virtual ~IMAPMessage();
virtual uint32_t uid();
virtual void setUid(uint32_t uid);
diff --git a/src/core/imap/MCIMAPPart.cc b/src/core/imap/MCIMAPPart.cc
index 76e59021..5fc39fc9 100644
--- a/src/core/imap/MCIMAPPart.cc
+++ b/src/core/imap/MCIMAPPart.cc
@@ -221,7 +221,7 @@ IMAPPart * IMAPPart::attachmentWithIMAPBody1PartBasic(struct mailimap_body_type_
mimeType = String::stringWithUTF8Format("video/%s", basic->bd_media_basic->med_subtype);
break;
case MAILIMAP_MEDIA_BASIC_OTHER:
- mimeType = String::stringWithUTF8Format("other/%s", basic->bd_media_basic->med_subtype);
+ mimeType = String::stringWithUTF8Format("%s/%s", basic->bd_media_basic->med_basic_type, basic->bd_media_basic->med_subtype);
break;
}
attachment->setMimeType(mimeType);
diff --git a/src/core/imap/MCIMAPSession.cc b/src/core/imap/MCIMAPSession.cc
index 7ebe4354..f08ff91a 100644..100755
--- a/src/core/imap/MCIMAPSession.cc
+++ b/src/core/imap/MCIMAPSession.cc
@@ -22,6 +22,7 @@
#include "MCHTMLRendererIMAPDataCallback.h"
#include "MCHTMLBodyRendererTemplateCallback.h"
#include "MCCertificateUtils.h"
+#include "MCIMAPIdentity.h"
using namespace mailcore;
@@ -36,6 +37,8 @@ String * mailcore::IMAPNamespacePersonal = NULL;
String * mailcore::IMAPNamespaceOther = NULL;
String * mailcore::IMAPNamespaceShared = NULL;
+static Array * resultsWithError(int r, clist * list, ErrorCode * pError);
+
__attribute__((constructor))
static void initialize()
{
@@ -333,15 +336,20 @@ void IMAPSession::init()
mQResyncEnabled = false;
mCondstoreEnabled = false;
mIdentityEnabled = false;
+ mNamespaceEnabled = false;
+ mCompressionEnabled = false;
mWelcomeString = NULL;
mNeedsMboxMailWorkaround = false;
mDefaultNamespace = NULL;
+ mServerIdentity = new IMAPIdentity();
+ mClientIdentity = new IMAPIdentity();
mTimeout = 30;
mUIDValidity = 0;
mUIDNext = 0;
mModSequenceValue = 0;
mFolderMsgCount = 0;
mFirstUnseenUid = 0;
+ mYahooServer = false;
mLastFetchedSequenceNumber = 0;
mCurrentFolder = NULL;
pthread_mutex_init(&mIdleLock, NULL);
@@ -351,6 +359,9 @@ void IMAPSession::init()
mProgressCallback = NULL;
mProgressItemsCount = 0;
mConnectionLogger = NULL;
+ mAutomaticConfigurationEnabled = true;
+ mAutomaticConfigurationDone = false;
+ mShouldDisconnect = false;
}
IMAPSession::IMAPSession()
@@ -360,6 +371,7 @@ IMAPSession::IMAPSession()
IMAPSession::~IMAPSession()
{
+ MC_SAFE_RELEASE(mServerIdentity);
MC_SAFE_RELEASE(mHostname);
MC_SAFE_RELEASE(mUsername);
MC_SAFE_RELEASE(mPassword);
@@ -470,16 +482,6 @@ bool IMAPSession::isVoIPEnabled()
return mVoIPEnabled;
}
-void IMAPSession::setDelimiter(char delimiter)
-{
- mDelimiter = delimiter;
-}
-
-char IMAPSession::delimiter()
-{
- return mDelimiter;
-}
-
static bool hasError(int errorCode)
{
return ((errorCode != MAILIMAP_NO_ERROR) && (errorCode != MAILIMAP_NO_ERROR_AUTHENTICATED) &&
@@ -488,6 +490,8 @@ static bool hasError(int errorCode)
bool IMAPSession::checkCertificate()
{
+ if (!isCheckCertificateEnabled())
+ return true;
return mailcore::checkCertificate(mImap->imap_stream, hostname());
}
@@ -576,17 +580,15 @@ void IMAPSession::connect(ErrorCode * pError)
MCLog("STARTTLS connect");
r = mailimap_socket_connect_voip(mImap, MCUTF8(mHostname), mPort, isVoIPEnabled());
if (hasError(r)) {
- unsetup();
* pError = ErrorConnection;
- return;
+ goto close;
}
r = mailimap_socket_starttls(mImap);
if (hasError(r)) {
- unsetup();
MCLog("no TLS %i", r);
* pError = ErrorTLSNotAvailable;
- return;
+ goto close;
}
break;
@@ -594,16 +596,14 @@ void IMAPSession::connect(ErrorCode * pError)
r = mailimap_ssl_connect_voip(mImap, MCUTF8(mHostname), mPort, isVoIPEnabled());
MCLog("ssl connect %s %u %u", MCUTF8(mHostname), mPort, r);
if (hasError(r)) {
- unsetup();
MCLog("connect error %i", r);
* pError = ErrorConnection;
- return;
+ goto close;
}
if (!checkCertificate()) {
- unsetup();
MCLog("ssl connect certificate ERROR %d", r);
* pError = ErrorCertificate;
- return;
+ goto close;
}
break;
@@ -613,10 +613,9 @@ void IMAPSession::connect(ErrorCode * pError)
r = mailimap_socket_connect_voip(mImap, MCUTF8(mHostname), mPort, isVoIPEnabled());
MCLog("socket connect %i", r);
if (hasError(r)) {
- unsetup();
MCLog("connect error %i", r);
* pError = ErrorConnection;
- return;
+ goto close;
}
break;
}
@@ -632,18 +631,40 @@ void IMAPSession::connect(ErrorCode * pError)
if (mImap->imap_response != NULL) {
MC_SAFE_REPLACE_RETAIN(String, mWelcomeString, String::stringWithUTF8Characters(mImap->imap_response));
+ mYahooServer = (mWelcomeString->locationOfString(MCSTR("yahoo.com")) != -1);
}
- * pError = ErrorNone;
mState = STATE_CONNECTED;
+
+ if (isAutomaticConfigurationEnabled()) {
+ if ((mImap->imap_connection_info != NULL) && (mImap->imap_connection_info->imap_capability != NULL)) {
+ // Don't keep result. It will be kept in session state.
+ capabilitySetWithSessionState(IndexSet::indexSet());
+ }
+ else {
+ capability(pError);
+ if (* pError != ErrorNone) {
+ MCLog("capabilities failed");
+ goto close;
+ }
+ }
+ }
+
+ * pError = ErrorNone;
MCLog("connect ok");
- LOCK();
- mCanIdle = true;
- UNLOCK();
+ return;
+
+close:
+ unsetup();
}
void IMAPSession::connectIfNeeded(ErrorCode * pError)
{
+ if (mShouldDisconnect) {
+ disconnect();
+ mShouldDisconnect = false;
+ }
+
if (mState == STATE_DISCONNECTED) {
connect(pError);
}
@@ -674,6 +695,13 @@ void IMAPSession::login(ErrorCode * pError)
MCAssert(mState == STATE_CONNECTED);
+ if (mImap->imap_connection_info != NULL) {
+ if (mImap->imap_connection_info->imap_capability != NULL) {
+ mailimap_capability_data_free(mImap->imap_connection_info->imap_capability);
+ mImap->imap_connection_info->imap_capability = NULL;
+ }
+ }
+
const char * utf8username;
const char * utf8password;
utf8username = MCUTF8(mUsername);
@@ -769,6 +797,7 @@ void IMAPSession::login(ErrorCode * pError)
break;
}
if (r == MAILIMAP_ERROR_STREAM) {
+ mShouldDisconnect = true;
* pError = ErrorConnection;
return;
}
@@ -807,8 +836,79 @@ void IMAPSession::login(ErrorCode * pError)
return;
}
- * pError = ErrorNone;
mState = STATE_LOGGEDIN;
+
+ if (isAutomaticConfigurationEnabled()) {
+ if ((mImap->imap_connection_info != NULL) && (mImap->imap_connection_info->imap_capability != NULL)) {
+ // Don't keep result. It will be kept in session state.
+ capabilitySetWithSessionState(IndexSet::indexSet());
+ }
+ else {
+ capability(pError);
+ if (* pError != ErrorNone) {
+ MCLog("capabilities failed");
+ return;
+ }
+ }
+ }
+ else {
+ // TODO: capabilities should be shared with other sessions for non automatic capabilities sessions.
+ }
+ enableFeatures();
+
+ if (isAutomaticConfigurationEnabled()) {
+ if (isNamespaceEnabled()) {
+ HashMap * result = fetchNamespace(pError);
+ if (* pError != ErrorNone) {
+ MCLog("fetch namespace failed");
+ return;
+ }
+ IMAPNamespace * personalNamespace = (IMAPNamespace *) result->objectForKey(IMAPNamespacePersonal);
+ setDefaultNamespace(personalNamespace);
+ mDelimiter = defaultNamespace()->mainDelimiter();
+ }
+ else {
+ clist * imap_folders;
+ IMAPFolder * folder;
+ Array * folders;
+
+ r = mailimap_list(mImap, "", "", &imap_folders);
+ folders = resultsWithError(r, imap_folders, pError);
+ if (* pError != ErrorNone)
+ return;
+
+ if (folders->count() > 0) {
+ folder = (IMAPFolder *) folders->objectAtIndex(0);
+ }
+ else {
+ folder = NULL;
+ }
+ if (folder == NULL) {
+ * pError = ErrorNonExistantFolder;
+ return;
+ }
+
+ mDelimiter = folder->delimiter();
+ IMAPNamespace * defaultNamespace = IMAPNamespace::namespaceWithPrefix(folder->path(), folder->delimiter());
+ setDefaultNamespace(defaultNamespace);
+ }
+
+ if (isIdentityEnabled()) {
+ IMAPIdentity * serverIdentity = identity(clientIdentity(), pError);
+ if (* pError != ErrorNone) {
+ MCLog("fetch identity failed");
+ return;
+ }
+ MC_SAFE_REPLACE_RETAIN(IMAPIdentity, mServerIdentity, serverIdentity);
+ }
+ }
+ else {
+ // TODO: namespace should be shared with other sessions for non automatic namespace.
+ }
+
+ mAutomaticConfigurationDone = true;
+
+ * pError = ErrorNone;
MCLog("login ok");
}
@@ -874,6 +974,7 @@ void IMAPSession::select(String * folder, ErrorCode * pError)
r = mailimap_select(mImap, MCUTF8(folder));
MCLog("select error : %i", r);
if (r == MAILIMAP_ERROR_STREAM) {
+ mShouldDisconnect = true;
* pError = ErrorConnection;
MCLog("select error : %s %i", MCUTF8DESC(this), * pError);
return;
@@ -884,6 +985,7 @@ void IMAPSession::select(String * folder, ErrorCode * pError)
}
else if (hasError(r)) {
* pError = ErrorNonExistantFolder;
+ mState = STATE_LOGGEDIN;
MC_SAFE_RELEASE(mCurrentFolder);
return;
}
@@ -947,6 +1049,7 @@ IMAPFolderStatus * IMAPSession::folderStatus(String * folder, ErrorCode * pError
MCLog("status error : %i", r);
if (r == MAILIMAP_ERROR_STREAM) {
+ mShouldDisconnect = true;
* pError = ErrorConnection;
MCLog("status error : %s %i", MCUTF8DESC(this), * pError);
return fs;
@@ -1124,6 +1227,7 @@ static Array * resultsWithError(int r, clist * list, ErrorCode * pError)
return result;
}
+// Deprecated
char IMAPSession::fetchDelimiterIfNeeded(char defaultDelimiter, ErrorCode * pError)
{
int r;
@@ -1136,6 +1240,8 @@ char IMAPSession::fetchDelimiterIfNeeded(char defaultDelimiter, ErrorCode * pErr
r = mailimap_list(mImap, "", "", &imap_folders);
folders = resultsWithError(r, imap_folders, pError);
+ if (* pError == ErrorConnection)
+ mShouldDisconnect = true;
if (* pError != ErrorNone)
return 0;
@@ -1156,18 +1262,22 @@ Array * /* IMAPFolder */ IMAPSession::fetchSubscribedFolders(ErrorCode * pError)
{
int r;
clist * imap_folders;
- char delimiter;
MCLog("fetch subscribed");
loginIfNeeded(pError);
if (* pError != ErrorNone)
return NULL;
- delimiter = fetchDelimiterIfNeeded(mDelimiter, pError);
- if (* pError != ErrorNone)
- return NULL;
-
- setDelimiter(delimiter);
+ if (mDelimiter == 0) {
+ char delimiter;
+
+ delimiter = fetchDelimiterIfNeeded(mDelimiter, pError);
+ if (* pError != ErrorNone)
+ return NULL;
+
+ //setDelimiter(delimiter);
+ mDelimiter = delimiter;
+ }
String * prefix;
prefix = defaultNamespace()->mainPrefix();
@@ -1175,31 +1285,38 @@ Array * /* IMAPFolder */ IMAPSession::fetchSubscribedFolders(ErrorCode * pError)
prefix = MCSTR("");
}
if (prefix->length() > 0) {
- if (!prefix->hasSuffix(String::stringWithUTF8Format("%c", delimiter))) {
- prefix = prefix->stringByAppendingUTF8Format("%c", delimiter);
+ if (!prefix->hasSuffix(String::stringWithUTF8Format("%c", mDelimiter))) {
+ prefix = prefix->stringByAppendingUTF8Format("%c", mDelimiter);
}
}
r = mailimap_lsub(mImap, MCUTF8(prefix), "*", &imap_folders);
MCLog("fetch subscribed %u", r);
- return resultsWithError(r, imap_folders, pError);
+ Array * result = resultsWithError(r, imap_folders, pError);
+ if (* pError == ErrorConnection)
+ mShouldDisconnect = true;
+ return result;
}
Array * /* IMAPFolder */ IMAPSession::fetchAllFolders(ErrorCode * pError)
{
int r;
clist * imap_folders;
- char delimiter;
loginIfNeeded(pError);
if (* pError != ErrorNone)
return NULL;
- delimiter = fetchDelimiterIfNeeded(mDelimiter, pError);
- if (* pError != ErrorNone)
- return NULL;
-
- setDelimiter(delimiter);
+ if (mDelimiter == 0) {
+ char delimiter;
+
+ delimiter = fetchDelimiterIfNeeded(mDelimiter, pError);
+ if (* pError != ErrorNone)
+ return NULL;
+
+ //setDelimiter(delimiter);
+ mDelimiter = delimiter;
+ }
String * prefix = NULL;
if (defaultNamespace()) {
@@ -1209,8 +1326,8 @@ Array * /* IMAPFolder */ IMAPSession::fetchAllFolders(ErrorCode * pError)
prefix = MCSTR("");
}
if (prefix->length() > 0) {
- if (!prefix->hasSuffix(String::stringWithUTF8Format("%c", delimiter))) {
- prefix = prefix->stringByAppendingUTF8Format("%c", delimiter);
+ if (!prefix->hasSuffix(String::stringWithUTF8Format("%c", mDelimiter))) {
+ prefix = prefix->stringByAppendingUTF8Format("%c", mDelimiter);
}
}
@@ -1220,7 +1337,10 @@ Array * /* IMAPFolder */ IMAPSession::fetchAllFolders(ErrorCode * pError)
else {
r = mailimap_list(mImap, MCUTF8(prefix), "*", &imap_folders);
}
- return resultsWithError(r, imap_folders, pError);
+ Array * result = resultsWithError(r, imap_folders, pError);
+ if (* pError == ErrorConnection)
+ mShouldDisconnect = true;
+ return result;
}
void IMAPSession::renameFolder(String * folder, String * otherName, ErrorCode * pError)
@@ -1233,6 +1353,7 @@ void IMAPSession::renameFolder(String * folder, String * otherName, ErrorCode *
r = mailimap_rename(mImap, MCUTF8(folder), MCUTF8(otherName));
if (r == MAILIMAP_ERROR_STREAM) {
+ mShouldDisconnect = true;
* pError = ErrorConnection;
return;
}
@@ -1257,6 +1378,7 @@ void IMAPSession::deleteFolder(String * folder, ErrorCode * pError)
r = mailimap_delete(mImap, MCUTF8(folder));
if (r == MAILIMAP_ERROR_STREAM) {
+ mShouldDisconnect = true;
* pError = ErrorConnection;
return;
}
@@ -1281,6 +1403,7 @@ void IMAPSession::createFolder(String * folder, ErrorCode * pError)
r = mailimap_create(mImap, MCUTF8(folder));
if (r == MAILIMAP_ERROR_STREAM) {
+ mShouldDisconnect = true;
* pError = ErrorConnection;
return;
}
@@ -1307,6 +1430,7 @@ void IMAPSession::subscribeFolder(String * folder, ErrorCode * pError)
r = mailimap_subscribe(mImap, MCUTF8(folder));
if (r == MAILIMAP_ERROR_STREAM) {
+ mShouldDisconnect = true;
* pError = ErrorConnection;
return;
}
@@ -1331,6 +1455,7 @@ void IMAPSession::unsubscribeFolder(String * folder, ErrorCode * pError)
r = mailimap_unsubscribe(mImap, MCUTF8(folder));
if (r == MAILIMAP_ERROR_STREAM) {
+ mShouldDisconnect = true;
* pError = ErrorConnection;
return;
}
@@ -1370,6 +1495,7 @@ void IMAPSession::appendMessage(String * folder, Data * messageData, MessageFlag
mProgressCallback = NULL;
if (r == MAILIMAP_ERROR_STREAM) {
+ mShouldDisconnect = true;
* pError = ErrorConnection;
return;
}
@@ -1417,6 +1543,7 @@ void IMAPSession::copyMessages(String * folder, IndexSet * uidSet, String * dest
r = mailimap_uidplus_uid_copy(mImap, current_set, MCUTF8(destFolder),
&uidvalidity, &src_uid, &dest_uid);
if (r == MAILIMAP_ERROR_STREAM) {
+ mShouldDisconnect = true;
* pError = ErrorConnection;
goto release;
}
@@ -1463,6 +1590,7 @@ void IMAPSession::expunge(String * folder, ErrorCode * pError)
r = mailimap_expunge(mImap);
if (r == MAILIMAP_ERROR_STREAM) {
+ mShouldDisconnect = true;
* pError = ErrorConnection;
return;
}
@@ -1568,6 +1696,7 @@ HashMap * IMAPSession::fetchMessageNumberUIDMapping(String * folder, uint32_t fr
if (r == MAILIMAP_ERROR_STREAM) {
MCLog("error stream");
+ mShouldDisconnect = true;
* pError = ErrorConnection;
return NULL;
}
@@ -2082,6 +2211,7 @@ IMAPSyncResult * IMAPSession::fetchMessages(String * folder, IMAPMessagesRequest
if (r == MAILIMAP_ERROR_STREAM) {
MCLog("error stream");
+ mShouldDisconnect = true;
* pError = ErrorConnection;
return NULL;
}
@@ -2264,6 +2394,7 @@ Data * IMAPSession::fetchMessageByUID(String * folder, uint32_t uid,
mProgressCallback = NULL;
if (r == MAILIMAP_ERROR_STREAM) {
+ mShouldDisconnect = true;
* pError = ErrorConnection;
return NULL;
}
@@ -2334,6 +2465,7 @@ Data * IMAPSession::fetchMessageAttachmentByUID(String * folder, uint32_t uid, S
MCLog("had error : %i", r);
if (r == MAILIMAP_ERROR_STREAM) {
+ mShouldDisconnect = true;
* pError = ErrorConnection;
return NULL;
}
@@ -2445,10 +2577,15 @@ IndexSet * IMAPSession::search(String * folder, IMAPSearchExpression * expressio
clist * result_list = NULL;
- int r = mailimap_uid_search(mImap, "utf-8", key, &result_list);
+ const char * charset = "utf-8";
+ if (mYahooServer) {
+ charset = NULL;
+ }
+ int r = mailimap_uid_search(mImap, charset, key, &result_list);
mailimap_search_key_free(key);
MCLog("had error : %i", r);
if (r == MAILIMAP_ERROR_STREAM) {
+ mShouldDisconnect = true;
* pError = ErrorConnection;
return NULL;
}
@@ -2471,6 +2608,37 @@ IndexSet * IMAPSession::search(String * folder, IMAPSearchExpression * expressio
return result;
}
+void IMAPSession::getQuota(uint32_t *usage, uint32_t *limit, ErrorCode * pError)
+{
+ mailimap_quota_complete_data *quota_data;
+
+ int r = mailimap_quota_getquotaroot(mImap, "INBOX", &quota_data);
+ if (r == MAILIMAP_ERROR_STREAM) {
+ mShouldDisconnect = true;
+ * pError = ErrorConnection;
+ return;
+ }
+ else if (r == MAILIMAP_ERROR_PARSE) {
+ * pError = ErrorParse;
+ return;
+ }
+ else if (hasError(r)) {
+ * pError = ErrorFetch;
+ return;
+ }
+ for(clistiter * cur = clist_begin(quota_data->quota_list); cur != NULL; cur = clist_next(cur)) {
+ mailimap_quota_quota_data *quota = (mailimap_quota_quota_data*)clist_content(cur);
+ for (clistiter *cur2 = clist_begin(quota->quota_list); cur2 != NULL; cur2 = clist_next(cur2)) {
+ mailimap_quota_quota_resource *res = (mailimap_quota_quota_resource*)clist_content(cur2);
+ if (!strcasecmp("STORAGE", res->resource_name)) {
+ *usage = res->usage;
+ *limit = res->limit;
+ }
+ }
+ }
+ mailimap_quota_complete_data_free(quota_data);
+}
+
bool IMAPSession::setupIdle()
{
// main thread
@@ -2512,6 +2680,7 @@ void IMAPSession::idle(String * folder, uint32_t lastKnownUID, ErrorCode * pErro
r = mailimap_idle(mImap);
if (r == MAILIMAP_ERROR_STREAM) {
+ mShouldDisconnect = true;
* pError = ErrorConnection;
return;
}
@@ -2531,6 +2700,7 @@ void IMAPSession::idle(String * folder, uint32_t lastKnownUID, ErrorCode * pErro
case MAILSTREAM_IDLE_ERROR:
case MAILSTREAM_IDLE_CANCELLED:
{
+ mShouldDisconnect = true;
* pError = ErrorConnection;
MCLog("error or cancelled");
return;
@@ -2552,6 +2722,7 @@ void IMAPSession::idle(String * folder, uint32_t lastKnownUID, ErrorCode * pErro
r = mailimap_idle_done(mImap);
if (r == MAILIMAP_ERROR_STREAM) {
+ mShouldDisconnect = true;
* pError = ErrorConnection;
return;
}
@@ -2591,31 +2762,22 @@ void IMAPSession::disconnect()
unsetup();
}
-HashMap * IMAPSession::identity(String * vendor, String * name, String * version, ErrorCode * pError)
+IMAPIdentity * IMAPSession::identity(IMAPIdentity * clientIdentity, ErrorCode * pError)
{
connectIfNeeded(pError);
if (* pError != ErrorNone)
return NULL;
struct mailimap_id_params_list * client_identification;
- char * dup_name;
- char * dup_value;
client_identification = mailimap_id_params_list_new_empty();
- if (name != NULL) {
- dup_name = strdup("name");
- dup_value = strdup(name->UTF8Characters());
- mailimap_id_params_list_add_name_value(client_identification, dup_name, dup_value);
- }
- if (version != NULL) {
- dup_name = strdup("version");
- dup_value = strdup(version->UTF8Characters());
- mailimap_id_params_list_add_name_value(client_identification, dup_name, dup_value);
- }
- if (vendor != NULL) {
- dup_name = strdup("vendor");
- dup_value = strdup(vendor->UTF8Characters());
+ mc_foreacharray(String, key, clientIdentity->allInfoKeys()) {
+ char * dup_name;
+ char * dup_value;
+
+ dup_name = strdup(key->UTF8Characters());
+ dup_value = strdup(clientIdentity->name()->UTF8Characters());
mailimap_id_params_list_add_name_value(client_identification, dup_name, dup_value);
}
@@ -2624,6 +2786,7 @@ HashMap * IMAPSession::identity(String * vendor, String * name, String * version
r = mailimap_id(mImap, client_identification, &server_identification);
mailimap_id_params_list_free(client_identification);
if (r == MAILIMAP_ERROR_STREAM) {
+ mShouldDisconnect = true;
* pError = ErrorConnection;
return NULL;
}
@@ -2636,7 +2799,7 @@ HashMap * IMAPSession::identity(String * vendor, String * name, String * version
return NULL;
}
- HashMap * result = HashMap::hashMap();
+ IMAPIdentity * result = new IMAPIdentity();
clistiter * cur;
for(cur = clist_begin(server_identification->idpa_list) ; cur != NULL ; cur = clist_next(cur)) {
@@ -2648,12 +2811,13 @@ HashMap * IMAPSession::identity(String * vendor, String * name, String * version
String * responseValue;
responseKey = String::stringWithUTF8Characters(param->idpa_name);
responseValue = String::stringWithUTF8Characters(param->idpa_value);
- result->setObjectForKey(responseKey, responseValue);
+ result->setInfoForKey(responseKey, responseValue);
}
mailimap_id_params_list_free(server_identification);
* pError = ErrorNone;
+ result->autorelease();
return result;
}
@@ -2685,6 +2849,16 @@ void IMAPSession::setDefaultNamespace(IMAPNamespace * ns)
MC_SAFE_REPLACE_RETAIN(IMAPNamespace, mDefaultNamespace, ns);
}
+IMAPIdentity * IMAPSession::serverIdentity()
+{
+ return mServerIdentity;
+}
+
+IMAPIdentity * IMAPSession::clientIdentity()
+{
+ return mClientIdentity;
+}
+
HashMap * IMAPSession::fetchNamespace(ErrorCode * pError)
{
HashMap * result;
@@ -2698,6 +2872,7 @@ HashMap * IMAPSession::fetchNamespace(ErrorCode * pError)
result = HashMap::hashMap();
r = mailimap_namespace(mImap, &namespace_data);
if (r == MAILIMAP_ERROR_STREAM) {
+ mShouldDisconnect = true;
* pError = ErrorConnection;
return NULL;
}
@@ -2834,6 +3009,7 @@ void IMAPSession::storeFlags(String * folder, IndexSet * uids, IMAPStoreFlagsReq
r = mailimap_uid_store(mImap, current_set, store_att_flags);
if (r == MAILIMAP_ERROR_STREAM) {
+ mShouldDisconnect = true;
* pError = ErrorConnection;
goto release;
}
@@ -2903,6 +3079,7 @@ void IMAPSession::storeLabels(String * folder, IndexSet * uids, IMAPStoreFlagsRe
}
r = mailimap_uid_store_xgmlabels(mImap, current_set, fl_sign, 1, xgmlabels);
if (r == MAILIMAP_ERROR_STREAM) {
+ mShouldDisconnect = true;
* pError = ErrorConnection;
goto release;
}
@@ -2981,12 +3158,13 @@ IndexSet * IMAPSession::capability(ErrorCode * pError)
int r;
struct mailimap_capability_data * cap;
- loginIfNeeded(pError);
+ connectIfNeeded(pError);
if (* pError != ErrorNone)
return NULL;
r = mailimap_capability(mImap, &cap);
if (r == MAILIMAP_ERROR_STREAM) {
+ mShouldDisconnect = true;
* pError = ErrorConnection;
return NULL;
}
@@ -3002,39 +3180,81 @@ IndexSet * IMAPSession::capability(ErrorCode * pError)
mailimap_capability_data_free(cap);
IndexSet * result = new IndexSet();
+ capabilitySetWithSessionState(result);
+
+ * pError = ErrorNone;
+ result->autorelease();
+ return result;
+}
+
+void IMAPSession::capabilitySetWithSessionState(IndexSet * capabilities)
+{
+ if (mailimap_has_idle(mImap)) {
+ LOCK();
+ mCanIdle = true;
+ UNLOCK();
+ }
if (mailimap_has_id(mImap)) {
- result->addIndex(IMAPCapabilityId);
- mIdentityEnabled = true;
+ capabilities->addIndex(IMAPCapabilityId);
}
if (mailimap_has_xlist(mImap)) {
- result->addIndex(IMAPCapabilityXList);
- mXListEnabled = true;
+ capabilities->addIndex(IMAPCapabilityXList);
}
if (mailimap_has_extension(mImap, (char *) "X-GM-EXT-1")) {
// Disable use of XLIST if this is the Gmail IMAP server because it implements
// RFC 6154.
- mXListEnabled = false;
+ capabilities->addIndex(IMAPCapabilityGmail);
}
if (mailimap_has_idle(mImap)) {
- result->addIndex(IMAPCapabilityIdle);
- mIdleEnabled = true;
+ capabilities->addIndex(IMAPCapabilityIdle);
}
if (mailimap_has_condstore(mImap)) {
- result->addIndex(IMAPCapabilityCondstore);
+ capabilities->addIndex(IMAPCapabilityCondstore);
+ }
+ if (mailimap_has_qresync(mImap)) {
+ capabilities->addIndex(IMAPCapabilityQResync);
+ }
+ if (mailimap_has_xoauth2(mImap)) {
+ capabilities->addIndex(IMAPCapabilityXOAuth2);
+ }
+ if (mailimap_has_namespace(mImap)) {
+ capabilities->addIndex(IMAPCapabilityNamespace);
+ }
+ if (mailimap_has_compress_deflate(mImap)) {
+ capabilities->addIndex(IMAPCapabilityCompressDeflate);
+ }
+ applyCapabilities(capabilities);
+}
+
+void IMAPSession::applyCapabilities(IndexSet * capabilities)
+{
+ if (capabilities->containsIndex(IMAPCapabilityId)) {
+ mIdentityEnabled = true;
+ }
+ if (capabilities->containsIndex(IMAPCapabilityXList)) {
+ mXListEnabled = true;
+ }
+ if (capabilities->containsIndex(IMAPCapabilityGmail)) {
+ mXListEnabled = false;
+ }
+ if (capabilities->containsIndex(IMAPCapabilityIdle)) {
+ mIdleEnabled = true;
+ }
+ if (capabilities->containsIndex(IMAPCapabilityCondstore)) {
mCondstoreEnabled = true;
}
- if (mailimap_has_condstore(mImap)) {
- result->addIndex(IMAPCapabilityQResync);
+ if (capabilities->containsIndex(IMAPCapabilityQResync)) {
mQResyncEnabled = true;
}
- if (mailimap_has_xoauth2(mImap)) {
- result->addIndex(IMAPCapabilityXOAuth2);
+ if (capabilities->containsIndex(IMAPCapabilityXOAuth2)) {
mXOauth2Enabled = true;
}
-
- * pError = ErrorNone;
- result->autorelease();
- return result;
+ if (capabilities->containsIndex(IMAPCapabilityNamespace)) {
+ mNamespaceEnabled = true;
+ }
+ if (capabilities->containsIndex(IMAPCapabilityCompressDeflate)) {
+ mCompressionEnabled = true;
+ }
}
bool IMAPSession::isIdleEnabled()
@@ -3062,10 +3282,21 @@ bool IMAPSession::isIdentityEnabled()
return mIdentityEnabled;
}
-bool IMAPSession::isXOAuthEnabled() {
+bool IMAPSession::isXOAuthEnabled()
+{
return mXOauth2Enabled;
}
+bool IMAPSession::isNamespaceEnabled()
+{
+ return mNamespaceEnabled;
+}
+
+bool IMAPSession::isCompressionEnabled()
+{
+ return mCompressionEnabled;
+}
+
bool IMAPSession::isDisconnected()
{
return mState == STATE_DISCONNECTED;
@@ -3153,3 +3384,84 @@ String * IMAPSession::plainTextBodyRendering(IMAPMessage * message, String * fol
return plainTextBodyString;
}
+
+void IMAPSession::setAutomaticConfigurationEnabled(bool enabled)
+{
+ mAutomaticConfigurationEnabled = enabled;
+}
+
+bool IMAPSession::isAutomaticConfigurationEnabled()
+{
+ return mAutomaticConfigurationEnabled;
+}
+
+bool IMAPSession::enableFeature(String * feature)
+{
+ struct mailimap_capability_data * caps;
+ clist * cap_list;
+ struct mailimap_capability * cap;
+ int r;
+
+ cap_list = clist_new();
+ cap = mailimap_capability_new(MAILIMAP_CAPABILITY_NAME, NULL, strdup(MCUTF8(feature)));
+ clist_append(cap_list, cap);
+ caps = mailimap_capability_data_new(cap_list);
+
+ struct mailimap_capability_data * result;
+ r = mailimap_enable(mImap, caps, &result);
+ if (r != MAILIMAP_NO_ERROR)
+ return false;
+
+ mailimap_capability_data_free(result);
+
+ return true;
+}
+
+void IMAPSession::enableFeatures()
+{
+ if (isCompressionEnabled()) {
+ ErrorCode error;
+ enableCompression(&error);
+ if (error != ErrorNone) {
+ MCLog("could not enable compression");
+ }
+ }
+
+ if (isQResyncEnabled()) {
+ enableFeature(MCSTR("QRESYNC"));
+ }
+ else if (isCondstoreEnabled()) {
+ enableFeature(MCSTR("CONDSTORE"));
+ }
+}
+
+void IMAPSession::enableCompression(ErrorCode * pError)
+{
+ int r;
+ r = mailimap_compress(mImap);
+ if (r == MAILIMAP_ERROR_STREAM) {
+ mShouldDisconnect = true;
+ * pError = ErrorConnection;
+ return;
+ }
+ else if (r == MAILIMAP_ERROR_PARSE) {
+ * pError = ErrorParse;
+ return;
+ }
+ else if (hasError(r)) {
+ * pError = ErrorCompression;
+ return;
+ }
+
+ * pError = ErrorNone;
+}
+
+bool IMAPSession::isAutomaticConfigurationDone()
+{
+ return mAutomaticConfigurationDone;
+}
+
+void IMAPSession::resetAutomaticConfigurationDone()
+{
+ mAutomaticConfigurationDone = false;
+}
diff --git a/src/core/imap/MCIMAPSession.h b/src/core/imap/MCIMAPSession.h
index 4128b516..f4f83e72 100644..100755
--- a/src/core/imap/MCIMAPSession.h
+++ b/src/core/imap/MCIMAPSession.h
@@ -20,6 +20,7 @@ namespace mailcore {
class IMAPProgressCallback;
class IMAPSyncResult;
class IMAPFolderStatus;
+ class IMAPIdentity;
class IMAPSession : public Object {
public:
@@ -59,13 +60,12 @@ namespace mailcore {
virtual bool isVoIPEnabled();
// Needed for fetchSubscribedFolders() and fetchAllFolders().
- virtual void setDelimiter(char delimiter);
- virtual char delimiter();
-
- // Needed for fetchSubscribedFolders() and fetchAllFolders().
virtual void setDefaultNamespace(IMAPNamespace * ns);
virtual IMAPNamespace * defaultNamespace();
+ virtual IMAPIdentity * serverIdentity();
+ virtual IMAPIdentity * clientIdentity();
+
virtual void select(String * folder, ErrorCode * pError);
virtual IMAPFolderStatus * folderStatus(String * folder, ErrorCode * pError);
@@ -126,6 +126,7 @@ namespace mailcore {
virtual IndexSet * search(String * folder, IMAPSearchKind kind, String * searchString, ErrorCode * pError);
virtual IndexSet * search(String * folder, IMAPSearchExpression * expression, ErrorCode * pError);
+ virtual void getQuota(uint32_t *usage, uint32_t *limit, ErrorCode * pError);
virtual bool setupIdle();
virtual void idle(String * folder, uint32_t lastKnownUID, ErrorCode * pError);
@@ -139,10 +140,12 @@ namespace mailcore {
virtual void login(ErrorCode * pError);
- virtual HashMap * identity(String * vendor, String * name, String * version, ErrorCode * pError);
+ IMAPIdentity * identity(IMAPIdentity * clientIdentity, ErrorCode * pError);
virtual IndexSet * capability(ErrorCode * pError);
+ virtual void enableCompression(ErrorCode * pError);
+
virtual uint32_t uidValidity();
virtual uint32_t uidNext();
virtual uint64_t modSequenceValue();
@@ -155,6 +158,8 @@ namespace mailcore {
virtual bool isQResyncEnabled();
virtual bool isIdentityEnabled();
virtual bool isXOAuthEnabled();
+ virtual bool isNamespaceEnabled();
+ virtual bool isCompressionEnabled();
virtual void setConnectionLogger(ConnectionLogger * logger);
virtual ConnectionLogger * connectionLogger();
@@ -172,10 +177,19 @@ namespace mailcore {
This method can be used to generate the summary of the message.*/
virtual String * plainTextBodyRendering(IMAPMessage * message, String * folder, ErrorCode * pError);
+ /** Enable automatic query of the capabilities of the IMAP server when set to true. */
+ virtual void setAutomaticConfigurationEnabled(bool enabled);
+
+ /** Check if the automatic query of the capabilities of the IMAP server is enabled. */
+ virtual bool isAutomaticConfigurationEnabled();
+
public: // private
virtual void loginIfNeeded(ErrorCode * pError);
virtual void connectIfNeeded(ErrorCode * pError);
virtual bool isDisconnected();
+ virtual bool isAutomaticConfigurationDone();
+ virtual void resetAutomaticConfigurationDone();
+ virtual void applyCapabilities(IndexSet * capabilities);
private:
String * mHostname;
@@ -189,6 +203,8 @@ namespace mailcore {
bool mVoIPEnabled;
char mDelimiter;
IMAPNamespace * mDefaultNamespace;
+ IMAPIdentity * mServerIdentity;
+ IMAPIdentity * mClientIdentity;
time_t mTimeout;
bool mBodyProgressEnabled;
@@ -198,6 +214,8 @@ namespace mailcore {
bool mQResyncEnabled;
bool mIdentityEnabled;
bool mXOauth2Enabled;
+ bool mNamespaceEnabled;
+ bool mCompressionEnabled;
String * mWelcomeString;
bool mNeedsMboxMailWorkaround;
uint32_t mUIDValidity;
@@ -205,6 +223,7 @@ namespace mailcore {
uint64_t mModSequenceValue;
unsigned int mFolderMsgCount;
uint32_t mFirstUnseenUid;
+ bool mYahooServer;
unsigned int mLastFetchedSequenceNumber;
String * mCurrentFolder;
@@ -215,6 +234,9 @@ namespace mailcore {
IMAPProgressCallback * mProgressCallback;
unsigned int mProgressItemsCount;
ConnectionLogger * mConnectionLogger;
+ bool mAutomaticConfigurationEnabled;
+ bool mAutomaticConfigurationDone;
+ bool mShouldDisconnect;
void init();
void bodyProgress(unsigned int current, unsigned int maximum);
@@ -230,6 +252,9 @@ namespace mailcore {
bool fetchByUID, struct mailimap_set * imapset, uint64_t modseq,
HashMap * mapping, uint32_t startUid, IMAPProgressCallback * progressCallback,
Array * extraHeaders, ErrorCode * pError);
+ void capabilitySetWithSessionState(IndexSet * capabilities);
+ bool enableFeature(String * feature);
+ void enableFeatures();
};
}