diff options
author | 2013-07-03 17:06:20 -0400 | |
---|---|---|
committer | 2013-07-03 17:06:20 -0400 | |
commit | a2f9f56ec6dc3fccb5a3b237ca62d3156cfa1883 (patch) | |
tree | 1a3c0ebae239e6571bb1c5d02e5921d299f9a399 | |
parent | cc9b898f07b3f750b910cfea73c0e223984f7cad (diff) | |
parent | 9fe6ce12c4880a6c2f2a4180752987dd30d65c89 (diff) |
Merge branch 'master' into message-rendering-with-session
Conflicts:
build-mac/mailcore2.xcodeproj/project.pbxproj
62 files changed, 1114 insertions, 459 deletions
@@ -6,5 +6,5 @@ xcuserdata project.xcworkspace example/ios/iOS UI Test/DerivedData - +scripts/prebuilt.list diff --git a/build-mac/mailcore2.xcodeproj/project.pbxproj b/build-mac/mailcore2.xcodeproj/project.pbxproj index 2c943e02..cec24abe 100644 --- a/build-mac/mailcore2.xcodeproj/project.pbxproj +++ b/build-mac/mailcore2.xcodeproj/project.pbxproj @@ -26,6 +26,8 @@ 9EF9AB23175F406D0027FA3B /* MCOIMAPFolderStatusOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9EF9AB16175F35C60027FA3B /* MCOIMAPFolderStatusOperation.h */; }; 9EF9AB24175F409D0027FA3B /* MCIMAPFolderStatusOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9EF9AB0E175F30C20027FA3B /* MCIMAPFolderStatusOperation.h */; }; 9EF9AB25175F40C70027FA3B /* MCIMAPFolderStatusOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9EF9AB0E175F30C20027FA3B /* MCIMAPFolderStatusOperation.h */; }; + BD63713B177DFF080094121B /* MCLibetpan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BD637139177DFF080094121B /* MCLibetpan.cpp */; }; + BD63713C177DFF080094121B /* MCLibetpan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BD637139177DFF080094121B /* MCLibetpan.cpp */; }; C07AD5D7FD82F8ACAB576231 /* NSError+MCO.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C07AD44B013BB42A240B4F04 /* NSError+MCO.h */; }; C07AD99B2E2054C684DB8FF6 /* NSError+MCO.mm in Sources */ = {isa = PBXBuildFile; fileRef = C07ADFE43E22B38EFF23ADB5 /* NSError+MCO.mm */; }; C07ADC28B83E7959BF114D46 /* MCOIMAPSession.mm in Sources */ = {isa = PBXBuildFile; fileRef = C07AD057D3C8FBDC7AC95733 /* MCOIMAPSession.mm */; }; @@ -1085,6 +1087,8 @@ 9EF9AB10175F319A0027FA3B /* MCIMAPFolderStatusOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPFolderStatusOperation.cc; sourceTree = "<group>"; }; 9EF9AB16175F35C60027FA3B /* MCOIMAPFolderStatusOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOIMAPFolderStatusOperation.h; sourceTree = "<group>"; }; 9EF9AB18175F36600027FA3B /* MCOIMAPFolderStatusOperation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOIMAPFolderStatusOperation.mm; sourceTree = "<group>"; }; + BD637139177DFF080094121B /* MCLibetpan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCLibetpan.cpp; sourceTree = "<group>"; }; + BD63713A177DFF080094121B /* MCLibetpan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCLibetpan.h; sourceTree = "<group>"; }; C07AD057D3C8FBDC7AC95733 /* MCOIMAPSession.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOIMAPSession.mm; sourceTree = "<group>"; }; C07AD44B013BB42A240B4F04 /* NSError+MCO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSError+MCO.h"; sourceTree = "<group>"; }; C07ADFE43E22B38EFF23ADB5 /* NSError+MCO.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSError+MCO.mm"; sourceTree = "<group>"; }; @@ -1851,6 +1855,8 @@ C68B2AEB1778A589005E61EF /* MCConnectionLogger.h */, C68B2AF517797389005E61EF /* MCConnectionLoggerUtils.cc */, C68B2AF617797389005E61EF /* MCConnectionLoggerUtils.h */, + BD637139177DFF080094121B /* MCLibetpan.cpp */, + BD63713A177DFF080094121B /* MCLibetpan.h */, ); path = basetypes; sourceTree = "<group>"; @@ -2501,6 +2507,7 @@ 9E774D891767C7F60065EB9B /* MCIMAPFolderStatus.cc in Sources */, DAD1C7D8177E92650011AC59 /* MCMessageRendererHelper.cpp in Sources */, DAD28C8B1783CFFC00F2BB8F /* MCHTMLBodyRendererCallback.cc in Sources */, + BD63713B177DFF080094121B /* MCLibetpan.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2685,6 +2692,7 @@ 9E774D8A1767C7F60065EB9B /* MCIMAPFolderStatus.cc in Sources */, DAD1C7D9177E92650011AC59 /* MCMessageRendererHelper.cpp in Sources */, DAD28C8C1783CFFC00F2BB8F /* MCHTMLBodyRendererCallback.cc in Sources */, + BD63713C177DFF080094121B /* MCLibetpan.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/scripts/get-prebuilt.sh b/scripts/get-prebuilt.sh index 35b2980f..8a44c659 100755 --- a/scripts/get-prebuilt.sh +++ b/scripts/get-prebuilt.sh @@ -34,6 +34,7 @@ if test x$1 != xskipprebuilt ; then mkdir -p ../Externals/prebuilt pushd ../Externals/prebuilt rm -rf .git + echo Getting prebuilt libraries... if test -d mailcore2-deps ; then cd mailcore2-deps git pull --rebase @@ -41,14 +42,8 @@ if test x$1 != xskipprebuilt ; then else git clone --depth 1 "$url" fi - # for filename in $files ; do - # if test ! -f $filename ; then - # echo get $filename - # curl -L -O "$url_prefix/$filename" - # fi - # done - rsync --exclude=.git -av mailcore2-deps/ ../builds/builds/ - popd - fi + rsync --exclude=.git -av mailcore2-deps/ ../builds/builds/ + popd fi + fi fi diff --git a/scripts/prepare-icu4c-ios.sh b/scripts/prepare-icu4c-ios.sh index eee89069..5630c2e1 100755 --- a/scripts/prepare-icu4c-ios.sh +++ b/scripts/prepare-icu4c-ios.sh @@ -6,6 +6,7 @@ version='51_1' url="http://download.icu-project.org/files/icu4c/$versionfolder/icu4c-$version-src.tgz" package_filename="icu4c-$version-src.tgz" sysrootpath="/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk" +enable_icu_data=0 pushd `dirname $0` > /dev/null scriptpath=`pwd` @@ -115,8 +116,10 @@ done mkdir -p "$tmpdir/bin/icu4c-ios" cp -R $tmpdir/crossbuild/icu4c-x86_64/include "$tmpdir/bin/icu4c-ios" -mkdir -p "$tmpdir/bin/icu4c-ios/share/icu" -cp "$tmpdir/crossbuild/icu4c-x86_64/share/icu/$versionfolder/icudt51l.dat" "$tmpdir/bin/icu4c-ios/share/icu" +if test x$enable_icu_data = x1 ; then + mkdir -p "$tmpdir/bin/icu4c-ios/share/icu" + cp "$tmpdir/crossbuild/icu4c-x86_64/share/icu/$versionfolder/icudt51l.dat" "$tmpdir/bin/icu4c-ios/share/icu" +fi mkdir -p "$tmpdir/bin/icu4c-ios/lib" cd "$tmpdir/bin" diff --git a/scripts/prepare-icu4c-macos.sh b/scripts/prepare-icu4c-macos.sh index 9ae0cf7d..55806bc2 100755 --- a/scripts/prepare-icu4c-macos.sh +++ b/scripts/prepare-icu4c-macos.sh @@ -6,6 +6,7 @@ url="http://download.icu-project.org/files/icu4c/$versionfolder/icu4c-$version-s package_filename="icu4c-$version-src.tgz" arch="x86_64" sysrootpath="/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk" +enable_icu_data=0 arch_flags="" for current_arch in $arch ; do @@ -90,8 +91,10 @@ done mkdir -p "$tmpdir/bin/icu4c" cp -R "$tmpdir/bin/icu4c-x86_64/include" "$tmpdir/bin/icu4c" -mkdir -p "$tmpdir/bin/icu4c/share/icu" -cp "$tmpdir/bin/icu4c-x86_64/share/icu/$versionfolder/icudt51l.dat" "$tmpdir/bin/icu4c/share/icu" +if test x$enable_icu_data = x1 ; then + mkdir -p "$tmpdir/bin/icu4c/share/icu" + cp "$tmpdir/bin/icu4c-x86_64/share/icu/$versionfolder/icudt51l.dat" "$tmpdir/bin/icu4c/share/icu" +fi mkdir -p "$tmpdir/bin/icu4c/lib" cd "$tmpdir/bin" diff --git a/scripts/prepare-libetpan-ios.sh b/scripts/prepare-libetpan-ios.sh index 395b51a7..7a5a054b 100755 --- a/scripts/prepare-libetpan-ios.sh +++ b/scripts/prepare-libetpan-ios.sh @@ -2,7 +2,7 @@ sdkversion=6.1 url="https://github.com/dinhviethoa/libetpan.git" -rev=fb889b032d5a5f7e7178a038918bcdcd5d19d6ec +rev=78427a0506be00e1e72ac8f88aa4b71bebd4137f pushd `dirname $0` > /dev/null scriptpath=`pwd` diff --git a/scripts/prepare-libetpan-macos.sh b/scripts/prepare-libetpan-macos.sh index cd1fa8e3..81013fa6 100755 --- a/scripts/prepare-libetpan-macos.sh +++ b/scripts/prepare-libetpan-macos.sh @@ -1,7 +1,7 @@ #!/bin/sh url="https://github.com/dinhviethoa/libetpan.git" -rev=fb889b032d5a5f7e7178a038918bcdcd5d19d6ec +rev=78427a0506be00e1e72ac8f88aa4b71bebd4137f pushd `dirname $0` > /dev/null scriptpath=`pwd` diff --git a/src/async/imap/MCIMAPAsyncConnection.cc b/src/async/imap/MCIMAPAsyncConnection.cc index 2891d439..fc1935b7 100644 --- a/src/async/imap/MCIMAPAsyncConnection.cc +++ b/src/async/imap/MCIMAPAsyncConnection.cc @@ -33,6 +33,7 @@ #include "MCOperationQueueCallback.h" #include "MCIMAPDisconnectOperation.h" #include "MCIMAPAsyncSession.h" +#include "MCConnectionLogger.h" using namespace mailcore; @@ -46,11 +47,11 @@ namespace mailcore { virtual ~IMAPOperationQueueCallback() { } - virtual void queueStartRunning() { + virtual void queueStartRunning(OperationQueue * queue) { mConnection->queueStartRunning(); } - virtual void queueStoppedRunning() { + virtual void queueStoppedRunning(OperationQueue * queue) { mConnection->tryAutomaticDisconnect(); mConnection->queueStoppedRunning(); } @@ -58,6 +59,24 @@ namespace mailcore { private: IMAPAsyncConnection * mConnection; }; + + class IMAPConnectionLogger : public Object, public ConnectionLogger { + public: + IMAPConnectionLogger(IMAPAsyncConnection * connection) { + mConnection = connection; + } + + virtual ~IMAPConnectionLogger() { + } + + virtual void log(void * context, void * sender, ConnectionLogType logType, Data * buffer) + { + mConnection->logConnection(logType, buffer); + } + + private: + IMAPAsyncConnection * mConnection; + }; } IMAPAsyncConnection::IMAPAsyncConnection() @@ -70,11 +89,16 @@ IMAPAsyncConnection::IMAPAsyncConnection() mQueueCallback = new IMAPOperationQueueCallback(this); mQueue->setCallback(mQueueCallback); mOwner = NULL; + mConnectionLogger = NULL; + pthread_mutex_init(&mConnectionLoggerLock, NULL); + mInternalLogger = new IMAPConnectionLogger(this); } IMAPAsyncConnection::~IMAPAsyncConnection() { cancelDelayedPerformMethod((Object::Method) &IMAPAsyncConnection::tryAutomaticDisconnectAfterDelay, NULL); + pthread_mutex_destroy(&mConnectionLoggerLock); + MC_SAFE_RELEASE(mInternalLogger); MC_SAFE_RELEASE(mQueueCallback); MC_SAFE_RELEASE(mLastFolder); MC_SAFE_RELEASE(mDefaultNamespace); @@ -122,6 +146,16 @@ String * IMAPAsyncConnection::password() return mSession->password(); } +void IMAPAsyncConnection::setOAuth2Token(String * token) +{ + mSession->setOAuth2Token(token); +} + +String * IMAPAsyncConnection::OAuth2Token() +{ + return mSession->OAuth2Token(); +} + void IMAPAsyncConnection::setAuthType(AuthType authType) { mSession->setAuthType(authType); @@ -526,4 +560,35 @@ IMAPAsyncSession * IMAPAsyncConnection::owner() return mOwner; } +void IMAPAsyncConnection::setConnectionLogger(ConnectionLogger * logger) +{ + pthread_mutex_lock(&mConnectionLoggerLock); + mConnectionLogger = logger; + if (mConnectionLogger != NULL) { + mSession->setConnectionLogger(mInternalLogger); + } + else { + mSession->setConnectionLogger(NULL); + } + pthread_mutex_unlock(&mConnectionLoggerLock); +} +ConnectionLogger * IMAPAsyncConnection::connectionLogger() +{ + ConnectionLogger * result; + + pthread_mutex_lock(&mConnectionLoggerLock); + result = mConnectionLogger; + pthread_mutex_unlock(&mConnectionLoggerLock); + + return result; +} + +void IMAPAsyncConnection::logConnection(ConnectionLogType logType, Data * buffer) +{ + pthread_mutex_lock(&mConnectionLoggerLock); + if (mConnectionLogger != NULL) { + mConnectionLogger->log(this, logType, buffer); + } + pthread_mutex_unlock(&mConnectionLoggerLock); +} diff --git a/src/async/imap/MCIMAPAsyncConnection.h b/src/async/imap/MCIMAPAsyncConnection.h index d6ef6a91..319cc224 100644 --- a/src/async/imap/MCIMAPAsyncConnection.h +++ b/src/async/imap/MCIMAPAsyncConnection.h @@ -8,129 +8,139 @@ #ifdef __cplusplus namespace mailcore { - - class IMAPOperation; - class IMAPFetchFoldersOperation; - class IMAPAppendMessageOperation; - class IMAPCopyMessagesOperation; - class IMAPFetchMessagesOperation; - class IMAPFetchContentOperation; - class IMAPIdleOperation; - class IMAPFolderInfoOperation; - class IMAPFolderStatusOperation; - class IMAPSession; - class IMAPNamespace; - class IMAPSearchOperation; - class IMAPSearchExpression; - class IMAPFetchNamespaceOperation; - class IMAPIdentityOperation; - class IMAPCapabilityOperation; + + class IMAPOperation; + class IMAPFetchFoldersOperation; + class IMAPAppendMessageOperation; + class IMAPCopyMessagesOperation; + class IMAPFetchMessagesOperation; + class IMAPFetchContentOperation; + class IMAPIdleOperation; + class IMAPFolderInfoOperation; + class IMAPFolderStatusOperation; + class IMAPSession; + class IMAPNamespace; + class IMAPSearchOperation; + class IMAPSearchExpression; + class IMAPFetchNamespaceOperation; + class IMAPIdentityOperation; + class IMAPCapabilityOperation; class IMAPOperationQueueCallback; class IMAPAsyncSession; + class IMAPConnectionLogger; - class IMAPAsyncConnection : public Object { - public: - IMAPAsyncConnection(); - virtual ~IMAPAsyncConnection(); - - virtual void setHostname(String * hostname); - virtual String * hostname(); + class IMAPAsyncConnection : public Object { + public: + IMAPAsyncConnection(); + virtual ~IMAPAsyncConnection(); + + virtual void setHostname(String * hostname); + virtual String * hostname(); + + virtual void setPort(unsigned int port); + virtual unsigned int port(); + + virtual void setUsername(String * username); + virtual String * username(); + + virtual void setPassword(String * password); + virtual String * password(); - virtual void setPort(unsigned int port); - virtual unsigned int port(); + virtual void setOAuth2Token(String * token); + virtual String * OAuth2Token(); - virtual void setUsername(String * username); - virtual String * username(); + virtual void setAuthType(AuthType authType); + virtual AuthType authType(); - virtual void setPassword(String * password); - virtual String * password(); + virtual void setConnectionType(ConnectionType connectionType); + virtual ConnectionType connectionType(); - virtual void setAuthType(AuthType authType); - virtual AuthType authType(); + virtual void setTimeout(time_t timeout); + virtual time_t timeout(); - virtual void setConnectionType(ConnectionType connectionType); - virtual ConnectionType connectionType(); + virtual void setCheckCertificateEnabled(bool enabled); + virtual bool isCheckCertificateEnabled(); - virtual void setTimeout(time_t timeout); - virtual time_t timeout(); - - virtual void setCheckCertificateEnabled(bool enabled); - virtual bool isCheckCertificateEnabled(); + virtual void setVoIPEnabled(bool enabled); + virtual bool isVoIPEnabled(); - virtual void setVoIPEnabled(bool enabled); - virtual bool isVoIPEnabled(); + virtual void setDelimiter(char delimiter); + virtual char delimiter(); - virtual void setDelimiter(char delimiter); - virtual char delimiter(); + virtual void setDefaultNamespace(IMAPNamespace * ns); + virtual IMAPNamespace * defaultNamespace(); - virtual void setDefaultNamespace(IMAPNamespace * ns); - virtual IMAPNamespace * defaultNamespace(); + virtual void setConnectionLogger(ConnectionLogger * logger); + virtual ConnectionLogger * connectionLogger(); - virtual IMAPFolderInfoOperation * folderInfoOperation(String * folder); + virtual IMAPFolderInfoOperation * folderInfoOperation(String * folder); virtual IMAPFolderStatusOperation * folderStatusOperation(String * folder); - - virtual IMAPFetchFoldersOperation * fetchSubscribedFoldersOperation(); - virtual IMAPFetchFoldersOperation * fetchAllFoldersOperation(); - - virtual IMAPOperation * renameFolderOperation(String * folder, String * otherName); - virtual IMAPOperation * deleteFolderOperation(String * folder); - virtual IMAPOperation * createFolderOperation(String * folder); - - virtual IMAPOperation * subscribeFolderOperation(String * folder); - virtual IMAPOperation * unsubscribeFolderOperation(String * folder); - - virtual IMAPAppendMessageOperation * appendMessageOperation(String * folder, Data * messageData, MessageFlag flags); - - virtual IMAPCopyMessagesOperation * copyMessagesOperation(String * folder, IndexSet * uids, String * destFolder); - - virtual IMAPOperation * expungeOperation(String * folder); - - virtual IMAPFetchMessagesOperation * fetchMessagesByUIDOperation(String * folder, IMAPMessagesRequestKind requestKind, + + virtual IMAPFetchFoldersOperation * fetchSubscribedFoldersOperation(); + virtual IMAPFetchFoldersOperation * fetchAllFoldersOperation(); + + virtual IMAPOperation * renameFolderOperation(String * folder, String * otherName); + virtual IMAPOperation * deleteFolderOperation(String * folder); + virtual IMAPOperation * createFolderOperation(String * folder); + + virtual IMAPOperation * subscribeFolderOperation(String * folder); + virtual IMAPOperation * unsubscribeFolderOperation(String * folder); + + virtual IMAPAppendMessageOperation * appendMessageOperation(String * folder, Data * messageData, MessageFlag flags); + + virtual IMAPCopyMessagesOperation * copyMessagesOperation(String * folder, IndexSet * uids, String * destFolder); + + virtual IMAPOperation * expungeOperation(String * folder); + + virtual IMAPFetchMessagesOperation * fetchMessagesByUIDOperation(String * folder, IMAPMessagesRequestKind requestKind, IndexSet * uids); - virtual IMAPFetchMessagesOperation * fetchMessagesByNumberOperation(String * folder, IMAPMessagesRequestKind requestKind, + virtual IMAPFetchMessagesOperation * fetchMessagesByNumberOperation(String * folder, IMAPMessagesRequestKind requestKind, IndexSet * numbers); virtual IMAPFetchMessagesOperation * syncMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, IndexSet * uids, uint64_t modSeq); - virtual IMAPFetchContentOperation * fetchMessageByUIDOperation(String * folder, uint32_t uid); - virtual IMAPFetchContentOperation * fetchMessageAttachmentByUIDOperation(String * folder, uint32_t uid, String * partID, + virtual IMAPFetchContentOperation * fetchMessageByUIDOperation(String * folder, uint32_t uid); + virtual IMAPFetchContentOperation * fetchMessageAttachmentByUIDOperation(String * folder, uint32_t uid, String * partID, Encoding encoding); - - virtual IMAPOperation * storeFlagsOperation(String * folder, IndexSet * uids, IMAPStoreFlagsRequestKind kind, MessageFlag flags); - virtual IMAPOperation * storeLabelsOperation(String * folder, IndexSet * uids, IMAPStoreFlagsRequestKind kind, Array * labels); - - virtual IMAPSearchOperation * searchOperation(String * folder, IMAPSearchKind kind, String * searchString); - virtual IMAPSearchOperation * searchOperation(String * folder, IMAPSearchExpression * expression); - - virtual IMAPIdleOperation * idleOperation(String * folder, uint32_t lastKnownUID); - - virtual IMAPFetchNamespaceOperation * fetchNamespaceOperation(); - - virtual IMAPIdentityOperation * identityOperation(String * vendor, String * name, String * version); + + virtual IMAPOperation * storeFlagsOperation(String * folder, IndexSet * uids, IMAPStoreFlagsRequestKind kind, MessageFlag flags); + virtual IMAPOperation * storeLabelsOperation(String * folder, IndexSet * uids, IMAPStoreFlagsRequestKind kind, Array * labels); + + virtual IMAPSearchOperation * searchOperation(String * folder, IMAPSearchKind kind, String * searchString); + virtual IMAPSearchOperation * searchOperation(String * folder, IMAPSearchExpression * expression); + + virtual IMAPIdleOperation * idleOperation(String * folder, uint32_t lastKnownUID); + + virtual IMAPFetchNamespaceOperation * fetchNamespaceOperation(); + + virtual IMAPIdentityOperation * identityOperation(String * vendor, String * name, String * version); virtual IMAPOperation * checkAccountOperation(); virtual IMAPCapabilityOperation * capabilityOperation(); private: - IMAPSession * mSession; - OperationQueue * mQueue; - char mDelimiter; - IMAPNamespace * mDefaultNamespace; - String * mLastFolder; + IMAPSession * mSession; + OperationQueue * mQueue; + char mDelimiter; + IMAPNamespace * mDefaultNamespace; + String * mLastFolder; IMAPOperationQueueCallback * mQueueCallback; - IMAPAsyncSession * mOwner; + IMAPAsyncSession * mOwner; + ConnectionLogger * mConnectionLogger; + IMAPConnectionLogger * mInternalLogger; + pthread_mutex_t mConnectionLoggerLock; virtual void tryAutomaticDisconnectAfterDelay(void * context); - + public: // private - virtual void runOperation(IMAPOperation * operation); - virtual IMAPSession * session(); + virtual void runOperation(IMAPOperation * operation); + virtual IMAPSession * session(); - virtual unsigned int operationsCount(); + virtual unsigned int operationsCount(); - virtual void setLastFolder(String * folder); - virtual String * lastFolder(); + virtual void setLastFolder(String * folder); + virtual String * lastFolder(); virtual void tryAutomaticDisconnect(); virtual void queueStartRunning(); @@ -138,6 +148,8 @@ namespace mailcore { virtual void setOwner(IMAPAsyncSession * owner); virtual IMAPAsyncSession * owner(); + + virtual void logConnection(ConnectionLogType logType, Data * buffer); }; } diff --git a/src/async/imap/MCIMAPAsyncSession.cc b/src/async/imap/MCIMAPAsyncSession.cc index 7c085e4a..6981322e 100644 --- a/src/async/imap/MCIMAPAsyncSession.cc +++ b/src/async/imap/MCIMAPAsyncSession.cc @@ -11,6 +11,7 @@ #include "MCIMAPAsyncConnection.h" #include "MCIMAPNamespace.h" #include "MCOperationQueueCallback.h" +#include "MCConnectionLogger.h" #define DEFAULT_MAX_CONNECTIONS 3 @@ -26,6 +27,7 @@ IMAPAsyncSession::IMAPAsyncSession() mPort = 0; mUsername = NULL; mPassword = NULL; + mOAuth2Token = NULL; mAuthType = AuthTypeSASLNone; mConnectionType = ConnectionTypeClear; mCheckCertificateEnabled = true; @@ -33,11 +35,17 @@ IMAPAsyncSession::IMAPAsyncSession() mDelimiter = 0; mDefaultNamespace = NULL; mTimeout = 30.; + mConnectionLogger = NULL; } IMAPAsyncSession::~IMAPAsyncSession() { MC_SAFE_RELEASE(mSessions); + MC_SAFE_RELEASE(mHostname); + MC_SAFE_RELEASE(mUsername); + MC_SAFE_RELEASE(mPassword); + MC_SAFE_RELEASE(mOAuth2Token); + MC_SAFE_RELEASE(mDefaultNamespace); } void IMAPAsyncSession::setHostname(String * hostname) @@ -80,6 +88,16 @@ String * IMAPAsyncSession::password() return mPassword; } +void IMAPAsyncSession::setOAuth2Token(String * token) +{ + MC_SAFE_REPLACE_COPY(String, mOAuth2Token, token); +} + +String * IMAPAsyncSession::OAuth2Token() +{ + return mOAuth2Token; +} + void IMAPAsyncSession::setAuthType(AuthType authType) { mAuthType = authType; @@ -174,6 +192,7 @@ unsigned int IMAPAsyncSession::maximumConnections() IMAPAsyncConnection * IMAPAsyncSession::session() { IMAPAsyncConnection * session = new IMAPAsyncConnection(); + session->setConnectionLogger(mConnectionLogger); session->setOwner(this); session->autorelease(); @@ -181,6 +200,7 @@ IMAPAsyncConnection * IMAPAsyncSession::session() session->setPort(mPort); session->setUsername(mUsername); session->setPassword(mPassword); + session->setOAuth2Token(mOAuth2Token); session->setAuthType(mAuthType); session->setConnectionType(mConnectionType); session->setTimeout(mTimeout); @@ -429,3 +449,16 @@ IMAPCapabilityOperation * IMAPAsyncSession::capabilityOperation() return session->capabilityOperation(); } +void IMAPAsyncSession::setConnectionLogger(ConnectionLogger * logger) +{ + mConnectionLogger = logger; + for(unsigned int i = 0 ; i < mSessions->count() ; i ++) { + IMAPAsyncConnection * currentSession = (IMAPAsyncConnection *) mSessions->objectAtIndex(i); + currentSession->setConnectionLogger(logger); + } +} + +ConnectionLogger * IMAPAsyncSession::connectionLogger() +{ + return mConnectionLogger; +} diff --git a/src/async/imap/MCIMAPAsyncSession.h b/src/async/imap/MCIMAPAsyncSession.h index 390fdab8..ae1bbb90 100644 --- a/src/async/imap/MCIMAPAsyncSession.h +++ b/src/async/imap/MCIMAPAsyncSession.h @@ -51,6 +51,11 @@ namespace mailcore { virtual void setPassword(String * password); virtual String * password(); + // To authenticate using OAuth2, username and oauth2token should be set. + // auth type to use is AuthTypeOAuth2. + virtual void setOAuth2Token(String * token); + virtual String * OAuth2Token(); + virtual void setAuthType(AuthType authType); virtual AuthType authType(); @@ -78,6 +83,9 @@ namespace mailcore { virtual void setMaximumConnections(unsigned int maxConnections); virtual unsigned int maximumConnections(); + virtual void setConnectionLogger(ConnectionLogger * logger); + virtual ConnectionLogger * connectionLogger(); + virtual IMAPFolderInfoOperation * folderInfoOperation(String * folder); virtual IMAPFolderStatusOperation * folderStatusOperation(String * folder); @@ -124,7 +132,7 @@ namespace mailcore { virtual IMAPOperation * checkAccountOperation(); virtual IMAPCapabilityOperation * capabilityOperation(); - + private: Array * mSessions; @@ -132,6 +140,7 @@ namespace mailcore { unsigned int mPort; String * mUsername; String * mPassword; + String * mOAuth2Token; AuthType mAuthType; ConnectionType mConnectionType; bool mCheckCertificateEnabled; @@ -141,6 +150,7 @@ namespace mailcore { time_t mTimeout; bool mAllowsFolderConcurrentAccessEnabled; unsigned int mMaximumConnections; + ConnectionLogger * mConnectionLogger; virtual IMAPAsyncConnection * sessionForFolder(String * folder, bool urgent = false); virtual IMAPAsyncConnection * session(); diff --git a/src/async/pop/MCPOPAsyncSession.cc b/src/async/pop/MCPOPAsyncSession.cc index 1269a34b..342b0f5e 100644 --- a/src/async/pop/MCPOPAsyncSession.cc +++ b/src/async/pop/MCPOPAsyncSession.cc @@ -15,6 +15,7 @@ #include "MCPOPFetchMessagesOperation.h" #include "MCPOPCheckAccountOperation.h" #include "MCOperationQueueCallback.h" +#include "MCConnectionLogger.h" using namespace mailcore; @@ -28,17 +29,35 @@ namespace mailcore { virtual ~POPOperationQueueCallback() { } - virtual void queueStartRunning() { + virtual void queueStartRunning(OperationQueue * queue) { mSession->retain(); } - virtual void queueStoppedRunning() { + virtual void queueStoppedRunning(OperationQueue * queue) { mSession->release(); } private: POPAsyncSession * mSession; }; + + class POPConnectionLogger : public Object, public ConnectionLogger { + public: + POPConnectionLogger(POPAsyncSession * session) { + mSession = session; + } + + virtual ~POPConnectionLogger() { + } + + virtual void log(void * context, void * sender, ConnectionLogType logType, Data * buffer) + { + mSession->logConnection(logType, buffer); + } + + private: + POPAsyncSession * mSession; + }; } POPAsyncSession::POPAsyncSession() @@ -47,10 +66,16 @@ POPAsyncSession::POPAsyncSession() mQueue = new OperationQueue(); mQueueCallback = new POPOperationQueueCallback(this); mQueue->setCallback(mQueueCallback); + mConnectionLogger = NULL; + pthread_mutex_init(&mConnectionLoggerLock, NULL); + mInternalLogger = new POPConnectionLogger(this); + mSession->setConnectionLogger(mInternalLogger); } POPAsyncSession::~POPAsyncSession() { + MC_SAFE_RELEASE(mInternalLogger); + pthread_mutex_destroy(&mConnectionLoggerLock); MC_SAFE_RELEASE(mQueueCallback); MC_SAFE_RELEASE(mSession); MC_SAFE_RELEASE(mQueue); @@ -193,3 +218,36 @@ void POPAsyncSession::runOperation(POPOperation * operation) { mQueue->addOperation(operation); } + +void POPAsyncSession::setConnectionLogger(ConnectionLogger * logger) +{ + pthread_mutex_lock(&mConnectionLoggerLock); + mConnectionLogger = logger; + if (mConnectionLogger != NULL) { + mSession->setConnectionLogger(mInternalLogger); + } + else { + mSession->setConnectionLogger(NULL); + } + pthread_mutex_unlock(&mConnectionLoggerLock); +} + +ConnectionLogger * POPAsyncSession::connectionLogger() +{ + ConnectionLogger * result; + + pthread_mutex_lock(&mConnectionLoggerLock); + result = mConnectionLogger; + pthread_mutex_unlock(&mConnectionLoggerLock); + + return result; +} + +void POPAsyncSession::logConnection(ConnectionLogType logType, Data * buffer) +{ + pthread_mutex_lock(&mConnectionLoggerLock); + if (mConnectionLogger != NULL) { + mConnectionLogger->log(this, logType, buffer); + } + pthread_mutex_unlock(&mConnectionLoggerLock); +} diff --git a/src/async/pop/MCPOPAsyncSession.h b/src/async/pop/MCPOPAsyncSession.h index 452d4d75..0345ecd6 100644 --- a/src/async/pop/MCPOPAsyncSession.h +++ b/src/async/pop/MCPOPAsyncSession.h @@ -23,6 +23,7 @@ namespace mailcore { class POPDeleteMessagesOperation; class POPFetchMessagesOperation; class POPOperationQueueCallback; + class POPConnectionLogger; class POPAsyncSession : public Object { public: @@ -53,6 +54,9 @@ namespace mailcore { virtual void setCheckCertificateEnabled(bool enabled); virtual bool isCheckCertificateEnabled(); + virtual void setConnectionLogger(ConnectionLogger * logger); + virtual ConnectionLogger * connectionLogger(); + virtual POPFetchMessagesOperation * fetchMessagesOperation(); virtual POPFetchHeaderOperation * fetchHeaderOperation(unsigned int index); @@ -70,11 +74,14 @@ namespace mailcore { POPSession * mSession; OperationQueue * mQueue; POPOperationQueueCallback * mQueueCallback; + ConnectionLogger * mConnectionLogger; + pthread_mutex_t mConnectionLoggerLock; + POPConnectionLogger * mInternalLogger; public: // private virtual void runOperation(POPOperation * operation); virtual POPSession * session(); - + virtual void logConnection(ConnectionLogType logType, Data * buffer); }; } diff --git a/src/async/smtp/MCSMTPAsyncSession.cc b/src/async/smtp/MCSMTPAsyncSession.cc index 723c0330..fafc2e82 100644 --- a/src/async/smtp/MCSMTPAsyncSession.cc +++ b/src/async/smtp/MCSMTPAsyncSession.cc @@ -19,11 +19,11 @@ namespace mailcore { virtual ~SMTPOperationQueueCallback() { } - virtual void queueStartRunning() { + virtual void queueStartRunning(OperationQueue * queue) { mSession->retain(); } - virtual void queueStoppedRunning() { + virtual void queueStoppedRunning(OperationQueue * queue) { mSession->tryAutomaticDisconnect(); mSession->release(); } @@ -31,6 +31,24 @@ namespace mailcore { private: SMTPAsyncSession * mSession; }; + + class SMTPConnectionLogger : public Object, public ConnectionLogger { + public: + SMTPConnectionLogger(SMTPAsyncSession * session) { + mSession = session; + } + + virtual ~SMTPConnectionLogger() { + } + + virtual void log(void * context, void * sender, ConnectionLogType logType, Data * buffer) + { + mSession->logConnection(logType, buffer); + } + + private: + SMTPAsyncSession * mSession; + }; } SMTPAsyncSession::SMTPAsyncSession() @@ -39,10 +57,16 @@ SMTPAsyncSession::SMTPAsyncSession() mQueue = new OperationQueue(); mQueueCallback = new SMTPOperationQueueCallback(this); mQueue->setCallback(mQueueCallback); + mConnectionLogger = NULL; + pthread_mutex_init(&mConnectionLoggerLock, NULL); + mInternalLogger = new SMTPConnectionLogger(this); + mSession->setConnectionLogger(mInternalLogger); } SMTPAsyncSession::~SMTPAsyncSession() { + MC_SAFE_RELEASE(mInternalLogger); + pthread_mutex_destroy(&mConnectionLoggerLock); cancelDelayedPerformMethod((Object::Method) &SMTPAsyncSession::tryAutomaticDisconnectAfterDelay, NULL); MC_SAFE_RELEASE(mQueueCallback); MC_SAFE_RELEASE(mQueue); @@ -184,3 +208,36 @@ SMTPOperation * SMTPAsyncSession::checkAccountOperation(Address * from) op->setSession(this); return (SMTPOperation *) op->autorelease(); } + +void SMTPAsyncSession::setConnectionLogger(ConnectionLogger * logger) +{ + pthread_mutex_lock(&mConnectionLoggerLock); + mConnectionLogger = logger; + if (mConnectionLogger != NULL) { + mSession->setConnectionLogger(mInternalLogger); + } + else { + mSession->setConnectionLogger(NULL); + } + pthread_mutex_unlock(&mConnectionLoggerLock); +} + +ConnectionLogger * SMTPAsyncSession::connectionLogger() +{ + ConnectionLogger * result; + + pthread_mutex_lock(&mConnectionLoggerLock); + result = mConnectionLogger; + pthread_mutex_unlock(&mConnectionLoggerLock); + + return result; +} + +void SMTPAsyncSession::logConnection(ConnectionLogType logType, Data * buffer) +{ + pthread_mutex_lock(&mConnectionLoggerLock); + if (mConnectionLogger != NULL) { + mConnectionLogger->log(this, logType, buffer); + } + pthread_mutex_unlock(&mConnectionLoggerLock); +} diff --git a/src/async/smtp/MCSMTPAsyncSession.h b/src/async/smtp/MCSMTPAsyncSession.h index 9cd7a8f0..9fa6dbdf 100644 --- a/src/async/smtp/MCSMTPAsyncSession.h +++ b/src/async/smtp/MCSMTPAsyncSession.h @@ -14,6 +14,7 @@ namespace mailcore { class SMTPSession; class Address; class SMTPOperationQueueCallback; + class SMTPConnectionLogger; class SMTPAsyncSession : public Object { public: @@ -47,6 +48,9 @@ namespace mailcore { virtual void setUseHeloIPEnabled(bool enabled); virtual bool useHeloIPEnabled(); + virtual void setConnectionLogger(ConnectionLogger * logger); + virtual ConnectionLogger * connectionLogger(); + virtual SMTPOperation * sendMessageOperation(Data * messageData); virtual SMTPOperation * checkAccountOperation(Address * from); @@ -54,11 +58,15 @@ namespace mailcore { virtual void runOperation(SMTPOperation * operation); virtual SMTPSession * session(); virtual void tryAutomaticDisconnect(); - + virtual void logConnection(ConnectionLogType logType, Data * buffer); + private: SMTPSession * mSession; OperationQueue * mQueue; SMTPOperationQueueCallback * mQueueCallback; + ConnectionLogger * mConnectionLogger; + pthread_mutex_t mConnectionLoggerLock; + SMTPConnectionLogger * mInternalLogger; virtual void tryAutomaticDisconnectAfterDelay(void * context); }; diff --git a/src/core/abstract/MCMessageConstants.h b/src/core/abstract/MCMessageConstants.h index 417bdb6c..9e1b46b7 100644 --- a/src/core/abstract/MCMessageConstants.h +++ b/src/core/abstract/MCMessageConstants.h @@ -4,214 +4,215 @@ #ifdef __cplusplus namespace mailcore { - - enum ConnectionType { - ConnectionTypeClear = 1 << 0, - ConnectionTypeStartTLS = 1 << 1, - ConnectionTypeTLS = 1 << 2, - }; + + enum ConnectionType { + ConnectionTypeClear = 1 << 0, + ConnectionTypeStartTLS = 1 << 1, + ConnectionTypeTLS = 1 << 2, + }; - enum AuthType { - AuthTypeSASLNone = 0, - AuthTypeSASLCRAMMD5 = 1 << 0, - AuthTypeSASLPlain = 1 << 1, - AuthTypeSASLGSSAPI = 1 << 2, - AuthTypeSASLDIGESTMD5 = 1 << 3, - AuthTypeSASLLogin = 1 << 4, - AuthTypeSASLSRP = 1 << 5, - AuthTypeSASLNTLM = 1 << 6, - AuthTypeSASLKerberosV4 = 1 << 7, - }; + enum AuthType { + AuthTypeSASLNone = 0, + AuthTypeSASLCRAMMD5 = 1 << 0, + AuthTypeSASLPlain = 1 << 1, + AuthTypeSASLGSSAPI = 1 << 2, + AuthTypeSASLDIGESTMD5 = 1 << 3, + AuthTypeSASLLogin = 1 << 4, + AuthTypeSASLSRP = 1 << 5, + AuthTypeSASLNTLM = 1 << 6, + AuthTypeSASLKerberosV4 = 1 << 7, + AuthTypeXOAuth2 = 1 << 8, + }; - enum IMAPFolderFlag { - IMAPFolderFlagNone = 0, - IMAPFolderFlagMarked = 1 << 0, - IMAPFolderFlagUnmarked = 1 << 1, - IMAPFolderFlagNoSelect = 1 << 2, - IMAPFolderFlagNoInferiors = 1 << 3, - IMAPFolderFlagInbox = 1 << 4, - IMAPFolderFlagSentMail = 1 << 5, - IMAPFolderFlagStarred = 1 << 6, - IMAPFolderFlagAllMail = 1 << 7, - IMAPFolderFlagTrash = 1 << 8, - IMAPFolderFlagDrafts = 1 << 9, - IMAPFolderFlagSpam = 1 << 10, - IMAPFolderFlagImportant = 1 << 11, - IMAPFolderFlagArchive = 1 << 12, + enum IMAPFolderFlag { + IMAPFolderFlagNone = 0, + IMAPFolderFlagMarked = 1 << 0, + IMAPFolderFlagUnmarked = 1 << 1, + IMAPFolderFlagNoSelect = 1 << 2, + IMAPFolderFlagNoInferiors = 1 << 3, + IMAPFolderFlagInbox = 1 << 4, + IMAPFolderFlagSentMail = 1 << 5, + IMAPFolderFlagStarred = 1 << 6, + IMAPFolderFlagAllMail = 1 << 7, + IMAPFolderFlagTrash = 1 << 8, + IMAPFolderFlagDrafts = 1 << 9, + IMAPFolderFlagSpam = 1 << 10, + IMAPFolderFlagImportant = 1 << 11, + IMAPFolderFlagArchive = 1 << 12, IMAPFolderFlagAll = IMAPFolderFlagAllMail, IMAPFolderFlagJunk = IMAPFolderFlagSpam, IMAPFolderFlagFlagged = IMAPFolderFlagStarred, - }; + }; - enum MessageFlag { - MessageFlagNone = 0, - MessageFlagSeen = 1 << 0, - MessageFlagAnswered = 1 << 1, - MessageFlagFlagged = 1 << 2, - MessageFlagDeleted = 1 << 3, - MessageFlagDraft = 1 << 4, - MessageFlagMDNSent = 1 << 5, - MessageFlagForwarded = 1 << 6, - MessageFlagSubmitPending = 1 << 7, - MessageFlagSubmitted = 1 << 8, - } ; + enum MessageFlag { + MessageFlagNone = 0, + MessageFlagSeen = 1 << 0, + MessageFlagAnswered = 1 << 1, + MessageFlagFlagged = 1 << 2, + MessageFlagDeleted = 1 << 3, + MessageFlagDraft = 1 << 4, + MessageFlagMDNSent = 1 << 5, + MessageFlagForwarded = 1 << 6, + MessageFlagSubmitPending = 1 << 7, + MessageFlagSubmitted = 1 << 8, + } ; - enum IMAPMessagesRequestKind { - IMAPMessagesRequestKindUid = 0, // This is the default and it's always fetched - IMAPMessagesRequestKindFlags = 1 << 0, - IMAPMessagesRequestKindHeaders = 1 << 1, - IMAPMessagesRequestKindStructure = 1 << 2, - IMAPMessagesRequestKindInternalDate = 1 << 3, - IMAPMessagesRequestKindFullHeaders = 1 << 4, - IMAPMessagesRequestKindHeaderSubject = 1 << 5, - IMAPMessagesRequestKindGmailLabels = 1 << 6, - IMAPMessagesRequestKindGmailMessageID = 1 << 7, - IMAPMessagesRequestKindGmailThreadID = 1 << 8, - }; + enum IMAPMessagesRequestKind { + IMAPMessagesRequestKindUid = 0, // This is the default and it's always fetched + IMAPMessagesRequestKindFlags = 1 << 0, + IMAPMessagesRequestKindHeaders = 1 << 1, + IMAPMessagesRequestKindStructure = 1 << 2, + IMAPMessagesRequestKindInternalDate = 1 << 3, + IMAPMessagesRequestKindFullHeaders = 1 << 4, + IMAPMessagesRequestKindHeaderSubject = 1 << 5, + IMAPMessagesRequestKindGmailLabels = 1 << 6, + IMAPMessagesRequestKindGmailMessageID = 1 << 7, + IMAPMessagesRequestKindGmailThreadID = 1 << 8, + }; - enum IMAPFetchRequestType { - IMAPFetchRequestTypeUID = 0, - IMAPFetchRequestTypeSequence = 1 - }; + enum IMAPFetchRequestType { + IMAPFetchRequestTypeUID = 0, + IMAPFetchRequestTypeSequence = 1 + }; - enum IMAPStoreFlagsRequestKind { - IMAPStoreFlagsRequestKindAdd, - IMAPStoreFlagsRequestKindRemove, - IMAPStoreFlagsRequestKindSet, - }; + enum IMAPStoreFlagsRequestKind { + IMAPStoreFlagsRequestKindAdd, + IMAPStoreFlagsRequestKindRemove, + IMAPStoreFlagsRequestKindSet, + }; - enum IMAPWorkaround { - IMAPWorkaroundGmail = 1 << 0, - IMAPWorkaroundYahoo = 1 << 1, - IMAPWorkaroundExchange2003 = 1 << 2, - }; + enum IMAPWorkaround { + IMAPWorkaroundGmail = 1 << 0, + IMAPWorkaroundYahoo = 1 << 1, + IMAPWorkaroundExchange2003 = 1 << 2, + }; - enum IMAPCapability { - IMAPCapabilityACL, - IMAPCapabilityBinary, - IMAPCapabilityCatenate, - IMAPCapabilityChildren, - IMAPCapabilityCompressDeflate, - IMAPCapabilityCondstore, - IMAPCapabilityEnable, - IMAPCapabilityIdle, - IMAPCapabilityId, - IMAPCapabilityLiteralPlus, - IMAPCapabilityMultiAppend, - IMAPCapabilityNamespace, - IMAPCapabilityQResync, - IMAPCapabilityQuota, - IMAPCapabilitySort, - IMAPCapabilityStartTLS, - IMAPCapabilityThreadOrderedSubject, - IMAPCapabilityThreadReferences, - IMAPCapabilityUIDPlus, - IMAPCapabilityUnselect, - IMAPCapabilityXList, - IMAPCapabilityAuthAnonymous, - IMAPCapabilityAuthCRAMMD5, - IMAPCapabilityAuthDigestMD5, - IMAPCapabilityAuthExternal, - IMAPCapabilityAuthGSSAPI, - IMAPCapabilityAuthKerberosV4, - IMAPCapabilityAuthLogin, - IMAPCapabilityAuthNTLM, - IMAPCapabilityAuthOTP, - IMAPCapabilityAuthPlain, - IMAPCapabilityAuthSKey, - IMAPCapabilityAuthSRP, - }; + enum IMAPCapability { + IMAPCapabilityACL, + IMAPCapabilityBinary, + IMAPCapabilityCatenate, + IMAPCapabilityChildren, + IMAPCapabilityCompressDeflate, + IMAPCapabilityCondstore, + IMAPCapabilityEnable, + IMAPCapabilityIdle, + IMAPCapabilityId, + IMAPCapabilityLiteralPlus, + IMAPCapabilityMultiAppend, + IMAPCapabilityNamespace, + IMAPCapabilityQResync, + IMAPCapabilityQuota, + IMAPCapabilitySort, + IMAPCapabilityStartTLS, + IMAPCapabilityThreadOrderedSubject, + IMAPCapabilityThreadReferences, + IMAPCapabilityUIDPlus, + IMAPCapabilityUnselect, + IMAPCapabilityXList, + IMAPCapabilityAuthAnonymous, + IMAPCapabilityAuthCRAMMD5, + IMAPCapabilityAuthDigestMD5, + IMAPCapabilityAuthExternal, + IMAPCapabilityAuthGSSAPI, + IMAPCapabilityAuthKerberosV4, + IMAPCapabilityAuthLogin, + IMAPCapabilityAuthNTLM, + IMAPCapabilityAuthOTP, + IMAPCapabilityAuthPlain, + IMAPCapabilityAuthSKey, + IMAPCapabilityAuthSRP, + }; - enum POPCapability { - POPCapabilityNone, - POPCapabilityStartTLS, - POPCapabilityTop, - POPCapabilityUser, - POPCapabilityRespCodes, - POPCapabilityPipelining, - POPCapabilityUIDL, - POPCapabilitySASL, - POPCapabilityAuthAnonymous, - POPCapabilityAuthCRAMMD5, - POPCapabilityAuthDigestMD5, - POPCapabilityAuthExternal, - POPCapabilityAuthGSSAPI, - POPCapabilityAuthKerberosV4, - POPCapabilityAuthLogin, - POPCapabilityAuthNTLM, - POPCapabilityAuthOTP, - POPCapabilityAuthPlain, - POPCapabilityAuthSKey, - POPCapabilityAuthSRP, - }; + enum POPCapability { + POPCapabilityNone, + POPCapabilityStartTLS, + POPCapabilityTop, + POPCapabilityUser, + POPCapabilityRespCodes, + POPCapabilityPipelining, + POPCapabilityUIDL, + POPCapabilitySASL, + POPCapabilityAuthAnonymous, + POPCapabilityAuthCRAMMD5, + POPCapabilityAuthDigestMD5, + POPCapabilityAuthExternal, + POPCapabilityAuthGSSAPI, + POPCapabilityAuthKerberosV4, + POPCapabilityAuthLogin, + POPCapabilityAuthNTLM, + POPCapabilityAuthOTP, + POPCapabilityAuthPlain, + POPCapabilityAuthSKey, + POPCapabilityAuthSRP, + }; - enum Encoding { - Encoding7Bit = 0, // should match MAILIMAP_BODY_FLD_ENC_7BIT - Encoding8Bit = 1, // should match MAILIMAP_BODY_FLD_ENC_8BIT - EncodingBinary = 2, // should match MAILIMAP_BODY_FLD_ENC_BINARY - EncodingBase64 = 3, // should match MAILIMAP_BODY_FLD_ENC_BASE64 - EncodingQuotedPrintable = 4, // should match MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE - EncodingOther = 5, // should match MAILIMAP_BODY_FLD_ENC_OTHER - // negative values should be used for other encoding - EncodingUUEncode = -1 - }; - - enum IMAPSearchKind { - IMAPSearchKindNone, - IMAPSearchKindFrom, - IMAPSearchKindRecipient, - IMAPSearchKindSubject, - IMAPSearchKindContent, - IMAPSearchKindHeader, - IMAPSearchKindOr, - IMAPSearchKindAnd, - }; - - enum ErrorCode { - ErrorNone, - ErrorConnection, - ErrorTLSNotAvailable, - ErrorParse, - ErrorCertificate, - ErrorAuthentication, - ErrorGmailIMAPNotEnabled, - ErrorGmailExceededBandwidthLimit, - ErrorGmailTooManySimultaneousConnections, - ErrorMobileMeMoved, - ErrorYahooUnavailable, - ErrorNonExistantFolder, - ErrorRename, - ErrorDelete, - ErrorCreate, - ErrorSubscribe, - ErrorAppend, - ErrorCopy, - ErrorExpunge, - ErrorFetch, - ErrorIdle, - ErrorIdentity, - ErrorNamespace, - ErrorStore, + enum Encoding { + Encoding7Bit = 0, // should match MAILIMAP_BODY_FLD_ENC_7BIT + Encoding8Bit = 1, // should match MAILIMAP_BODY_FLD_ENC_8BIT + EncodingBinary = 2, // should match MAILIMAP_BODY_FLD_ENC_BINARY + EncodingBase64 = 3, // should match MAILIMAP_BODY_FLD_ENC_BASE64 + EncodingQuotedPrintable = 4, // should match MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE + EncodingOther = 5, // should match MAILIMAP_BODY_FLD_ENC_OTHER + // negative values should be used for other encoding + EncodingUUEncode = -1 + }; + + enum IMAPSearchKind { + IMAPSearchKindNone, + IMAPSearchKindFrom, + IMAPSearchKindRecipient, + IMAPSearchKindSubject, + IMAPSearchKindContent, + IMAPSearchKindHeader, + IMAPSearchKindOr, + IMAPSearchKindAnd, + }; + + enum ErrorCode { + ErrorNone, + ErrorConnection, + ErrorTLSNotAvailable, + ErrorParse, + ErrorCertificate, + ErrorAuthentication, + ErrorGmailIMAPNotEnabled, + ErrorGmailExceededBandwidthLimit, + ErrorGmailTooManySimultaneousConnections, + ErrorMobileMeMoved, + ErrorYahooUnavailable, + ErrorNonExistantFolder, + ErrorRename, + ErrorDelete, + ErrorCreate, + ErrorSubscribe, + ErrorAppend, + ErrorCopy, + ErrorExpunge, + ErrorFetch, + ErrorIdle, + ErrorIdentity, + ErrorNamespace, + ErrorStore, ErrorCapability, - ErrorStartTLSNotAvailable, - ErrorSendMessageIllegalAttachment, - ErrorStorageLimit, - ErrorSendMessageNotAllowed, - ErrorNeedsConnectToWebmail, - ErrorSendMessage, - ErrorAuthenticationRequired, - ErrorFetchMessageList, - ErrorDeleteMessage, + ErrorStartTLSNotAvailable, + ErrorSendMessageIllegalAttachment, + ErrorStorageLimit, + ErrorSendMessageNotAllowed, + ErrorNeedsConnectToWebmail, + ErrorSendMessage, + ErrorAuthenticationRequired, + ErrorFetchMessageList, + ErrorDeleteMessage, ErrorInvalidAccount, - }; - - enum PartType { - PartTypeSingle, - PartTypeMessage, - PartTypeMultipartMixed, - PartTypeMultipartRelated, - PartTypeMultipartAlternative, - }; + }; + + enum PartType { + PartTypeSingle, + PartTypeMessage, + PartTypeMultipartMixed, + PartTypeMultipartRelated, + PartTypeMultipartAlternative, + }; } #endif diff --git a/src/core/basetypes/MCConnectionLogger.h b/src/core/basetypes/MCConnectionLogger.h index 8083d12d..dd596857 100644 --- a/src/core/basetypes/MCConnectionLogger.h +++ b/src/core/basetypes/MCConnectionLogger.h @@ -9,6 +9,8 @@ #ifndef __MAILCORE_CONNECTION_LOGGER_H_ #define __MAILCORE_CONNECTION_LOGGER_H_ +#include <stdlib.h> + #ifdef __cplusplus namespace mailcore { @@ -17,20 +19,23 @@ namespace mailcore { class String; enum ConnectionLogType { - ConnectionLogTypeGeneric, + // Received data ConnectionLogTypeReceived, + // Sent data ConnectionLogTypeSent, + // Sent private data ConnectionLogTypeSentPrivate, - ConnectionLogTypeErrorGeneric, + // Parse error + ConnectionLogTypeErrorParse, + // Error while receiving data - log() is called with a NULL buffer. ConnectionLogTypeErrorReceived, + // Error while sending data - log() is called with a NULL buffer. ConnectionLogTypeErrorSent, - ConnectionLogTypeErrorSentPrivate, }; class ConnectionLogger { public: - virtual void logBuffer(ConnectionLogType logType, Data * buffer) {} - virtual void logString(ConnectionLogType logType, String * log) {} + virtual void log(void * sender, ConnectionLogType logType, Data * buffer) {} }; } diff --git a/src/core/basetypes/MCConnectionLoggerUtils.cc b/src/core/basetypes/MCConnectionLoggerUtils.cc index 669c8449..234713e7 100644 --- a/src/core/basetypes/MCConnectionLoggerUtils.cc +++ b/src/core/basetypes/MCConnectionLoggerUtils.cc @@ -14,21 +14,12 @@ mailcore::ConnectionLogType mailcore::getConnectionType(int log_type) { - ConnectionLogType type = ConnectionLogTypeGeneric; + ConnectionLogType type = (ConnectionLogType) -1; bool isBuffer = false; switch (log_type) { - case MAILSTREAM_LOG_TYPE_INFO_GENERIC: - type = ConnectionLogTypeGeneric; - break; - case MAILSTREAM_LOG_TYPE_INFO_RECEIVED: - type = ConnectionLogTypeReceived; - break; - case MAILSTREAM_LOG_TYPE_INFO_SENT: - type = ConnectionLogTypeSent; - break; - case MAILSTREAM_LOG_TYPE_ERROR_GENERIC: - type = ConnectionLogTypeErrorGeneric; + case MAILSTREAM_LOG_TYPE_ERROR_PARSE: + type = ConnectionLogTypeErrorParse; isBuffer = true; break; case MAILSTREAM_LOG_TYPE_ERROR_RECEIVED: @@ -60,9 +51,7 @@ bool mailcore::isBufferFromLogType(int log_type) bool isBuffer = false; switch (log_type) { - case MAILSTREAM_LOG_TYPE_ERROR_GENERIC: - case MAILSTREAM_LOG_TYPE_ERROR_RECEIVED: - case MAILSTREAM_LOG_TYPE_ERROR_SENT: + case MAILSTREAM_LOG_TYPE_ERROR_PARSE: case MAILSTREAM_LOG_TYPE_DATA_RECEIVED: case MAILSTREAM_LOG_TYPE_DATA_SENT: case MAILSTREAM_LOG_TYPE_DATA_SENT_PRIVATE: diff --git a/src/core/basetypes/MCHTMLCleaner.cc b/src/core/basetypes/MCHTMLCleaner.cc index 12f1371e..7d45d3f2 100644 --- a/src/core/basetypes/MCHTMLCleaner.cc +++ b/src/core/basetypes/MCHTMLCleaner.cc @@ -68,6 +68,7 @@ String * HTMLCleaner::cleanHTML(String * input) String * result = String::stringWithUTF8Characters((const char *) output.bp); + tidyBufFree(&docbuf); tidyBufFree(&output); tidyBufFree(&errbuf); tidyRelease(tdoc); diff --git a/src/core/basetypes/MCLibetpan.cpp b/src/core/basetypes/MCLibetpan.cpp new file mode 100644 index 00000000..c8258cc2 --- /dev/null +++ b/src/core/basetypes/MCLibetpan.cpp @@ -0,0 +1,16 @@ +// +// MCLibetpan.cpp +// mailcore2 +// +// Created by Hoa Dinh on 6/28/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCLibetpan.h" + +#include <libetpan/libetpan.h> + +__attribute__((constructor)) +static void initialize() { + mailstream_cfstream_enabled = 1; +} diff --git a/src/core/basetypes/MCLibetpan.h b/src/core/basetypes/MCLibetpan.h new file mode 100644 index 00000000..ef7db1f8 --- /dev/null +++ b/src/core/basetypes/MCLibetpan.h @@ -0,0 +1,14 @@ +// +// MCLibetpan.h +// mailcore2 +// +// Created by Hoa Dinh on 6/28/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef __MAILCORE_MCLIBETPAN_H_ +#define __MAILCORE_MCLIBETPAN_H_ + +// No API in this file. + +#endif diff --git a/src/core/basetypes/MCObject.cc b/src/core/basetypes/MCObject.cc index 879c194f..235738cd 100644 --- a/src/core/basetypes/MCObject.cc +++ b/src/core/basetypes/MCObject.cc @@ -83,7 +83,9 @@ String * Object::className() { int status; char * unmangled = abi::__cxa_demangle(typeid(* this).name(), NULL, NULL, &status); - return mailcore::String::uniquedStringWithUTF8Characters(unmangled); + String * result = String::uniquedStringWithUTF8Characters(unmangled); + free(unmangled); + return result; } String * Object::description() diff --git a/src/core/basetypes/MCOperationQueue.cc b/src/core/basetypes/MCOperationQueue.cc index d4529fab..9c30ad22 100644 --- a/src/core/basetypes/MCOperationQueue.cc +++ b/src/core/basetypes/MCOperationQueue.cc @@ -159,7 +159,7 @@ void OperationQueue::stoppedOnMainThread(void * context) mStarted = false; if (mCallback) { - mCallback->queueStoppedRunning(); + mCallback->queueStoppedRunning(this); } release(); // (2) @@ -173,7 +173,7 @@ void OperationQueue::startThread() return; if (mCallback) { - mCallback->queueStartRunning(); + mCallback->queueStartRunning(this); } retain(); // (3) diff --git a/src/core/basetypes/MCOperationQueueCallback.h b/src/core/basetypes/MCOperationQueueCallback.h index 367888bb..605de030 100644 --- a/src/core/basetypes/MCOperationQueueCallback.h +++ b/src/core/basetypes/MCOperationQueueCallback.h @@ -15,8 +15,8 @@ namespace mailcore { class OperationQueueCallback { public: - virtual void queueStartRunning() {} - virtual void queueStoppedRunning() {} + virtual void queueStartRunning(OperationQueue * queue) {} + virtual void queueStoppedRunning(OperationQueue * queue) {} }; } diff --git a/src/core/basetypes/MCString.cc b/src/core/basetypes/MCString.cc index 832ffac2..034e3299 100644 --- a/src/core/basetypes/MCString.cc +++ b/src/core/basetypes/MCString.cc @@ -10,6 +10,9 @@ #include <libetpan/libetpan.h> #include <libxml/xmlmemory.h> #include <libxml/HTMLparser.h> +#if __APPLE__ +#include <CoreFoundation/CoreFoundation.h> +#endif #include "MCData.h" #include "MCHash.h" @@ -781,7 +784,9 @@ String * String::stringWithVUTF8Format(const char * format, va_list ap) { char * result; vasprintf(&result, format, ap); - return stringWithUTF8Characters(result); + String * str = stringWithUTF8Characters(result); + free(result); + return str; } String * String::stringWithUTF8Characters(const char * UTF8Characters) @@ -1121,6 +1126,20 @@ String * String::uppercaseString() void String::appendBytes(const char * bytes, unsigned int length, const char * charset) { +#if __APPLE__ + CFStringRef encodingName = CFStringCreateWithCString(NULL, charset, kCFStringEncodingUTF8); + CFStringEncoding encoding = CFStringConvertIANACharSetNameToEncoding(encodingName); + CFStringRef cfStr = CFStringCreateWithBytes(NULL, (const UInt8 *) bytes, (CFIndex) length, encoding, false); + if (cfStr != NULL) { + CFDataRef data = CFStringCreateExternalRepresentation(NULL, cfStr, kCFStringEncodingUTF16LE, '_'); + if (data != NULL) { + appendCharactersLength((const UChar *) CFDataGetBytePtr(data), (unsigned int) CFDataGetLength(data) / 2); + CFRelease(data); + } + CFRelease(cfStr); + } + CFRelease(encodingName); +#else UErrorCode err; err = U_ZERO_ERROR; @@ -1150,6 +1169,7 @@ void String::appendBytes(const char * bytes, unsigned int length, const char * c free(dest); ucnv_close(converter); +#endif } String * String::extractedSubject() @@ -1773,7 +1793,7 @@ String * String::flattenHTML() bool String::hasSuffix(String * suffix) { - if (mLength > suffix->mLength) { + if (mLength >= suffix->mLength) { if (u_memcmp(suffix->mUnicodeChars + (mLength - suffix->mLength), mUnicodeChars, suffix->mLength) == 0) { return true; @@ -1784,7 +1804,7 @@ bool String::hasSuffix(String * suffix) bool String::hasPrefix(String * prefix) { - if (mLength > prefix->mLength) { + if (mLength >= prefix->mLength) { if (u_memcmp(prefix->mUnicodeChars, mUnicodeChars, prefix->mLength) == 0) { return true; } @@ -1810,13 +1830,34 @@ String * String::pathExtension() Data * String::dataUsingEncoding(const char * charset) { - UErrorCode err; - Data * data; - if (charset == NULL) { charset = "utf-8"; } +#if __APPLE__ + Data * data; + + data = NULL; + CFStringRef encodingName = CFStringCreateWithCString(NULL, charset, kCFStringEncodingUTF8); + CFStringEncoding encoding = CFStringConvertIANACharSetNameToEncoding(encodingName); + CFStringRef cfStr = CFStringCreateWithBytes(NULL, (const UInt8 *) mUnicodeChars, + (CFIndex) mLength * sizeof(* mUnicodeChars), kCFStringEncodingUTF16LE, false); + if (cfStr != NULL) { + CFDataRef cfData = CFStringCreateExternalRepresentation(NULL, cfStr, encoding, '_'); + if (cfData != NULL) { + data = Data::dataWithBytes((const char *) CFDataGetBytePtr(cfData), + (unsigned int) CFDataGetLength(cfData)); + CFRelease(cfData); + } + CFRelease(cfStr); + } + CFRelease(encodingName); + + return data; +#else + UErrorCode err; + Data * data; + err = U_ZERO_ERROR; UConverter * converter = ucnv_open(charset, &err); if (converter == NULL) { @@ -1846,6 +1887,7 @@ Data * String::dataUsingEncoding(const char * charset) ucnv_close(converter); return data; +#endif } const char * String::fileSystemRepresentation() diff --git a/src/core/imap/MCIMAPSession.cc b/src/core/imap/MCIMAPSession.cc index c3327872..125cae2f 100644 --- a/src/core/imap/MCIMAPSession.cc +++ b/src/core/imap/MCIMAPSession.cc @@ -317,6 +317,7 @@ void IMAPSession::init() mPort = 0; mUsername = NULL; mPassword = NULL; + mOAuth2Token = NULL; mAuthType = AuthTypeSASLNone; mConnectionType = ConnectionTypeClear; mCheckCertificateEnabled = true; @@ -359,6 +360,7 @@ IMAPSession::~IMAPSession() MC_SAFE_RELEASE(mHostname); MC_SAFE_RELEASE(mUsername); MC_SAFE_RELEASE(mPassword); + MC_SAFE_RELEASE(mOAuth2Token); MC_SAFE_RELEASE(mWelcomeString); MC_SAFE_RELEASE(mDefaultNamespace); MC_SAFE_RELEASE(mCurrentFolder); @@ -405,6 +407,16 @@ String * IMAPSession::password() return mPassword; } +void IMAPSession::setOAuth2Token(String * token) +{ + MC_SAFE_REPLACE_COPY(String, mOAuth2Token, token); +} + +String * IMAPSession::OAuth2Token() +{ + return mOAuth2Token; +} + void IMAPSession::setAuthType(AuthType authType) { mAuthType = authType; @@ -502,15 +514,17 @@ static void logger(mailimap * imap, int log_type, const char * buffer, size_t si return; ConnectionLogType type = getConnectionType(log_type); + if ((int) type == -1) + return; + bool isBuffer = isBufferFromLogType(log_type); if (isBuffer) { Data * data = Data::dataWithBytes(buffer, (unsigned int) size); - session->connectionLogger()->logBuffer(type, data); + session->connectionLogger()->log(session, type, data); } else { - Data * data = Data::dataWithBytes(buffer, (unsigned int) size); - session->connectionLogger()->logString(type, String::stringWithData(data)); + session->connectionLogger()->log(session, type, NULL); } } @@ -748,6 +762,10 @@ void IMAPSession::login(ErrorCode * pError) utf8username, utf8username, utf8password, NULL/* realm */); break; + + case AuthTypeXOAuth2: + r = mailimap_oauth2_authenticate(mImap, MCUTF8(mUsername), MCUTF8(mOAuth2Token)); + break; } if (r == MAILIMAP_ERROR_STREAM) { * pError = ErrorConnection; diff --git a/src/core/imap/MCIMAPSession.h b/src/core/imap/MCIMAPSession.h index 757613e8..53510b0b 100644 --- a/src/core/imap/MCIMAPSession.h +++ b/src/core/imap/MCIMAPSession.h @@ -38,6 +38,11 @@ namespace mailcore { virtual void setPassword(String * password); virtual String * password(); + // To authenticate using OAuth2, username and oauth2token should be set. + // auth type to use is AuthTypeOAuth2. + virtual void setOAuth2Token(String * token); + virtual String * OAuth2Token(); + virtual void setAuthType(AuthType authType); virtual AuthType authType(); @@ -154,6 +159,7 @@ namespace mailcore { unsigned int mPort; String * mUsername; String * mPassword; + String * mOAuth2Token; AuthType mAuthType; ConnectionType mConnectionType; bool mCheckCertificateEnabled; diff --git a/src/core/pop/MCPOPSession.cc b/src/core/pop/MCPOPSession.cc index fe15c500..fea4e5e0 100644 --- a/src/core/pop/MCPOPSession.cc +++ b/src/core/pop/MCPOPSession.cc @@ -160,11 +160,10 @@ static void logger(mailpop3 * pop3, int log_type, const char * buffer, size_t si if (isBuffer) { Data * data = Data::dataWithBytes(buffer, (unsigned int) size); - session->connectionLogger()->logBuffer(type, data); + session->connectionLogger()->log(session, type, data); } else { - Data * data = Data::dataWithBytes(buffer, (unsigned int) size); - session->connectionLogger()->logString(type, String::stringWithData(data)); + session->connectionLogger()->log(session, type, NULL); } } diff --git a/src/core/provider/MCMailProvider.cc b/src/core/provider/MCMailProvider.cc index b814e2ea..43fd94f9 100644 --- a/src/core/provider/MCMailProvider.cc +++ b/src/core/provider/MCMailProvider.cc @@ -18,7 +18,7 @@ using namespace mailcore; void MailProvider::init() { mIdentifier = NULL; - mImapServices = new Array(); + mImapServices = new Array(); mSmtpServices = new Array(); mPopServices = new Array(); mDomainMatch = new Array(); @@ -31,15 +31,27 @@ MailProvider::MailProvider() init(); } +MailProvider::MailProvider(MailProvider * other) +{ + init(); + MC_SAFE_REPLACE_COPY(String, mIdentifier, other->mIdentifier); + MC_SAFE_REPLACE_COPY(Array, mImapServices, other->mImapServices); + MC_SAFE_REPLACE_COPY(Array, mSmtpServices, other->mSmtpServices); + MC_SAFE_REPLACE_COPY(Array, mPopServices, other->mPopServices); + MC_SAFE_REPLACE_COPY(Array, mDomainMatch, other->mDomainMatch); + MC_SAFE_REPLACE_COPY(Set, mMxSet, other->mMxSet); + MC_SAFE_REPLACE_COPY(HashMap, mMailboxPaths, other->mMailboxPaths); +} + MailProvider::~MailProvider() { - MC_SAFE_RELEASE(mImapServices); - MC_SAFE_RELEASE(mSmtpServices); - MC_SAFE_RELEASE(mPopServices); - MC_SAFE_RELEASE(mMxSet); - MC_SAFE_RELEASE(mDomainMatch); - MC_SAFE_RELEASE(mMailboxPaths); - MC_SAFE_RELEASE(mIdentifier); + MC_SAFE_RELEASE(mImapServices); + MC_SAFE_RELEASE(mSmtpServices); + MC_SAFE_RELEASE(mPopServices); + MC_SAFE_RELEASE(mMxSet); + MC_SAFE_RELEASE(mDomainMatch); + MC_SAFE_RELEASE(mMailboxPaths); + MC_SAFE_RELEASE(mIdentifier); } MailProvider * MailProvider::providerWithInfo(HashMap * info) @@ -52,7 +64,7 @@ MailProvider * MailProvider::providerWithInfo(HashMap * info) void MailProvider::fillWithInfo(HashMap * info) { - Array * imapInfos; + Array * imapInfos; Array * smtpInfos; Array * popInfos; HashMap * serverInfo; @@ -68,9 +80,9 @@ void MailProvider::fillWithInfo(HashMap * info) } mxs = (Array *) info->objectForKey(MCSTR("mx")); mMxSet->removeAllObjects(); - mc_foreacharray(String, mx, mxs) { - mMxSet->addObject(mx->lowercaseString()); - } + mc_foreacharray(String, mx, mxs) { + mMxSet->addObject(mx->lowercaseString()); + } serverInfo = (HashMap *) info->objectForKey(MCSTR("servers")); imapInfos = (Array *) serverInfo->objectForKey(MCSTR("imap")); @@ -78,52 +90,52 @@ void MailProvider::fillWithInfo(HashMap * info) popInfos = (Array *) serverInfo->objectForKey(MCSTR("pop")); mImapServices->removeAllObjects(); - mc_foreacharray(HashMap, imapInfo, imapInfos) { - NetService * service = NetService::serviceWithInfo(imapInfo); + mc_foreacharray(HashMap, imapInfo, imapInfos) { + NetService * service = NetService::serviceWithInfo(imapInfo); mImapServices->addObject(service); - } - + } + mSmtpServices->removeAllObjects(); - mc_foreacharray(HashMap, smtpInfo, smtpInfos) { - NetService * service = NetService::serviceWithInfo(smtpInfo); - mSmtpServices->addObject(service); - } - + mc_foreacharray(HashMap, smtpInfo, smtpInfos) { + NetService * service = NetService::serviceWithInfo(smtpInfo); + mSmtpServices->addObject(service); + } + mPopServices->removeAllObjects(); - mc_foreacharray(HashMap, popInfo, popInfos) { - NetService * service = NetService::serviceWithInfo(popInfo); - mPopServices->addObject(service); - } + mc_foreacharray(HashMap, popInfo, popInfos) { + NetService * service = NetService::serviceWithInfo(popInfo); + mPopServices->addObject(service); + } } void MailProvider::setIdentifier(String * identifier) { - MC_SAFE_REPLACE_COPY(String, mIdentifier, identifier); + MC_SAFE_REPLACE_COPY(String, mIdentifier, identifier); } String * MailProvider::identifier() { - return mIdentifier; + return mIdentifier; } Array * MailProvider::imapServices() { - return mImapServices; + return mImapServices; } Array * MailProvider::smtpServices() { - return mSmtpServices; + return mSmtpServices; } Array * MailProvider::popServices() { - return mPopServices; + return mPopServices; } bool MailProvider::matchEmail(String * email) { - Array * components; + Array * components; String * domain; const char * cDomain; @@ -133,9 +145,9 @@ bool MailProvider::matchEmail(String * email) domain = (String *) components->lastObject(); cDomain = domain->UTF8Characters(); - - mc_foreacharray(String, match, mDomainMatch) { - regex_t r; + + mc_foreacharray(String, match, mDomainMatch) { + regex_t r; bool matched; match = String::stringWithUTF8Format("^%s$", match->UTF8Characters()); @@ -151,14 +163,14 @@ bool MailProvider::matchEmail(String * email) if (matched) return true; - } + } return false; } bool MailProvider::matchMX(String * hostname) { - return mMxSet->containsObject(hostname->lowercaseString()); + return mMxSet->containsObject(hostname->lowercaseString()); } String * MailProvider::sentMailFolderPath() @@ -168,38 +180,38 @@ String * MailProvider::sentMailFolderPath() String * MailProvider::starredFolderPath() { - return (String *) mMailboxPaths->objectForKey(MCSTR("starred")); + return (String *) mMailboxPaths->objectForKey(MCSTR("starred")); } String * MailProvider::allMailFolderPath() { - return (String *) mMailboxPaths->objectForKey(MCSTR("allmail")); + return (String *) mMailboxPaths->objectForKey(MCSTR("allmail")); } String * MailProvider::trashFolderPath() { - return (String *) mMailboxPaths->objectForKey(MCSTR("trash")); + return (String *) mMailboxPaths->objectForKey(MCSTR("trash")); } String * MailProvider::draftsFolderPath() { - return (String *) mMailboxPaths->objectForKey(MCSTR("drafts")); + return (String *) mMailboxPaths->objectForKey(MCSTR("drafts")); } String * MailProvider::spamFolderPath() { - return (String *) mMailboxPaths->objectForKey(MCSTR("spam")); + return (String *) mMailboxPaths->objectForKey(MCSTR("spam")); } String * MailProvider::importantFolderPath() { - return (String *) mMailboxPaths->objectForKey(MCSTR("important")); + return (String *) mMailboxPaths->objectForKey(MCSTR("important")); } bool MailProvider::isMainFolder(String * folderPath, String * prefix) { - mc_foreachdictionaryValue(String, path, mMailboxPaths) { - String * fullPath; + mc_foreachdictionaryValue(String, path, mMailboxPaths) { + String * fullPath; if (prefix != NULL) { fullPath = prefix->stringByAppendingString((String *) path); @@ -210,7 +222,7 @@ bool MailProvider::isMainFolder(String * folderPath, String * prefix) if (fullPath->isEqual(folderPath)) return true; - } + } return false; } @@ -219,3 +231,9 @@ String * MailProvider::description() { return String::stringWithUTF8Format("<%s:%p, %s>", className()->UTF8Characters(), this, MCUTF8(mIdentifier)); } + +Object * MailProvider::copy() +{ + return new MailProvider(this); +} + diff --git a/src/core/provider/MCMailProvider.h b/src/core/provider/MCMailProvider.h index 306b180d..81b816e9 100644 --- a/src/core/provider/MCMailProvider.h +++ b/src/core/provider/MCMailProvider.h @@ -45,8 +45,10 @@ namespace mailcore { virtual bool isMainFolder(String * folderPath, String * prefix); public: // subclass behavior + MailProvider(MailProvider * other); virtual String * description(); - + virtual Object * copy(); + public: // private virtual void setIdentifier(String * identifier); virtual void fillWithInfo(HashMap * info); diff --git a/src/core/provider/MCNetService.cc b/src/core/provider/MCNetService.cc index 53ae7475..f760dc61 100644 --- a/src/core/provider/MCNetService.cc +++ b/src/core/provider/MCNetService.cc @@ -19,12 +19,20 @@ void NetService::init() NetService::NetService() { - init(); + init(); +} + +NetService::NetService(NetService * other) +{ + init(); + MC_SAFE_REPLACE_COPY(String, mHostname, other->mHostname); + mPort = other->mPort; + mConnectionType = other->mConnectionType; } NetService::~NetService() { - MC_SAFE_RELEASE(mHostname); + MC_SAFE_RELEASE(mHostname); } NetService * NetService::serviceWithInfo(HashMap * info) @@ -37,10 +45,10 @@ NetService * NetService::serviceWithInfo(HashMap * info) void NetService::fillWithInfo(HashMap * info) { - bool ssl = false; + bool ssl = false; bool starttls = false; - - setHostname((String *) info->objectForKey(MCSTR("hostname"))); + + setHostname((String *) info->objectForKey(MCSTR("hostname"))); if (info->objectForKey(MCSTR("port")) != NULL) { setPort(((Value *) info->objectForKey(MCSTR("port")))->intValue()); } @@ -68,57 +76,57 @@ void NetService::setHostname(String *hostname) String * NetService::hostname() { - return mHostname; + return mHostname; } void NetService::setPort(unsigned int port) { - mPort = port; + mPort = port; } unsigned int NetService::port() { - return mPort; + return mPort; } void NetService::setConnectionType(ConnectionType connectionType) { - mConnectionType = connectionType; + mConnectionType = connectionType; } ConnectionType NetService::connectionType() { - return mConnectionType; + return mConnectionType; } String * NetService::normalizedHostnameWithEmail(String * email) { - Array *components = email->componentsSeparatedByString(MCSTR("@")); - String *hostname = (String *) mHostname->copy(); - if (components->count() != 0) { - hostname->replaceOccurrencesOfString(MCSTR("{domain}"), (String *) components->lastObject()); - return hostname; - } - return mHostname; + Array *components = email->componentsSeparatedByString(MCSTR("@")); + String *hostname = (String *) mHostname->copy(); + if (components->count() != 0) { + hostname->replaceOccurrencesOfString(MCSTR("{domain}"), (String *) components->lastObject()); + return hostname; + } + return mHostname; } HashMap * NetService::info() { - HashMap * result; + HashMap * result; result = new HashMap(); if (mHostname != NULL) { - result->setObjectForKey(MCSTR("hostname"), mHostname); + result->setObjectForKey(MCSTR("hostname"), mHostname); } if (mPort != 0) { - result->setObjectForKey(MCSTR("port"), Value::valueWithIntValue(mPort)); + result->setObjectForKey(MCSTR("port"), Value::valueWithIntValue(mPort)); } switch (mConnectionType) { case ConnectionTypeTLS: - result->setObjectForKey(MCSTR("ssl"), Value::valueWithBoolValue(true)); + result->setObjectForKey(MCSTR("ssl"), Value::valueWithBoolValue(true)); break; case ConnectionTypeStartTLS: - result->setObjectForKey(MCSTR("starttls"), Value::valueWithBoolValue(true)); + result->setObjectForKey(MCSTR("starttls"), Value::valueWithBoolValue(true)); break; default: break; @@ -126,3 +134,13 @@ HashMap * NetService::info() return result; } + +String * NetService::description() +{ + return String::stringWithUTF8Format("<%s:%p, hostname: %s, port: %u>", className()->UTF8Characters(), this, MCUTF8(mHostname), mPort); +} + +Object * NetService::copy() +{ + return new NetService(this); +} diff --git a/src/core/provider/MCNetService.h b/src/core/provider/MCNetService.h index 7b0b9e14..d3aa5dd7 100644 --- a/src/core/provider/MCNetService.h +++ b/src/core/provider/MCNetService.h @@ -15,35 +15,40 @@ #ifdef __cplusplus namespace mailcore { - class NetService : public Object { - - public: - NetService(); - virtual ~NetService(); - - virtual void setHostname(String * hostname); - virtual String * hostname(); - - virtual void setPort(unsigned int port); - virtual unsigned int port(); - - virtual void setConnectionType(ConnectionType connectionType); - virtual ConnectionType connectionType(); - - virtual String * normalizedHostnameWithEmail(String * email); + class NetService : public Object { + + public: + NetService(); + virtual ~NetService(); + + virtual void setHostname(String * hostname); + virtual String * hostname(); + + virtual void setPort(unsigned int port); + virtual unsigned int port(); + + virtual void setConnectionType(ConnectionType connectionType); + virtual ConnectionType connectionType(); + + virtual String * normalizedHostnameWithEmail(String * email); public: // serialization static NetService * serviceWithInfo(HashMap * info); - virtual HashMap * info(); + virtual HashMap * info(); + + public: //subclass behavior + NetService(NetService * other); + virtual String * description(); + virtual Object * copy(); + + private: + String * mHostname; + unsigned int mPort; + ConnectionType mConnectionType; - private: - String * mHostname; - unsigned int mPort; - ConnectionType mConnectionType; - - void init(); + void init(); void fillWithInfo(HashMap * info); - }; + }; } #endif diff --git a/src/core/smtp/MCSMTPSession.cc b/src/core/smtp/MCSMTPSession.cc index e74a540a..dcbad71e 100644 --- a/src/core/smtp/MCSMTPSession.cc +++ b/src/core/smtp/MCSMTPSession.cc @@ -164,7 +164,7 @@ void SMTPSession::bodyProgress(unsigned int current, unsigned int maximum) } -static void logger(mailsmtp * pop3, int log_type, const char * buffer, size_t size, void * context) +static void logger(mailsmtp * smtp, int log_type, const char * buffer, size_t size, void * context) { SMTPSession * session = (SMTPSession *) context; @@ -176,11 +176,10 @@ static void logger(mailsmtp * pop3, int log_type, const char * buffer, size_t si if (isBuffer) { Data * data = Data::dataWithBytes(buffer, (unsigned int) size); - session->connectionLogger()->logBuffer(type, data); + session->connectionLogger()->log(session, type, data); } else { - Data * data = Data::dataWithBytes(buffer, (unsigned int) size); - session->connectionLogger()->logString(type, String::stringWithData(data)); + session->connectionLogger()->log(session, type, NULL); } } diff --git a/src/objc/abstract/MCOAbstractMessage.mm b/src/objc/abstract/MCOAbstractMessage.mm index 6fedcc8a..05530845 100644 --- a/src/objc/abstract/MCOAbstractMessage.mm +++ b/src/objc/abstract/MCOAbstractMessage.mm @@ -28,6 +28,12 @@ return _message; } +- (id) init +{ + MCAssert(0); + return nil; +} + - (id) initWithMCMessage:(mailcore::AbstractMessage *)message { self = [super init]; @@ -40,7 +46,7 @@ - (void) dealloc { - _message->release(); + MC_SAFE_RELEASE(_message); [super dealloc]; } diff --git a/src/objc/abstract/MCOAbstractPart.mm b/src/objc/abstract/MCOAbstractPart.mm index 8b2b008d..7a37dcaf 100644 --- a/src/objc/abstract/MCOAbstractPart.mm +++ b/src/objc/abstract/MCOAbstractPart.mm @@ -27,6 +27,12 @@ return _part; } +- (id) init +{ + MCAssert(0); + return nil; +} + - (id) initWithMCPart:(mailcore::AbstractPart *)part { self = [super init]; @@ -39,7 +45,7 @@ - (void) dealloc { - _part->release(); + MC_SAFE_RELEASE(_part); [super dealloc]; } diff --git a/src/objc/abstract/MCOConstants.h b/src/objc/abstract/MCOConstants.h index 8fafabf3..5ec21422 100644 --- a/src/objc/abstract/MCOConstants.h +++ b/src/objc/abstract/MCOConstants.h @@ -33,6 +33,8 @@ typedef enum { MCOAuthTypeSASLNTLM = 1 << 6, /** Kerberos 4 authentication.*/ MCOAuthTypeSASLKerberosV4 = 1 << 7, + /** OAuth2 authentication.*/ + MCOAuthTypeXOAuth2 = 1 << 8, } MCOAuthType; /** It's the IMAP flags of the folder.*/ @@ -324,4 +326,28 @@ typedef enum { MCOErrorInvalidAccount, } MCOErrorCode; +/** Here's the list of connection log types.*/ +typedef enum { + /** Received data.*/ + MCOConnectionLogTypeReceived, + /** Sent data.*/ + MCOConnectionLogTypeSent, + /** Sent private data. It can be a password.*/ + MCOConnectionLogTypeSentPrivate, + /** Parse error.*/ + MCOConnectionLogTypeErrorParse, + /** Error while receiving data. The data passed to the log will be nil.*/ + MCOConnectionLogTypeErrorReceived, + /** Error while sending dataThe data passed to the log will be nil.*/ + MCOConnectionLogTypeErrorSent, +} MCOConnectionLogType; + +/** + It's a network traffic logger. + @param connectionID is the identifier of the underlaying network socket. + @param type is the type of the log. + @param data is the data related to the log. + */ +typedef void (^MCOConnectionLogger)(void * connectionID, MCOConnectionLogType type, NSData * data); + #endif diff --git a/src/objc/abstract/MCOMessageHeader.mm b/src/objc/abstract/MCOMessageHeader.mm index 6729894d..427131b0 100644 --- a/src/objc/abstract/MCOMessageHeader.mm +++ b/src/objc/abstract/MCOMessageHeader.mm @@ -67,6 +67,12 @@ return self; } +- (void) dealloc +{ + _nativeHeader->release(); + [super dealloc]; +} + + (MCOMessageHeader *) messageHeaderWithMCMessageHeader:(mailcore::MessageHeader *)header { if (header == NULL) diff --git a/src/objc/imap/MCOIMAPAppendMessageOperation.mm b/src/objc/imap/MCOIMAPAppendMessageOperation.mm index 16463016..c281b925 100644 --- a/src/objc/imap/MCOIMAPAppendMessageOperation.mm +++ b/src/objc/imap/MCOIMAPAppendMessageOperation.mm @@ -57,6 +57,8 @@ typedef void (^CompletionType)(NSError *error, uint32_t createdUID); } else { _completionBlock([NSError mco_errorWithErrorCode:op->error()], 0); } + [_completionBlock release]; + _completionBlock = nil; } - (void) bodyProgress:(unsigned int)current maximum:(unsigned int)maximum diff --git a/src/objc/imap/MCOIMAPCapabilityOperation.mm b/src/objc/imap/MCOIMAPCapabilityOperation.mm index 048475c9..42952378 100644 --- a/src/objc/imap/MCOIMAPCapabilityOperation.mm +++ b/src/objc/imap/MCOIMAPCapabilityOperation.mm @@ -53,6 +53,8 @@ typedef void (^CompletionType)(NSError *error, MCOIndexSet * capabilities); } else { _completionBlock([NSError mco_errorWithErrorCode:op->error()], nil); } + [_completionBlock release]; + _completionBlock = nil; } @end diff --git a/src/objc/imap/MCOIMAPCopyMessagesOperation.mm b/src/objc/imap/MCOIMAPCopyMessagesOperation.mm index 8f7bf501..d14bcc84 100644 --- a/src/objc/imap/MCOIMAPCopyMessagesOperation.mm +++ b/src/objc/imap/MCOIMAPCopyMessagesOperation.mm @@ -54,6 +54,8 @@ typedef void (^CompletionType)(NSError *error, MCOIndexSet * destUids); } else { _completionBlock([NSError mco_errorWithErrorCode:op->error()], 0); } + [_completionBlock release]; + _completionBlock = nil; } @end diff --git a/src/objc/imap/MCOIMAPFetchContentOperation.mm b/src/objc/imap/MCOIMAPFetchContentOperation.mm index 984751c0..d5d4757d 100644 --- a/src/objc/imap/MCOIMAPFetchContentOperation.mm +++ b/src/objc/imap/MCOIMAPFetchContentOperation.mm @@ -57,6 +57,8 @@ typedef void (^CompletionType)(NSError *error, NSData * data); } else { _completionBlock([NSError mco_errorWithErrorCode:op->error()], nil); } + [_completionBlock release]; + _completionBlock = nil; } - (void) bodyProgress:(unsigned int)current maximum:(unsigned int)maximum diff --git a/src/objc/imap/MCOIMAPFetchFoldersOperation.mm b/src/objc/imap/MCOIMAPFetchFoldersOperation.mm index 53017c90..02b7d880 100644 --- a/src/objc/imap/MCOIMAPFetchFoldersOperation.mm +++ b/src/objc/imap/MCOIMAPFetchFoldersOperation.mm @@ -58,6 +58,8 @@ typedef void (^CompletionType)(NSError *error, NSArray *folder); } else { _completionBlock([NSError mco_errorWithErrorCode:op->error()], nil); } + [_completionBlock release]; + _completionBlock = nil; } @end diff --git a/src/objc/imap/MCOIMAPFetchMessagesOperation.mm b/src/objc/imap/MCOIMAPFetchMessagesOperation.mm index e43a46e5..6892ab1b 100644 --- a/src/objc/imap/MCOIMAPFetchMessagesOperation.mm +++ b/src/objc/imap/MCOIMAPFetchMessagesOperation.mm @@ -53,6 +53,8 @@ typedef void (^CompletionType)(NSError *error, NSArray * messages, MCOIndexSet * } else { _completionBlock([NSError mco_errorWithErrorCode:op->error()], nil, nil); } + [_completionBlock release]; + _completionBlock = nil; } - (void) itemProgress:(unsigned int)current maximum:(unsigned int)maximum diff --git a/src/objc/imap/MCOIMAPFetchNamespaceOperation.mm b/src/objc/imap/MCOIMAPFetchNamespaceOperation.mm index aaa02c96..861298bf 100644 --- a/src/objc/imap/MCOIMAPFetchNamespaceOperation.mm +++ b/src/objc/imap/MCOIMAPFetchNamespaceOperation.mm @@ -53,6 +53,8 @@ typedef void (^CompletionType)(NSError *error, NSDictionary * namespaces); } else { _completionBlock([NSError mco_errorWithErrorCode:op->error()], nil); } + [_completionBlock release]; + _completionBlock = nil; } @end diff --git a/src/objc/imap/MCOIMAPFolderInfoOperation.mm b/src/objc/imap/MCOIMAPFolderInfoOperation.mm index 37b1a649..61766073 100644 --- a/src/objc/imap/MCOIMAPFolderInfoOperation.mm +++ b/src/objc/imap/MCOIMAPFolderInfoOperation.mm @@ -61,6 +61,8 @@ typedef void (^CompletionType)(NSError *error, MCOIMAPFolderInfo *info); } else { _completionBlock([NSError mco_errorWithErrorCode:op->error()], nil); } + [_completionBlock release]; + _completionBlock = nil; } @end diff --git a/src/objc/imap/MCOIMAPFolderStatusOperation.mm b/src/objc/imap/MCOIMAPFolderStatusOperation.mm index c7f5370c..2420e0b9 100644 --- a/src/objc/imap/MCOIMAPFolderStatusOperation.mm +++ b/src/objc/imap/MCOIMAPFolderStatusOperation.mm @@ -55,6 +55,8 @@ typedef void (^CompletionType)(NSError *error, MCOIMAPFolderStatus *status); } else { _completionBlock([NSError mco_errorWithErrorCode:op->error()], nil); } + [_completionBlock release]; + _completionBlock = nil; } @end diff --git a/src/objc/imap/MCOIMAPIdentityOperation.mm b/src/objc/imap/MCOIMAPIdentityOperation.mm index acc5ea10..f02fbba5 100644 --- a/src/objc/imap/MCOIMAPIdentityOperation.mm +++ b/src/objc/imap/MCOIMAPIdentityOperation.mm @@ -53,6 +53,8 @@ typedef void (^CompletionType)(NSError *error, NSDictionary * serverIdentity); } else { _completionBlock([NSError mco_errorWithErrorCode:op->error()], nil); } + [_completionBlock release]; + _completionBlock = nil; } @end diff --git a/src/objc/imap/MCOIMAPIdleOperation.mm b/src/objc/imap/MCOIMAPIdleOperation.mm index 86419b75..d43bf818 100644 --- a/src/objc/imap/MCOIMAPIdleOperation.mm +++ b/src/objc/imap/MCOIMAPIdleOperation.mm @@ -53,6 +53,8 @@ typedef void (^CompletionType)(NSError *error); } else { _completionBlock([NSError mco_errorWithErrorCode:op->error()]); } + [_completionBlock release]; + _completionBlock = nil; } - (void) interruptIdle diff --git a/src/objc/imap/MCOIMAPOperation.mm b/src/objc/imap/MCOIMAPOperation.mm index 7b98c6bd..0b6d48e0 100644 --- a/src/objc/imap/MCOIMAPOperation.mm +++ b/src/objc/imap/MCOIMAPOperation.mm @@ -38,6 +38,8 @@ typedef void (^CompletionType)(NSError *error); NSError * error = [NSError mco_errorWithErrorCode:MCO_NATIVE_INSTANCE->error()]; _completionBlock(error); + [_completionBlock release]; + _completionBlock = nil; } @end diff --git a/src/objc/imap/MCOIMAPSearchOperation.mm b/src/objc/imap/MCOIMAPSearchOperation.mm index 92f57b62..730c73a0 100644 --- a/src/objc/imap/MCOIMAPSearchOperation.mm +++ b/src/objc/imap/MCOIMAPSearchOperation.mm @@ -54,6 +54,8 @@ typedef void (^CompletionType)(NSError *error, MCOIndexSet * searchResult); } else { _completionBlock([NSError mco_errorWithErrorCode:op->error()], nil); } + [_completionBlock release]; + _completionBlock = nil; } @end diff --git a/src/objc/imap/MCOIMAPSession.h b/src/objc/imap/MCOIMAPSession.h index 1b394eff..0358f7ad 100644 --- a/src/objc/imap/MCOIMAPSession.h +++ b/src/objc/imap/MCOIMAPSession.h @@ -90,6 +90,15 @@ */ @property (nonatomic, assign) unsigned int maximumConnections; +/** + Sets logger callback. The network traffic will be sent to this block. + + [session setConnectionLogger:^(void * connectionID, MCOConnectionLogType type, NSData * data) { + ... + }]; +*/ +@property (nonatomic, copy) MCOConnectionLogger connectionLogger; + /** @name Folder Operations */ /** diff --git a/src/objc/imap/MCOIMAPSession.mm b/src/objc/imap/MCOIMAPSession.mm index a8df8aed..43f366e6 100644 --- a/src/objc/imap/MCOIMAPSession.mm +++ b/src/objc/imap/MCOIMAPSession.mm @@ -22,8 +22,32 @@ using namespace mailcore; +@interface MCOIMAPSession () + +- (void) _logWithSender:(void *)sender connectionType:(MCOConnectionLogType)logType data:(NSData *)data; + +@end + +class MCOIMAPConnectionLoggerBridge : public Object, public ConnectionLogger { +public: + MCOIMAPConnectionLoggerBridge(MCOIMAPSession * session) + { + mSession = session; + } + + virtual void log(void * context, void * sender, ConnectionLogType logType, Data * data) + { + [mSession _logWithSender:sender connectionType:(MCOConnectionLogType)logType data:MCO_TO_OBJC(data)]; + } + +private: + MCOIMAPSession * mSession; +}; + @implementation MCOIMAPSession { IMAPAsyncSession * _session; + MCOConnectionLogger _connectionLogger; + MCOIMAPConnectionLoggerBridge * _loggerBridge; } #define nativeType mailcore::IMAPAsyncSession @@ -35,13 +59,16 @@ using namespace mailcore; - (id)init { self = [super init]; - if (self) { - _session = new IMAPAsyncSession(); - } + + _session = new IMAPAsyncSession(); + _loggerBridge = new MCOIMAPConnectionLoggerBridge(self); + return self; } - (void)dealloc { + MC_SAFE_RELEASE(_loggerBridge); + [_connectionLogger release]; _session->release(); [super dealloc]; } @@ -59,6 +86,24 @@ MCO_OBJC_SYNTHESIZE_SCALAR(char, char, setDelimiter, delimiter) MCO_OBJC_SYNTHESIZE_SCALAR(BOOL, BOOL, setAllowsFolderConcurrentAccessEnabled, allowsFolderConcurrentAccessEnabled) MCO_OBJC_SYNTHESIZE_SCALAR(unsigned int, unsigned int, setMaximumConnections, maximumConnections) +- (void) setConnectionLogger:(MCOConnectionLogger)connectionLogger +{ + [_connectionLogger release]; + _connectionLogger = [connectionLogger copy]; + + if (_connectionLogger != nil) { + _session->setConnectionLogger(_loggerBridge); + } + else { + _session->setConnectionLogger(NULL); + } +} + +- (MCOConnectionLogger) connectionLogger +{ + return _connectionLogger; +} + #pragma mark - Operations #define MCO_TO_OBJC_OP(op) [self _objcOperationFromNativeOp:op]; @@ -303,4 +348,9 @@ MCO_OBJC_SYNTHESIZE_SCALAR(unsigned int, unsigned int, setMaximumConnections, ma return MCO_TO_OBJC_OP(coreOp); } +- (void) _logWithSender:(void *)sender connectionType:(MCOConnectionLogType)logType data:(NSData *)data +{ + _connectionLogger(sender, logType, data); +} + @end diff --git a/src/objc/pop/MCOPOPFetchHeaderOperation.mm b/src/objc/pop/MCOPOPFetchHeaderOperation.mm index 1d2c35c6..ab467a76 100644 --- a/src/objc/pop/MCOPOPFetchHeaderOperation.mm +++ b/src/objc/pop/MCOPOPFetchHeaderOperation.mm @@ -54,6 +54,8 @@ typedef void (^CompletionType)(NSError *error, MCOMessageHeader * header); } else { _completionBlock([NSError mco_errorWithErrorCode:op->error()], nil); } + [_completionBlock release]; + _completionBlock = nil; } @end diff --git a/src/objc/pop/MCOPOPFetchMessageOperation.mm b/src/objc/pop/MCOPOPFetchMessageOperation.mm index 40740961..02bad3ad 100644 --- a/src/objc/pop/MCOPOPFetchMessageOperation.mm +++ b/src/objc/pop/MCOPOPFetchMessageOperation.mm @@ -90,6 +90,8 @@ private: } else { _completionBlock([NSError mco_errorWithErrorCode:op->error()], nil); } + [_completionBlock release]; + _completionBlock = nil; } - (void) bodyProgress:(unsigned int)current maximum:(unsigned int)maximum diff --git a/src/objc/pop/MCOPOPFetchMessagesOperation.mm b/src/objc/pop/MCOPOPFetchMessagesOperation.mm index dcb35845..2fe9b31f 100644 --- a/src/objc/pop/MCOPOPFetchMessagesOperation.mm +++ b/src/objc/pop/MCOPOPFetchMessagesOperation.mm @@ -54,6 +54,8 @@ typedef void (^CompletionType)(NSError *error, NSArray * messages); } else { _completionBlock([NSError mco_errorWithErrorCode:op->error()], nil); } + [_completionBlock release]; + _completionBlock = nil; } diff --git a/src/objc/pop/MCOPOPOperation.mm b/src/objc/pop/MCOPOPOperation.mm index 9b58f84d..5f4d1f59 100644 --- a/src/objc/pop/MCOPOPOperation.mm +++ b/src/objc/pop/MCOPOPOperation.mm @@ -41,6 +41,8 @@ typedef void (^CompletionType)(NSError *error); NSError * error = [NSError mco_errorWithErrorCode:MCO_NATIVE_INSTANCE->error()]; _completionBlock(error); + [_completionBlock release]; + _completionBlock = nil; } - (void) setSession:(MCOPOPSession *)session diff --git a/src/objc/pop/MCOPOPSession.h b/src/objc/pop/MCOPOPSession.h index 6ecca042..4f98421c 100644 --- a/src/objc/pop/MCOPOPSession.h +++ b/src/objc/pop/MCOPOPSession.h @@ -53,6 +53,15 @@ See MCOConnectionType for more information.*/ /** When set to YES, the connection will fail if the certificate is incorrect.*/ @property (nonatomic, assign, getter=isCheckCertificateEnabled) BOOL checkCertificateEnabled; +/** + Sets logger callback. The network traffic will be sent to this block. + + [session setConnectionLogger:^(void * connectionID, MCOConnectionLogType type, NSData * data) { + ... + }]; + */ +@property (nonatomic, copy) MCOConnectionLogger connectionLogger; + /** @name Operations */ /** diff --git a/src/objc/pop/MCOPOPSession.mm b/src/objc/pop/MCOPOPSession.mm index 11f7cad6..42c76646 100644 --- a/src/objc/pop/MCOPOPSession.mm +++ b/src/objc/pop/MCOPOPSession.mm @@ -16,8 +16,34 @@ #import "MCOPOPFetchMessagesOperation.h" #import "MCOPOPOperation+Private.h" +using namespace mailcore; + +@interface MCOPOPSession () + +- (void) _logWithSender:(void *)sender connectionType:(MCOConnectionLogType)logType data:(NSData *)data; + +@end + +class MCOPOPConnectionLoggerBridge : public Object, public ConnectionLogger { +public: + MCOPOPConnectionLoggerBridge(MCOPOPSession * session) + { + mSession = session; + } + + virtual void log(void * context, void * sender, ConnectionLogType logType, Data * data) + { + [mSession _logWithSender:sender connectionType:(MCOConnectionLogType)logType data:MCO_TO_OBJC(data)]; + } + +private: + MCOPOPSession * mSession; +}; + @implementation MCOPOPSession { mailcore::POPAsyncSession * _session; + MCOConnectionLogger _connectionLogger; + MCOPOPConnectionLoggerBridge * _loggerBridge; } #define nativeType mailcore::POPAsyncSession @@ -34,13 +60,16 @@ - (id)init { self = [super init]; - if (self) { - _session = new mailcore::POPAsyncSession(); - } + + _session = new mailcore::POPAsyncSession(); + _loggerBridge = new MCOPOPConnectionLoggerBridge(self); + return self; } - (void)dealloc { + MC_SAFE_RELEASE(_loggerBridge); + [_connectionLogger release]; _session->release(); [super dealloc]; } @@ -54,6 +83,24 @@ MCO_OBJC_SYNTHESIZE_SCALAR(MCOConnectionType, mailcore::ConnectionType, setConne MCO_OBJC_SYNTHESIZE_SCALAR(NSTimeInterval, time_t, setTimeout, timeout) MCO_OBJC_SYNTHESIZE_BOOL(setCheckCertificateEnabled, isCheckCertificateEnabled) +- (void) setConnectionLogger:(MCOConnectionLogger)connectionLogger +{ + [_connectionLogger release]; + _connectionLogger = [connectionLogger copy]; + + if (_connectionLogger != nil) { + _session->setConnectionLogger(_loggerBridge); + } + else { + _session->setConnectionLogger(NULL); + } +} + +- (MCOConnectionLogger) connectionLogger +{ + return _connectionLogger; +} + #pragma mark - Operations @@ -111,4 +158,9 @@ MCO_OBJC_SYNTHESIZE_BOOL(setCheckCertificateEnabled, isCheckCertificateEnabled) return OPAQUE_OPERATION(coreOp); } +- (void) _logWithSender:(void *)sender connectionType:(MCOConnectionLogType)logType data:(NSData *)data +{ + _connectionLogger(sender, logType, data); +} + @end diff --git a/src/objc/smtp/MCOSMTPOperation.mm b/src/objc/smtp/MCOSMTPOperation.mm index cd52ad13..9d96613f 100644 --- a/src/objc/smtp/MCOSMTPOperation.mm +++ b/src/objc/smtp/MCOSMTPOperation.mm @@ -41,6 +41,8 @@ typedef void (^CompletionType)(NSError *error); NSError * error = [NSError mco_errorWithErrorCode:MCO_NATIVE_INSTANCE->error()]; _completionBlock(error); + [_completionBlock release]; + _completionBlock = NULL; } - (void) setSession:(MCOSMTPSession *)session diff --git a/src/objc/smtp/MCOSMTPSendOperation.mm b/src/objc/smtp/MCOSMTPSendOperation.mm index e41a9f5a..8a7d5b04 100644 --- a/src/objc/smtp/MCOSMTPSendOperation.mm +++ b/src/objc/smtp/MCOSMTPSendOperation.mm @@ -80,16 +80,16 @@ private: [self start]; } +// This method needs to be duplicated from MCOSMTPOperation since _completionBlock +// references the instance of this subclass and not the one from MCOSMTPOperation. - (void)operationCompleted { if (_completionBlock == NULL) return; - nativeType *op = MCO_NATIVE_INSTANCE; - if (op->error() == mailcore::ErrorNone) { - _completionBlock(nil); - } else { - _completionBlock([NSError mco_errorWithErrorCode:op->error()]); - } + NSError * error = [NSError mco_errorWithErrorCode:MCO_NATIVE_INSTANCE->error()]; + _completionBlock(error); + [_completionBlock release]; + _completionBlock = NULL; } - (void) bodyProgress:(unsigned int)current maximum:(unsigned int)maximum diff --git a/src/objc/smtp/MCOSMTPSession.h b/src/objc/smtp/MCOSMTPSession.h index 08189bed..44d37942 100644 --- a/src/objc/smtp/MCOSMTPSession.h +++ b/src/objc/smtp/MCOSMTPSession.h @@ -64,6 +64,15 @@ */ @property (nonatomic, assign, getter=isUseHeloIPEnabled) BOOL useHeloIPEnabled; +/** + Sets logger callback. The network traffic will be sent to this block. + + [session setConnectionLogger:^(void * connectionID, MCOConnectionLogType type, NSData * data) { + ... + }]; + */ +@property (nonatomic, copy) MCOConnectionLogger connectionLogger; + /** @name Operations */ /** diff --git a/src/objc/smtp/MCOSMTPSession.mm b/src/objc/smtp/MCOSMTPSession.mm index de6b54cd..1538d53a 100644 --- a/src/objc/smtp/MCOSMTPSession.mm +++ b/src/objc/smtp/MCOSMTPSession.mm @@ -17,8 +17,34 @@ #import "MCOAddress.h" #import "MCOSMTPOperation+Private.h" +using namespace mailcore; + +@interface MCOSMTPSession () + +- (void) _logWithSender:(void *)sender connectionType:(MCOConnectionLogType)logType data:(NSData *)data; + +@end + +class MCOSMTPConnectionLoggerBridge : public Object, public ConnectionLogger { +public: + MCOSMTPConnectionLoggerBridge(MCOSMTPSession * session) + { + mSession = session; + } + + virtual void log(void * context, void * sender, ConnectionLogType logType, Data * data) + { + [mSession _logWithSender:sender connectionType:(MCOConnectionLogType)logType data:MCO_TO_OBJC(data)]; + } + +private: + MCOSMTPSession * mSession; +}; + @implementation MCOSMTPSession { mailcore::SMTPAsyncSession * _session; + MCOConnectionLogger _connectionLogger; + MCOSMTPConnectionLoggerBridge * _loggerBridge; } #define nativeType mailcore::SMTPAsyncSession @@ -30,13 +56,16 @@ - (id)init { self = [super init]; - if (self) { - _session = new mailcore::SMTPAsyncSession(); - } + + _session = new mailcore::SMTPAsyncSession(); + _loggerBridge = new MCOSMTPConnectionLoggerBridge(self); + return self; } - (void)dealloc { + MC_SAFE_RELEASE(_loggerBridge); + [_connectionLogger release]; _session->release(); [super dealloc]; } @@ -51,6 +80,24 @@ MCO_OBJC_SYNTHESIZE_SCALAR(NSTimeInterval, time_t, setTimeout, timeout) MCO_OBJC_SYNTHESIZE_BOOL(setCheckCertificateEnabled, isCheckCertificateEnabled) MCO_OBJC_SYNTHESIZE_BOOL(setUseHeloIPEnabled, useHeloIPEnabled) +- (void) setConnectionLogger:(MCOConnectionLogger)connectionLogger +{ + [_connectionLogger release]; + _connectionLogger = [connectionLogger copy]; + + if (_connectionLogger != nil) { + _session->setConnectionLogger(_loggerBridge); + } + else { + _session->setConnectionLogger(NULL); + } +} + +- (MCOConnectionLogger) connectionLogger +{ + return _connectionLogger; +} + #pragma mark - Operations - (MCOSMTPSendOperation *) sendOperationWithData:(NSData *)messageData @@ -69,4 +116,9 @@ MCO_OBJC_SYNTHESIZE_BOOL(setUseHeloIPEnabled, useHeloIPEnabled) return result; } +- (void) _logWithSender:(void *)sender connectionType:(MCOConnectionLogType)logType data:(NSData *)data +{ + _connectionLogger(sender, logType, data); +} + @end |