From e3c45123799d84b0ff85035db606cc36b8379427 Mon Sep 17 00:00:00 2001 From: "Hoa V. DINH" Date: Wed, 19 Nov 2014 00:48:34 -0800 Subject: Renamed .cc files to .cpp (fixed #983) --- build-mac/mailcore2.xcodeproj/project.pbxproj | 1380 +++---- src/async/imap/MCIMAPAppendMessageOperation.cc | 82 - src/async/imap/MCIMAPAppendMessageOperation.cpp | 82 + src/async/imap/MCIMAPAsyncConnection.cc | 424 --- src/async/imap/MCIMAPAsyncConnection.cpp | 424 +++ src/async/imap/MCIMAPAsyncSession.cc | 848 ----- src/async/imap/MCIMAPAsyncSession.cpp | 848 +++++ src/async/imap/MCIMAPCapabilityOperation.cc | 43 - src/async/imap/MCIMAPCapabilityOperation.cpp | 43 + src/async/imap/MCIMAPCheckAccountOperation.cc | 23 - src/async/imap/MCIMAPCheckAccountOperation.cpp | 23 + src/async/imap/MCIMAPConnectOperation.cc | 21 - src/async/imap/MCIMAPConnectOperation.cpp | 21 + src/async/imap/MCIMAPCopyMessagesOperation.cc | 61 - src/async/imap/MCIMAPCopyMessagesOperation.cpp | 61 + src/async/imap/MCIMAPCreateFolderOperation.cc | 29 - src/async/imap/MCIMAPCreateFolderOperation.cpp | 29 + src/async/imap/MCIMAPDeleteFolderOperation.cc | 29 - src/async/imap/MCIMAPDeleteFolderOperation.cpp | 29 + src/async/imap/MCIMAPDisconnectOperation.cc | 28 - src/async/imap/MCIMAPDisconnectOperation.cpp | 28 + src/async/imap/MCIMAPExpungeOperation.cc | 29 - src/async/imap/MCIMAPExpungeOperation.cpp | 29 + src/async/imap/MCIMAPFetchContentOperation.cc | 98 - src/async/imap/MCIMAPFetchContentOperation.cpp | 98 + src/async/imap/MCIMAPFetchFoldersOperation.cc | 55 - src/async/imap/MCIMAPFetchFoldersOperation.cpp | 55 + src/async/imap/MCIMAPFetchMessagesOperation.cc | 120 - src/async/imap/MCIMAPFetchMessagesOperation.cpp | 120 + src/async/imap/MCIMAPFetchNamespaceOperation.cc | 38 - src/async/imap/MCIMAPFetchNamespaceOperation.cpp | 38 + .../imap/MCIMAPFetchParsedContentOperation.cc | 79 - .../imap/MCIMAPFetchParsedContentOperation.cpp | 79 + src/async/imap/MCIMAPFolderInfoOperation.cc | 86 - src/async/imap/MCIMAPFolderInfoOperation.cpp | 86 + src/async/imap/MCIMAPFolderStatusOperation.cc | 51 - src/async/imap/MCIMAPFolderStatusOperation.cpp | 51 + src/async/imap/MCIMAPIdentityOperation.cc | 51 - src/async/imap/MCIMAPIdentityOperation.cpp | 51 + src/async/imap/MCIMAPIdleOperation.cc | 98 - src/async/imap/MCIMAPIdleOperation.cpp | 98 + src/async/imap/MCIMAPMessageRenderingOperation.cc | 76 - src/async/imap/MCIMAPMessageRenderingOperation.cpp | 76 + src/async/imap/MCIMAPMultiDisconnectOperation.cc | 58 - src/async/imap/MCIMAPMultiDisconnectOperation.cpp | 58 + src/async/imap/MCIMAPNoopOperation.cc | 29 - src/async/imap/MCIMAPNoopOperation.cpp | 29 + src/async/imap/MCIMAPOperation.cc | 185 - src/async/imap/MCIMAPOperation.cpp | 185 + src/async/imap/MCIMAPQuotaOperation.cc | 47 - src/async/imap/MCIMAPQuotaOperation.cpp | 47 + src/async/imap/MCIMAPRenameFolderOperation.cc | 42 - src/async/imap/MCIMAPRenameFolderOperation.cpp | 42 + src/async/imap/MCIMAPSearchOperation.cc | 79 - src/async/imap/MCIMAPSearchOperation.cpp | 79 + src/async/imap/MCIMAPStoreFlagsOperation.cc | 92 - src/async/imap/MCIMAPStoreFlagsOperation.cpp | 92 + src/async/imap/MCIMAPStoreLabelsOperation.cc | 82 - src/async/imap/MCIMAPStoreLabelsOperation.cpp | 82 + src/async/imap/MCIMAPSubscribeFolderOperation.cc | 45 - src/async/imap/MCIMAPSubscribeFolderOperation.cpp | 45 + src/async/nntp/MCNNTPAsyncSession.cc | 302 -- src/async/nntp/MCNNTPAsyncSession.cpp | 302 ++ src/async/nntp/MCNNTPCheckAccountOperation.cc | 30 - src/async/nntp/MCNNTPCheckAccountOperation.cpp | 30 + src/async/nntp/MCNNTPDisconnectOperation.cc | 30 - src/async/nntp/MCNNTPDisconnectOperation.cpp | 30 + src/async/nntp/MCNNTPFetchAllArticlesOperation.cc | 49 - src/async/nntp/MCNNTPFetchAllArticlesOperation.cpp | 49 + src/async/nntp/MCNNTPFetchArticleOperation.cc | 69 - src/async/nntp/MCNNTPFetchArticleOperation.cpp | 69 + src/async/nntp/MCNNTPFetchHeaderOperation.cc | 59 - src/async/nntp/MCNNTPFetchHeaderOperation.cpp | 59 + src/async/nntp/MCNNTPFetchOverviewOperation.cc | 68 - src/async/nntp/MCNNTPFetchOverviewOperation.cpp | 68 + src/async/nntp/MCNNTPFetchServerTimeOperation.cc | 34 - src/async/nntp/MCNNTPFetchServerTimeOperation.cpp | 34 + src/async/nntp/MCNNTPListNewsgroupsOperation.cc | 48 - src/async/nntp/MCNNTPListNewsgroupsOperation.cpp | 48 + src/async/nntp/MCNNTPOperation.cc | 104 - src/async/nntp/MCNNTPOperation.cpp | 104 + src/async/pop/MCPOPAsyncSession.cc | 275 -- src/async/pop/MCPOPAsyncSession.cpp | 275 ++ src/async/pop/MCPOPCheckAccountOperation.cc | 30 - src/async/pop/MCPOPCheckAccountOperation.cpp | 30 + src/async/pop/MCPOPDeleteMessagesOperation.cc | 63 - src/async/pop/MCPOPDeleteMessagesOperation.cpp | 63 + src/async/pop/MCPOPFetchHeaderOperation.cc | 51 - src/async/pop/MCPOPFetchHeaderOperation.cpp | 51 + src/async/pop/MCPOPFetchMessageOperation.cc | 49 - src/async/pop/MCPOPFetchMessageOperation.cpp | 49 + src/async/pop/MCPOPFetchMessagesOperation.cc | 37 - src/async/pop/MCPOPFetchMessagesOperation.cpp | 37 + src/async/pop/MCPOPNoopOperation.cc | 30 - src/async/pop/MCPOPNoopOperation.cpp | 30 + src/async/pop/MCPOPOperation.cc | 104 - src/async/pop/MCPOPOperation.cpp | 104 + src/async/smtp/MCSMTPAsyncSession.cc | 294 -- src/async/smtp/MCSMTPAsyncSession.cpp | 294 ++ src/async/smtp/MCSMTPCheckAccountOperation.cc | 42 - src/async/smtp/MCSMTPCheckAccountOperation.cpp | 42 + src/async/smtp/MCSMTPDisconnectOperation.cc | 28 - src/async/smtp/MCSMTPDisconnectOperation.cpp | 28 + src/async/smtp/MCSMTPLoginOperation.cc | 29 - src/async/smtp/MCSMTPLoginOperation.cpp | 29 + src/async/smtp/MCSMTPNoopOperation.cc | 29 - src/async/smtp/MCSMTPNoopOperation.cpp | 29 + src/async/smtp/MCSMTPOperation.cc | 102 - src/async/smtp/MCSMTPOperation.cpp | 102 + src/async/smtp/MCSMTPSendWithDataOperation.cc | 70 - src/async/smtp/MCSMTPSendWithDataOperation.cpp | 70 + src/cmake/async.cmake | 110 +- src/cmake/core.cmake | 120 +- src/core/abstract/MCAbstractMessage.cc | 100 - src/core/abstract/MCAbstractMessage.cpp | 100 + src/core/abstract/MCAbstractMessagePart.cc | 98 - src/core/abstract/MCAbstractMessagePart.cpp | 98 + src/core/abstract/MCAbstractMultipart.cc | 111 - src/core/abstract/MCAbstractMultipart.cpp | 111 + src/core/abstract/MCAbstractPart.cc | 451 --- src/core/abstract/MCAbstractPart.cpp | 451 +++ src/core/abstract/MCAddress.cc | 528 --- src/core/abstract/MCAddress.cpp | 528 +++ src/core/abstract/MCMessageHeader.cc | 1291 ------- src/core/abstract/MCMessageHeader.cpp | 1291 +++++++ src/core/basetypes/MCArray.cc | 283 -- src/core/basetypes/MCArray.cpp | 283 ++ src/core/basetypes/MCAutoreleasePool.cc | 123 - src/core/basetypes/MCAutoreleasePool.cpp | 123 + src/core/basetypes/MCConnectionLoggerUtils.cc | 55 - src/core/basetypes/MCConnectionLoggerUtils.cpp | 55 + src/core/basetypes/MCData.cc | 908 ----- src/core/basetypes/MCData.cpp | 908 +++++ src/core/basetypes/MCHTMLCleaner.cc | 125 - src/core/basetypes/MCHTMLCleaner.cpp | 125 + src/core/basetypes/MCHash.cc | 12 - src/core/basetypes/MCHash.cpp | 12 + src/core/basetypes/MCHashMap.cc | 331 -- src/core/basetypes/MCHashMap.cpp | 331 ++ src/core/basetypes/MCIndexSet.cc | 437 --- src/core/basetypes/MCIndexSet.cpp | 437 +++ src/core/basetypes/MCJSON.cc | 35 - src/core/basetypes/MCJSON.cpp | 35 + src/core/basetypes/MCJSONParser.cc | 827 ---- src/core/basetypes/MCJSONParser.cpp | 827 ++++ src/core/basetypes/MCLibetpan.cc | 223 -- src/core/basetypes/MCLibetpan.cpp | 223 ++ src/core/basetypes/MCMD5.cc | 233 -- src/core/basetypes/MCMD5.cpp | 233 ++ src/core/basetypes/MCNull.cc | 19 - src/core/basetypes/MCNull.cpp | 19 + src/core/basetypes/MCObject.cc | 449 --- src/core/basetypes/MCObject.cpp | 449 +++ src/core/basetypes/MCOperation.cc | 107 - src/core/basetypes/MCOperation.cpp | 107 + src/core/basetypes/MCOperationQueue.cc | 310 -- src/core/basetypes/MCOperationQueue.cpp | 310 ++ src/core/basetypes/MCRange.cc | 162 - src/core/basetypes/MCRange.cpp | 162 + src/core/basetypes/MCSet.cc | 126 - src/core/basetypes/MCSet.cpp | 126 + src/core/basetypes/MCString.cc | 2460 ------------ src/core/basetypes/MCString.cpp | 2460 ++++++++++++ src/core/basetypes/MCValue.cc | 459 --- src/core/basetypes/MCValue.cpp | 459 +++ src/core/imap/MCIMAPFolder.cc | 70 - src/core/imap/MCIMAPFolder.cpp | 70 + src/core/imap/MCIMAPFolderStatus.cc | 122 - src/core/imap/MCIMAPFolderStatus.cpp | 122 + src/core/imap/MCIMAPIdentity.cc | 97 - src/core/imap/MCIMAPIdentity.cpp | 97 + src/core/imap/MCIMAPMessage.cc | 324 -- src/core/imap/MCIMAPMessage.cpp | 324 ++ src/core/imap/MCIMAPMessagePart.cc | 67 - src/core/imap/MCIMAPMessagePart.cpp | 67 + src/core/imap/MCIMAPMultipart.cc | 68 - src/core/imap/MCIMAPMultipart.cpp | 68 + src/core/imap/MCIMAPNamespace.cc | 144 - src/core/imap/MCIMAPNamespace.cpp | 144 + src/core/imap/MCIMAPNamespaceItem.cc | 152 - src/core/imap/MCIMAPNamespaceItem.cpp | 152 + src/core/imap/MCIMAPPart.cc | 369 -- src/core/imap/MCIMAPPart.cpp | 369 ++ src/core/imap/MCIMAPSearchExpression.cc | 406 -- src/core/imap/MCIMAPSearchExpression.cpp | 406 ++ src/core/imap/MCIMAPSession.cc | 3940 -------------------- src/core/imap/MCIMAPSession.cpp | 3940 ++++++++++++++++++++ src/core/imap/MCIMAPSyncResult.cc | 46 - src/core/imap/MCIMAPSyncResult.cpp | 46 + src/core/nntp/MCNNTPGroupInfo.cc | 64 - src/core/nntp/MCNNTPGroupInfo.cpp | 64 + src/core/nntp/MCNNTPSession.cc | 893 ----- src/core/nntp/MCNNTPSession.cpp | 893 +++++ src/core/pop/MCPOPMessageInfo.cc | 69 - src/core/pop/MCPOPMessageInfo.cpp | 69 + src/core/pop/MCPOPSession.cc | 602 --- src/core/pop/MCPOPSession.cpp | 602 +++ src/core/provider/MCMailProvider.cc | 268 -- src/core/provider/MCMailProvider.cpp | 268 ++ src/core/provider/MCMailProvidersManager.cc | 71 - src/core/provider/MCMailProvidersManager.cpp | 71 + src/core/provider/MCNetService.cc | 146 - src/core/provider/MCNetService.cpp | 146 + src/core/renderer/MCAddressDisplay.cc | 90 - src/core/renderer/MCAddressDisplay.cpp | 90 + src/core/renderer/MCDateFormatter.cc | 262 -- src/core/renderer/MCDateFormatter.cpp | 262 ++ .../renderer/MCHTMLBodyRendererTemplateCallback.cc | 16 - .../MCHTMLBodyRendererTemplateCallback.cpp | 16 + src/core/renderer/MCHTMLRenderer.cc | 574 --- src/core/renderer/MCHTMLRenderer.cpp | 574 +++ src/core/renderer/MCHTMLRendererCallback.cc | 283 -- src/core/renderer/MCHTMLRendererCallback.cpp | 283 ++ .../renderer/MCHTMLRendererIMAPDataCallback.cc | 28 - .../renderer/MCHTMLRendererIMAPDataCallback.cpp | 28 + src/core/renderer/MCSizeFormatter.cc | 43 - src/core/renderer/MCSizeFormatter.cpp | 43 + src/core/rfc822/MCAttachment.cc | 607 --- src/core/rfc822/MCAttachment.cpp | 607 +++ src/core/rfc822/MCMessageBuilder.cc | 959 ----- src/core/rfc822/MCMessageBuilder.cpp | 959 +++++ src/core/rfc822/MCMessageParser.cc | 179 - src/core/rfc822/MCMessageParser.cpp | 179 + src/core/rfc822/MCMessagePart.cc | 20 - src/core/rfc822/MCMessagePart.cpp | 20 + src/core/rfc822/MCMultipart.cc | 21 - src/core/rfc822/MCMultipart.cpp | 21 + src/core/security/MCCertificateUtils.cc | 162 - src/core/security/MCCertificateUtils.cpp | 162 + src/core/smtp/MCSMTPSession.cc | 804 ---- src/core/smtp/MCSMTPSession.cpp | 804 ++++ src/core/zip/MCZip.cc | 170 - src/core/zip/MCZip.cpp | 170 + 233 files changed, 28258 insertions(+), 28258 deletions(-) delete mode 100644 src/async/imap/MCIMAPAppendMessageOperation.cc create mode 100644 src/async/imap/MCIMAPAppendMessageOperation.cpp delete mode 100755 src/async/imap/MCIMAPAsyncConnection.cc create mode 100755 src/async/imap/MCIMAPAsyncConnection.cpp delete mode 100755 src/async/imap/MCIMAPAsyncSession.cc create mode 100755 src/async/imap/MCIMAPAsyncSession.cpp delete mode 100644 src/async/imap/MCIMAPCapabilityOperation.cc create mode 100644 src/async/imap/MCIMAPCapabilityOperation.cpp delete mode 100644 src/async/imap/MCIMAPCheckAccountOperation.cc create mode 100644 src/async/imap/MCIMAPCheckAccountOperation.cpp delete mode 100644 src/async/imap/MCIMAPConnectOperation.cc create mode 100644 src/async/imap/MCIMAPConnectOperation.cpp delete mode 100644 src/async/imap/MCIMAPCopyMessagesOperation.cc create mode 100644 src/async/imap/MCIMAPCopyMessagesOperation.cpp delete mode 100644 src/async/imap/MCIMAPCreateFolderOperation.cc create mode 100644 src/async/imap/MCIMAPCreateFolderOperation.cpp delete mode 100644 src/async/imap/MCIMAPDeleteFolderOperation.cc create mode 100644 src/async/imap/MCIMAPDeleteFolderOperation.cpp delete mode 100644 src/async/imap/MCIMAPDisconnectOperation.cc create mode 100644 src/async/imap/MCIMAPDisconnectOperation.cpp delete mode 100644 src/async/imap/MCIMAPExpungeOperation.cc create mode 100644 src/async/imap/MCIMAPExpungeOperation.cpp delete mode 100644 src/async/imap/MCIMAPFetchContentOperation.cc create mode 100644 src/async/imap/MCIMAPFetchContentOperation.cpp delete mode 100644 src/async/imap/MCIMAPFetchFoldersOperation.cc create mode 100644 src/async/imap/MCIMAPFetchFoldersOperation.cpp delete mode 100644 src/async/imap/MCIMAPFetchMessagesOperation.cc create mode 100644 src/async/imap/MCIMAPFetchMessagesOperation.cpp delete mode 100644 src/async/imap/MCIMAPFetchNamespaceOperation.cc create mode 100644 src/async/imap/MCIMAPFetchNamespaceOperation.cpp delete mode 100644 src/async/imap/MCIMAPFetchParsedContentOperation.cc create mode 100644 src/async/imap/MCIMAPFetchParsedContentOperation.cpp delete mode 100644 src/async/imap/MCIMAPFolderInfoOperation.cc create mode 100644 src/async/imap/MCIMAPFolderInfoOperation.cpp delete mode 100644 src/async/imap/MCIMAPFolderStatusOperation.cc create mode 100644 src/async/imap/MCIMAPFolderStatusOperation.cpp delete mode 100644 src/async/imap/MCIMAPIdentityOperation.cc create mode 100644 src/async/imap/MCIMAPIdentityOperation.cpp delete mode 100644 src/async/imap/MCIMAPIdleOperation.cc create mode 100644 src/async/imap/MCIMAPIdleOperation.cpp delete mode 100644 src/async/imap/MCIMAPMessageRenderingOperation.cc create mode 100644 src/async/imap/MCIMAPMessageRenderingOperation.cpp delete mode 100644 src/async/imap/MCIMAPMultiDisconnectOperation.cc create mode 100644 src/async/imap/MCIMAPMultiDisconnectOperation.cpp delete mode 100644 src/async/imap/MCIMAPNoopOperation.cc create mode 100644 src/async/imap/MCIMAPNoopOperation.cpp delete mode 100644 src/async/imap/MCIMAPOperation.cc create mode 100644 src/async/imap/MCIMAPOperation.cpp delete mode 100644 src/async/imap/MCIMAPQuotaOperation.cc create mode 100644 src/async/imap/MCIMAPQuotaOperation.cpp delete mode 100644 src/async/imap/MCIMAPRenameFolderOperation.cc create mode 100644 src/async/imap/MCIMAPRenameFolderOperation.cpp delete mode 100644 src/async/imap/MCIMAPSearchOperation.cc create mode 100644 src/async/imap/MCIMAPSearchOperation.cpp delete mode 100644 src/async/imap/MCIMAPStoreFlagsOperation.cc create mode 100644 src/async/imap/MCIMAPStoreFlagsOperation.cpp delete mode 100644 src/async/imap/MCIMAPStoreLabelsOperation.cc create mode 100644 src/async/imap/MCIMAPStoreLabelsOperation.cpp delete mode 100644 src/async/imap/MCIMAPSubscribeFolderOperation.cc create mode 100644 src/async/imap/MCIMAPSubscribeFolderOperation.cpp delete mode 100644 src/async/nntp/MCNNTPAsyncSession.cc create mode 100644 src/async/nntp/MCNNTPAsyncSession.cpp delete mode 100644 src/async/nntp/MCNNTPCheckAccountOperation.cc create mode 100644 src/async/nntp/MCNNTPCheckAccountOperation.cpp delete mode 100644 src/async/nntp/MCNNTPDisconnectOperation.cc create mode 100644 src/async/nntp/MCNNTPDisconnectOperation.cpp delete mode 100644 src/async/nntp/MCNNTPFetchAllArticlesOperation.cc create mode 100644 src/async/nntp/MCNNTPFetchAllArticlesOperation.cpp delete mode 100644 src/async/nntp/MCNNTPFetchArticleOperation.cc create mode 100644 src/async/nntp/MCNNTPFetchArticleOperation.cpp delete mode 100644 src/async/nntp/MCNNTPFetchHeaderOperation.cc create mode 100644 src/async/nntp/MCNNTPFetchHeaderOperation.cpp delete mode 100644 src/async/nntp/MCNNTPFetchOverviewOperation.cc create mode 100644 src/async/nntp/MCNNTPFetchOverviewOperation.cpp delete mode 100644 src/async/nntp/MCNNTPFetchServerTimeOperation.cc create mode 100644 src/async/nntp/MCNNTPFetchServerTimeOperation.cpp delete mode 100644 src/async/nntp/MCNNTPListNewsgroupsOperation.cc create mode 100644 src/async/nntp/MCNNTPListNewsgroupsOperation.cpp delete mode 100644 src/async/nntp/MCNNTPOperation.cc create mode 100644 src/async/nntp/MCNNTPOperation.cpp delete mode 100644 src/async/pop/MCPOPAsyncSession.cc create mode 100644 src/async/pop/MCPOPAsyncSession.cpp delete mode 100644 src/async/pop/MCPOPCheckAccountOperation.cc create mode 100644 src/async/pop/MCPOPCheckAccountOperation.cpp delete mode 100644 src/async/pop/MCPOPDeleteMessagesOperation.cc create mode 100644 src/async/pop/MCPOPDeleteMessagesOperation.cpp delete mode 100644 src/async/pop/MCPOPFetchHeaderOperation.cc create mode 100644 src/async/pop/MCPOPFetchHeaderOperation.cpp delete mode 100644 src/async/pop/MCPOPFetchMessageOperation.cc create mode 100644 src/async/pop/MCPOPFetchMessageOperation.cpp delete mode 100644 src/async/pop/MCPOPFetchMessagesOperation.cc create mode 100644 src/async/pop/MCPOPFetchMessagesOperation.cpp delete mode 100644 src/async/pop/MCPOPNoopOperation.cc create mode 100644 src/async/pop/MCPOPNoopOperation.cpp delete mode 100644 src/async/pop/MCPOPOperation.cc create mode 100644 src/async/pop/MCPOPOperation.cpp delete mode 100644 src/async/smtp/MCSMTPAsyncSession.cc create mode 100644 src/async/smtp/MCSMTPAsyncSession.cpp delete mode 100644 src/async/smtp/MCSMTPCheckAccountOperation.cc create mode 100644 src/async/smtp/MCSMTPCheckAccountOperation.cpp delete mode 100644 src/async/smtp/MCSMTPDisconnectOperation.cc create mode 100644 src/async/smtp/MCSMTPDisconnectOperation.cpp delete mode 100644 src/async/smtp/MCSMTPLoginOperation.cc create mode 100644 src/async/smtp/MCSMTPLoginOperation.cpp delete mode 100644 src/async/smtp/MCSMTPNoopOperation.cc create mode 100644 src/async/smtp/MCSMTPNoopOperation.cpp delete mode 100644 src/async/smtp/MCSMTPOperation.cc create mode 100644 src/async/smtp/MCSMTPOperation.cpp delete mode 100644 src/async/smtp/MCSMTPSendWithDataOperation.cc create mode 100644 src/async/smtp/MCSMTPSendWithDataOperation.cpp delete mode 100644 src/core/abstract/MCAbstractMessage.cc create mode 100644 src/core/abstract/MCAbstractMessage.cpp delete mode 100644 src/core/abstract/MCAbstractMessagePart.cc create mode 100644 src/core/abstract/MCAbstractMessagePart.cpp delete mode 100644 src/core/abstract/MCAbstractMultipart.cc create mode 100644 src/core/abstract/MCAbstractMultipart.cpp delete mode 100644 src/core/abstract/MCAbstractPart.cc create mode 100644 src/core/abstract/MCAbstractPart.cpp delete mode 100644 src/core/abstract/MCAddress.cc create mode 100644 src/core/abstract/MCAddress.cpp delete mode 100644 src/core/abstract/MCMessageHeader.cc create mode 100644 src/core/abstract/MCMessageHeader.cpp delete mode 100644 src/core/basetypes/MCArray.cc create mode 100644 src/core/basetypes/MCArray.cpp delete mode 100644 src/core/basetypes/MCAutoreleasePool.cc create mode 100644 src/core/basetypes/MCAutoreleasePool.cpp delete mode 100644 src/core/basetypes/MCConnectionLoggerUtils.cc create mode 100644 src/core/basetypes/MCConnectionLoggerUtils.cpp delete mode 100644 src/core/basetypes/MCData.cc create mode 100644 src/core/basetypes/MCData.cpp delete mode 100644 src/core/basetypes/MCHTMLCleaner.cc create mode 100644 src/core/basetypes/MCHTMLCleaner.cpp delete mode 100644 src/core/basetypes/MCHash.cc create mode 100644 src/core/basetypes/MCHash.cpp delete mode 100644 src/core/basetypes/MCHashMap.cc create mode 100644 src/core/basetypes/MCHashMap.cpp delete mode 100644 src/core/basetypes/MCIndexSet.cc create mode 100644 src/core/basetypes/MCIndexSet.cpp delete mode 100644 src/core/basetypes/MCJSON.cc create mode 100644 src/core/basetypes/MCJSON.cpp delete mode 100644 src/core/basetypes/MCJSONParser.cc create mode 100644 src/core/basetypes/MCJSONParser.cpp delete mode 100644 src/core/basetypes/MCLibetpan.cc create mode 100644 src/core/basetypes/MCLibetpan.cpp delete mode 100644 src/core/basetypes/MCMD5.cc create mode 100644 src/core/basetypes/MCMD5.cpp delete mode 100644 src/core/basetypes/MCNull.cc create mode 100644 src/core/basetypes/MCNull.cpp delete mode 100644 src/core/basetypes/MCObject.cc create mode 100644 src/core/basetypes/MCObject.cpp delete mode 100644 src/core/basetypes/MCOperation.cc create mode 100644 src/core/basetypes/MCOperation.cpp delete mode 100644 src/core/basetypes/MCOperationQueue.cc create mode 100644 src/core/basetypes/MCOperationQueue.cpp delete mode 100644 src/core/basetypes/MCRange.cc create mode 100644 src/core/basetypes/MCRange.cpp delete mode 100644 src/core/basetypes/MCSet.cc create mode 100644 src/core/basetypes/MCSet.cpp delete mode 100644 src/core/basetypes/MCString.cc create mode 100644 src/core/basetypes/MCString.cpp delete mode 100644 src/core/basetypes/MCValue.cc create mode 100644 src/core/basetypes/MCValue.cpp delete mode 100644 src/core/imap/MCIMAPFolder.cc create mode 100644 src/core/imap/MCIMAPFolder.cpp delete mode 100644 src/core/imap/MCIMAPFolderStatus.cc create mode 100644 src/core/imap/MCIMAPFolderStatus.cpp delete mode 100644 src/core/imap/MCIMAPIdentity.cc create mode 100644 src/core/imap/MCIMAPIdentity.cpp delete mode 100644 src/core/imap/MCIMAPMessage.cc create mode 100644 src/core/imap/MCIMAPMessage.cpp delete mode 100644 src/core/imap/MCIMAPMessagePart.cc create mode 100644 src/core/imap/MCIMAPMessagePart.cpp delete mode 100644 src/core/imap/MCIMAPMultipart.cc create mode 100644 src/core/imap/MCIMAPMultipart.cpp delete mode 100644 src/core/imap/MCIMAPNamespace.cc create mode 100644 src/core/imap/MCIMAPNamespace.cpp delete mode 100644 src/core/imap/MCIMAPNamespaceItem.cc create mode 100644 src/core/imap/MCIMAPNamespaceItem.cpp delete mode 100644 src/core/imap/MCIMAPPart.cc create mode 100644 src/core/imap/MCIMAPPart.cpp delete mode 100644 src/core/imap/MCIMAPSearchExpression.cc create mode 100644 src/core/imap/MCIMAPSearchExpression.cpp delete mode 100755 src/core/imap/MCIMAPSession.cc create mode 100755 src/core/imap/MCIMAPSession.cpp delete mode 100644 src/core/imap/MCIMAPSyncResult.cc create mode 100644 src/core/imap/MCIMAPSyncResult.cpp delete mode 100644 src/core/nntp/MCNNTPGroupInfo.cc create mode 100644 src/core/nntp/MCNNTPGroupInfo.cpp delete mode 100644 src/core/nntp/MCNNTPSession.cc create mode 100644 src/core/nntp/MCNNTPSession.cpp delete mode 100644 src/core/pop/MCPOPMessageInfo.cc create mode 100644 src/core/pop/MCPOPMessageInfo.cpp delete mode 100644 src/core/pop/MCPOPSession.cc create mode 100644 src/core/pop/MCPOPSession.cpp delete mode 100644 src/core/provider/MCMailProvider.cc create mode 100644 src/core/provider/MCMailProvider.cpp delete mode 100644 src/core/provider/MCMailProvidersManager.cc create mode 100644 src/core/provider/MCMailProvidersManager.cpp delete mode 100644 src/core/provider/MCNetService.cc create mode 100644 src/core/provider/MCNetService.cpp delete mode 100644 src/core/renderer/MCAddressDisplay.cc create mode 100644 src/core/renderer/MCAddressDisplay.cpp delete mode 100644 src/core/renderer/MCDateFormatter.cc create mode 100644 src/core/renderer/MCDateFormatter.cpp delete mode 100644 src/core/renderer/MCHTMLBodyRendererTemplateCallback.cc create mode 100644 src/core/renderer/MCHTMLBodyRendererTemplateCallback.cpp delete mode 100644 src/core/renderer/MCHTMLRenderer.cc create mode 100644 src/core/renderer/MCHTMLRenderer.cpp delete mode 100644 src/core/renderer/MCHTMLRendererCallback.cc create mode 100644 src/core/renderer/MCHTMLRendererCallback.cpp delete mode 100644 src/core/renderer/MCHTMLRendererIMAPDataCallback.cc create mode 100644 src/core/renderer/MCHTMLRendererIMAPDataCallback.cpp delete mode 100644 src/core/renderer/MCSizeFormatter.cc create mode 100644 src/core/renderer/MCSizeFormatter.cpp delete mode 100644 src/core/rfc822/MCAttachment.cc create mode 100644 src/core/rfc822/MCAttachment.cpp delete mode 100644 src/core/rfc822/MCMessageBuilder.cc create mode 100644 src/core/rfc822/MCMessageBuilder.cpp delete mode 100644 src/core/rfc822/MCMessageParser.cc create mode 100644 src/core/rfc822/MCMessageParser.cpp delete mode 100644 src/core/rfc822/MCMessagePart.cc create mode 100644 src/core/rfc822/MCMessagePart.cpp delete mode 100644 src/core/rfc822/MCMultipart.cc create mode 100644 src/core/rfc822/MCMultipart.cpp delete mode 100644 src/core/security/MCCertificateUtils.cc create mode 100644 src/core/security/MCCertificateUtils.cpp delete mode 100644 src/core/smtp/MCSMTPSession.cc create mode 100644 src/core/smtp/MCSMTPSession.cpp delete mode 100644 src/core/zip/MCZip.cc create mode 100644 src/core/zip/MCZip.cpp diff --git a/build-mac/mailcore2.xcodeproj/project.pbxproj b/build-mac/mailcore2.xcodeproj/project.pbxproj index 72ba0fce..73897013 100755 --- a/build-mac/mailcore2.xcodeproj/project.pbxproj +++ b/build-mac/mailcore2.xcodeproj/project.pbxproj @@ -13,17 +13,17 @@ 27780C3D19CF9D9800C77E44 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27780C3C19CF9D9800C77E44 /* CFNetwork.framework */; }; 27780C3E19CF9DDF00C77E44 /* libMailCore-ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C6BA2C191705F4E6003F0E9E /* libMailCore-ios.a */; }; 4B3C1BDE17ABF309008BBF4C /* MCOIMAPQuotaOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B3C1BDD17ABF307008BBF4C /* MCOIMAPQuotaOperation.mm */; }; - 4B3C1BE117ABF4BC008BBF4C /* MCIMAPQuotaOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4B3C1BDF17ABF4BB008BBF4C /* MCIMAPQuotaOperation.cc */; }; + 4B3C1BE117ABF4BC008BBF4C /* MCIMAPQuotaOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B3C1BDF17ABF4BB008BBF4C /* MCIMAPQuotaOperation.cpp */; }; 4B3C1BE217ABFF7C008BBF4C /* MCOIMAPQuotaOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4B3C1BDC17ABF306008BBF4C /* MCOIMAPQuotaOperation.h */; }; 4B3C1BE317ABFF91008BBF4C /* MCOIMAPQuotaOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B3C1BDD17ABF307008BBF4C /* MCOIMAPQuotaOperation.mm */; }; 4B3C1BE417AC0156008BBF4C /* MCIMAPQuotaOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4B3C1BE017ABF4BC008BBF4C /* MCIMAPQuotaOperation.h */; }; - 4B3C1BE517AC0176008BBF4C /* MCIMAPQuotaOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4B3C1BDF17ABF4BB008BBF4C /* MCIMAPQuotaOperation.cc */; }; + 4B3C1BE517AC0176008BBF4C /* MCIMAPQuotaOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B3C1BDF17ABF4BB008BBF4C /* MCIMAPQuotaOperation.cpp */; }; 4BE4029117B548B900ECC5E4 /* MCOIMAPQuotaOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4B3C1BDC17ABF306008BBF4C /* MCOIMAPQuotaOperation.h */; }; 4BE4029217B548D900ECC5E4 /* MCIMAPQuotaOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4B3C1BE017ABF4BC008BBF4C /* MCIMAPQuotaOperation.h */; }; 8199FBEB19FAEA440040BBC3 /* MCOIMAPFetchParsedContentOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8199FBE819FAEA440040BBC3 /* MCOIMAPFetchParsedContentOperation.mm */; }; 8199FBEC19FAEA440040BBC3 /* MCOIMAPFetchParsedContentOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8199FBE819FAEA440040BBC3 /* MCOIMAPFetchParsedContentOperation.mm */; }; - 8199FBF119FAF1270040BBC3 /* MCIMAPFetchParsedContentOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8199FBEF19FAF1270040BBC3 /* MCIMAPFetchParsedContentOperation.cc */; }; - 8199FBF219FAF1270040BBC3 /* MCIMAPFetchParsedContentOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8199FBEF19FAF1270040BBC3 /* MCIMAPFetchParsedContentOperation.cc */; }; + 8199FBF119FAF1270040BBC3 /* MCIMAPFetchParsedContentOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8199FBEF19FAF1270040BBC3 /* MCIMAPFetchParsedContentOperation.cpp */; }; + 8199FBF219FAF1270040BBC3 /* MCIMAPFetchParsedContentOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8199FBEF19FAF1270040BBC3 /* MCIMAPFetchParsedContentOperation.cpp */; }; 8199FBF719FAF3AF0040BBC3 /* MCOIMAPFetchParsedContentOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8199FBE719FAEA440040BBC3 /* MCOIMAPFetchParsedContentOperation.h */; }; 8199FBF819FAF3AF0040BBC3 /* MCIMAPFetchParsedContentOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8199FBF019FAF1270040BBC3 /* MCIMAPFetchParsedContentOperation.h */; }; 8416A99D17F284F400B3C7DA /* MCOSMTPNoopOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8416A99C17F284F400B3C7DA /* MCOSMTPNoopOperation.mm */; }; @@ -37,23 +37,23 @@ 84391346199C3ABB00FEFCDD /* MCONNTPGroupInfo.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84D73791199C0511005124E5 /* MCONNTPGroupInfo.h */; }; 84391347199C3ABD00FEFCDD /* MCONNTPGroupInfo.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84D73791199C0511005124E5 /* MCONNTPGroupInfo.h */; }; 84915BB8199C4B0400EDDED9 /* MCNNTP.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8491899C18C93F92002063A3 /* MCNNTP.h */; }; - 849189A118C93FB7002063A3 /* MCNNTPSession.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8491899F18C93FB7002063A3 /* MCNNTPSession.cc */; }; - 849189A218C93FB7002063A3 /* MCNNTPSession.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8491899F18C93FB7002063A3 /* MCNNTPSession.cc */; }; + 849189A118C93FB7002063A3 /* MCNNTPSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8491899F18C93FB7002063A3 /* MCNNTPSession.cpp */; }; + 849189A218C93FB7002063A3 /* MCNNTPSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8491899F18C93FB7002063A3 /* MCNNTPSession.cpp */; }; 849189A318C94023002063A3 /* MCNNTP.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8491899C18C93F92002063A3 /* MCNNTP.h */; }; 849189A418C94023002063A3 /* MCNNTPSession.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 849189A018C93FB7002063A3 /* MCNNTPSession.h */; }; - 849189AB18C94986002063A3 /* MCNNTPGroupInfo.cc in Sources */ = {isa = PBXBuildFile; fileRef = 849189A918C94986002063A3 /* MCNNTPGroupInfo.cc */; }; - 849189AC18C94986002063A3 /* MCNNTPGroupInfo.cc in Sources */ = {isa = PBXBuildFile; fileRef = 849189A918C94986002063A3 /* MCNNTPGroupInfo.cc */; }; + 849189AB18C94986002063A3 /* MCNNTPGroupInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 849189A918C94986002063A3 /* MCNNTPGroupInfo.cpp */; }; + 849189AC18C94986002063A3 /* MCNNTPGroupInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 849189A918C94986002063A3 /* MCNNTPGroupInfo.cpp */; }; 849F53D817F28443002D417F /* MCOPOPNoopOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84B639EF17F282B4003B5BA2 /* MCOPOPNoopOperation.h */; }; 849F53D917F28443002D417F /* MCIMAPNoopOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84B639EC17F280F3003B5BA2 /* MCIMAPNoopOperation.h */; }; 849F53DA17F28443002D417F /* MCPOPNoopOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84B639E717F27EBD003B5BA2 /* MCPOPNoopOperation.h */; }; 849F53DB17F28443002D417F /* MCSMTPNoopOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84B639E217F279BB003B5BA2 /* MCSMTPNoopOperation.h */; }; 84AF9E7E172DBAF600E60AA3 /* providers.json in Resources */ = {isa = PBXBuildFile; fileRef = 84AF9E7D172DBAF600E60AA3 /* providers.json */; }; - 84B639E317F279BB003B5BA2 /* MCSMTPNoopOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 84B639E117F279BB003B5BA2 /* MCSMTPNoopOperation.cc */; }; - 84B639E417F279BB003B5BA2 /* MCSMTPNoopOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 84B639E117F279BB003B5BA2 /* MCSMTPNoopOperation.cc */; }; - 84B639E817F27EBD003B5BA2 /* MCPOPNoopOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 84B639E617F27EBD003B5BA2 /* MCPOPNoopOperation.cc */; }; - 84B639E917F27EBD003B5BA2 /* MCPOPNoopOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 84B639E617F27EBD003B5BA2 /* MCPOPNoopOperation.cc */; }; - 84B639ED17F280F3003B5BA2 /* MCIMAPNoopOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 84B639EB17F280F3003B5BA2 /* MCIMAPNoopOperation.cc */; }; - 84B639EE17F280F3003B5BA2 /* MCIMAPNoopOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 84B639EB17F280F3003B5BA2 /* MCIMAPNoopOperation.cc */; }; + 84B639E317F279BB003B5BA2 /* MCSMTPNoopOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84B639E117F279BB003B5BA2 /* MCSMTPNoopOperation.cpp */; }; + 84B639E417F279BB003B5BA2 /* MCSMTPNoopOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84B639E117F279BB003B5BA2 /* MCSMTPNoopOperation.cpp */; }; + 84B639E817F27EBD003B5BA2 /* MCPOPNoopOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84B639E617F27EBD003B5BA2 /* MCPOPNoopOperation.cpp */; }; + 84B639E917F27EBD003B5BA2 /* MCPOPNoopOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84B639E617F27EBD003B5BA2 /* MCPOPNoopOperation.cpp */; }; + 84B639ED17F280F3003B5BA2 /* MCIMAPNoopOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84B639EB17F280F3003B5BA2 /* MCIMAPNoopOperation.cpp */; }; + 84B639EE17F280F3003B5BA2 /* MCIMAPNoopOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84B639EB17F280F3003B5BA2 /* MCIMAPNoopOperation.cpp */; }; 84B639F117F282B4003B5BA2 /* MCOPOPNoopOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 84B639F017F282B4003B5BA2 /* MCOPOPNoopOperation.mm */; }; 84B639F217F282B4003B5BA2 /* MCOPOPNoopOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 84B639F017F282B4003B5BA2 /* MCOPOPNoopOperation.mm */; }; 84B639F317F2839C003B5BA2 /* MCOPOPNoopOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84B639EF17F282B4003B5BA2 /* MCOPOPNoopOperation.h */; }; @@ -62,28 +62,28 @@ 84B639F617F2839C003B5BA2 /* MCSMTPNoopOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84B639E217F279BB003B5BA2 /* MCSMTPNoopOperation.h */; }; 84CFA98319F7153B00FE35D2 /* MCONNTPFetchOverviewOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 84CFA98219F7153B00FE35D2 /* MCONNTPFetchOverviewOperation.mm */; }; 84CFA98419F7153B00FE35D2 /* MCONNTPFetchOverviewOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 84CFA98219F7153B00FE35D2 /* MCONNTPFetchOverviewOperation.mm */; }; - 84CFA98719F7159700FE35D2 /* MCNNTPFetchOverviewOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 84CFA98519F7159700FE35D2 /* MCNNTPFetchOverviewOperation.cc */; }; - 84CFA98819F7159700FE35D2 /* MCNNTPFetchOverviewOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 84CFA98519F7159700FE35D2 /* MCNNTPFetchOverviewOperation.cc */; }; - 84CFA98F19F724E500FE35D2 /* MCNNTPFetchServerTimeOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 84CFA98D19F724E500FE35D2 /* MCNNTPFetchServerTimeOperation.cc */; }; - 84CFA99019F724E500FE35D2 /* MCNNTPFetchServerTimeOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 84CFA98D19F724E500FE35D2 /* MCNNTPFetchServerTimeOperation.cc */; }; + 84CFA98719F7159700FE35D2 /* MCNNTPFetchOverviewOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84CFA98519F7159700FE35D2 /* MCNNTPFetchOverviewOperation.cpp */; }; + 84CFA98819F7159700FE35D2 /* MCNNTPFetchOverviewOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84CFA98519F7159700FE35D2 /* MCNNTPFetchOverviewOperation.cpp */; }; + 84CFA98F19F724E500FE35D2 /* MCNNTPFetchServerTimeOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84CFA98D19F724E500FE35D2 /* MCNNTPFetchServerTimeOperation.cpp */; }; + 84CFA99019F724E500FE35D2 /* MCNNTPFetchServerTimeOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84CFA98D19F724E500FE35D2 /* MCNNTPFetchServerTimeOperation.cpp */; }; 84CFA99519F725CB00FE35D2 /* MCONNTPFetchServerTimeOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 84CFA99419F725CB00FE35D2 /* MCONNTPFetchServerTimeOperation.mm */; }; 84CFA99619F725CB00FE35D2 /* MCONNTPFetchServerTimeOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 84CFA99419F725CB00FE35D2 /* MCONNTPFetchServerTimeOperation.mm */; }; - 84D7372C199BF66C005124E5 /* MCNNTPAsyncSession.cc in Sources */ = {isa = PBXBuildFile; fileRef = 84D7372A199BF66C005124E5 /* MCNNTPAsyncSession.cc */; }; - 84D7372D199BF66C005124E5 /* MCNNTPAsyncSession.cc in Sources */ = {isa = PBXBuildFile; fileRef = 84D7372A199BF66C005124E5 /* MCNNTPAsyncSession.cc */; }; - 84D73730199BF704005124E5 /* MCNNTPOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 84D7372E199BF704005124E5 /* MCNNTPOperation.cc */; }; - 84D73731199BF704005124E5 /* MCNNTPOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 84D7372E199BF704005124E5 /* MCNNTPOperation.cc */; }; + 84D7372C199BF66C005124E5 /* MCNNTPAsyncSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84D7372A199BF66C005124E5 /* MCNNTPAsyncSession.cpp */; }; + 84D7372D199BF66C005124E5 /* MCNNTPAsyncSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84D7372A199BF66C005124E5 /* MCNNTPAsyncSession.cpp */; }; + 84D73730199BF704005124E5 /* MCNNTPOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84D7372E199BF704005124E5 /* MCNNTPOperation.cpp */; }; + 84D73731199BF704005124E5 /* MCNNTPOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84D7372E199BF704005124E5 /* MCNNTPOperation.cpp */; }; 84D73733199BF7A7005124E5 /* MCNNTPProgressCallback.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84D73732199BF754005124E5 /* MCNNTPProgressCallback.h */; }; 84D73734199BF7A9005124E5 /* MCNNTPProgressCallback.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84D73732199BF754005124E5 /* MCNNTPProgressCallback.h */; }; - 84D73737199BF7F2005124E5 /* MCNNTPFetchHeaderOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 84D73735199BF7F2005124E5 /* MCNNTPFetchHeaderOperation.cc */; }; - 84D73738199BF7F2005124E5 /* MCNNTPFetchHeaderOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 84D73735199BF7F2005124E5 /* MCNNTPFetchHeaderOperation.cc */; }; + 84D73737199BF7F2005124E5 /* MCNNTPFetchHeaderOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84D73735199BF7F2005124E5 /* MCNNTPFetchHeaderOperation.cpp */; }; + 84D73738199BF7F2005124E5 /* MCNNTPFetchHeaderOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84D73735199BF7F2005124E5 /* MCNNTPFetchHeaderOperation.cpp */; }; 84D73739199BF81A005124E5 /* MCNNTPOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84D7372F199BF704005124E5 /* MCNNTPOperation.h */; }; 84D7373A199BF81D005124E5 /* MCNNTPOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84D7372F199BF704005124E5 /* MCNNTPOperation.h */; }; - 84D7373D199BF83B005124E5 /* MCNNTPFetchArticleOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 84D7373B199BF83B005124E5 /* MCNNTPFetchArticleOperation.cc */; }; - 84D7373E199BF83B005124E5 /* MCNNTPFetchArticleOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 84D7373B199BF83B005124E5 /* MCNNTPFetchArticleOperation.cc */; }; - 84D73742199BF963005124E5 /* MCNNTPFetchAllArticlesOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 84D73740199BF963005124E5 /* MCNNTPFetchAllArticlesOperation.cc */; }; - 84D73743199BF963005124E5 /* MCNNTPFetchAllArticlesOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 84D73740199BF963005124E5 /* MCNNTPFetchAllArticlesOperation.cc */; }; - 84D73746199BFA8C005124E5 /* MCNNTPCheckAccountOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 84D73744199BFA8C005124E5 /* MCNNTPCheckAccountOperation.cc */; }; - 84D73747199BFA8C005124E5 /* MCNNTPCheckAccountOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 84D73744199BFA8C005124E5 /* MCNNTPCheckAccountOperation.cc */; }; + 84D7373D199BF83B005124E5 /* MCNNTPFetchArticleOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84D7373B199BF83B005124E5 /* MCNNTPFetchArticleOperation.cpp */; }; + 84D7373E199BF83B005124E5 /* MCNNTPFetchArticleOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84D7373B199BF83B005124E5 /* MCNNTPFetchArticleOperation.cpp */; }; + 84D73742199BF963005124E5 /* MCNNTPFetchAllArticlesOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84D73740199BF963005124E5 /* MCNNTPFetchAllArticlesOperation.cpp */; }; + 84D73743199BF963005124E5 /* MCNNTPFetchAllArticlesOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84D73740199BF963005124E5 /* MCNNTPFetchAllArticlesOperation.cpp */; }; + 84D73746199BFA8C005124E5 /* MCNNTPCheckAccountOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84D73744199BFA8C005124E5 /* MCNNTPCheckAccountOperation.cpp */; }; + 84D73747199BFA8C005124E5 /* MCNNTPCheckAccountOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84D73744199BFA8C005124E5 /* MCNNTPCheckAccountOperation.cpp */; }; 84D73748199BFACA005124E5 /* MCNNTPAsyncSession.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84D7372B199BF66C005124E5 /* MCNNTPAsyncSession.h */; }; 84D73749199BFACF005124E5 /* MCNNTPAsyncSession.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84D7372B199BF66C005124E5 /* MCNNTPAsyncSession.h */; }; 84D7374A199BFB92005124E5 /* MCAsyncNNTP.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84D73729199BF63F005124E5 /* MCAsyncNNTP.h */; }; @@ -98,10 +98,10 @@ 84D73753199BFBE6005124E5 /* MCNNTPCheckAccountOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84D73745199BFA8C005124E5 /* MCNNTPCheckAccountOperation.h */; }; 84D73754199BFBEC005124E5 /* MCNNTPOperationCallback.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84D7373F199BF887005124E5 /* MCNNTPOperationCallback.h */; }; 84D73755199BFBF2005124E5 /* MCNNTPOperationCallback.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84D7373F199BF887005124E5 /* MCNNTPOperationCallback.h */; }; - 84D73758199BFC8A005124E5 /* MCNNTPDisconnectOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 84D73756199BFC8A005124E5 /* MCNNTPDisconnectOperation.cc */; }; - 84D73759199BFC8A005124E5 /* MCNNTPDisconnectOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 84D73756199BFC8A005124E5 /* MCNNTPDisconnectOperation.cc */; }; - 84D7375C199BFDCA005124E5 /* MCNNTPListNewsgroupsOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 84D7375A199BFDCA005124E5 /* MCNNTPListNewsgroupsOperation.cc */; }; - 84D7375D199BFDCA005124E5 /* MCNNTPListNewsgroupsOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 84D7375A199BFDCA005124E5 /* MCNNTPListNewsgroupsOperation.cc */; }; + 84D73758199BFC8A005124E5 /* MCNNTPDisconnectOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84D73756199BFC8A005124E5 /* MCNNTPDisconnectOperation.cpp */; }; + 84D73759199BFC8A005124E5 /* MCNNTPDisconnectOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84D73756199BFC8A005124E5 /* MCNNTPDisconnectOperation.cpp */; }; + 84D7375C199BFDCA005124E5 /* MCNNTPListNewsgroupsOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84D7375A199BFDCA005124E5 /* MCNNTPListNewsgroupsOperation.cpp */; }; + 84D7375D199BFDCA005124E5 /* MCNNTPListNewsgroupsOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84D7375A199BFDCA005124E5 /* MCNNTPListNewsgroupsOperation.cpp */; }; 84D7375E199BFF34005124E5 /* MCNNTPListNewsgroupsOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84D7375B199BFDCA005124E5 /* MCNNTPListNewsgroupsOperation.h */; }; 84D7375F199BFF38005124E5 /* MCNNTPListNewsgroupsOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84D7375B199BFDCA005124E5 /* MCNNTPListNewsgroupsOperation.h */; }; 84D73764199BFFC7005124E5 /* MCONNTPSession.mm in Sources */ = {isa = PBXBuildFile; fileRef = 84D73763199BFFC7005124E5 /* MCONNTPSession.mm */; }; @@ -135,24 +135,24 @@ 84E65533199BE15500EC8CC4 /* MCNNTPSession.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 849189A018C93FB7002063A3 /* MCNNTPSession.h */; }; 84E65534199BE2BF00EC8CC4 /* MCNNTPGroupInfo.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 849189AA18C94986002063A3 /* MCNNTPGroupInfo.h */; }; 84E65535199BE2C300EC8CC4 /* MCNNTPGroupInfo.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 849189AA18C94986002063A3 /* MCNNTPGroupInfo.h */; }; - 8B0095C91A00DDC500F84BC0 /* MCSMTPLoginOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8B0095C71A00DDC500F84BC0 /* MCSMTPLoginOperation.cc */; }; + 8B0095C91A00DDC500F84BC0 /* MCSMTPLoginOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8B0095C71A00DDC500F84BC0 /* MCSMTPLoginOperation.cpp */; }; 8B0095CC1A00DDE700F84BC0 /* MCOSMTPLoginOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8B0095CB1A00DDE700F84BC0 /* MCOSMTPLoginOperation.mm */; }; 8B0095CD1A00DE2A00F84BC0 /* MCOSMTPLoginOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8B0095CA1A00DDE700F84BC0 /* MCOSMTPLoginOperation.h */; }; 8B0095CE1A00DE7700F84BC0 /* MCOSMTPLoginOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8B0095CB1A00DDE700F84BC0 /* MCOSMTPLoginOperation.mm */; }; - 8B0095CF1A00DE7700F84BC0 /* MCSMTPLoginOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8B0095C71A00DDC500F84BC0 /* MCSMTPLoginOperation.cc */; }; + 8B0095CF1A00DE7700F84BC0 /* MCSMTPLoginOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8B0095C71A00DDC500F84BC0 /* MCSMTPLoginOperation.cpp */; }; 8B5764371A00E1B0004868C0 /* MCOSMTPLoginOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8B0095CA1A00DDE700F84BC0 /* MCOSMTPLoginOperation.h */; }; - 943F1A9A17D964F600F0C798 /* MCIMAPConnectOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 943F1A9817D964F600F0C798 /* MCIMAPConnectOperation.cc */; }; - 943F1A9E17D96C5500F0C798 /* MCIMAPConnectOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 943F1A9817D964F600F0C798 /* MCIMAPConnectOperation.cc */; }; + 943F1A9A17D964F600F0C798 /* MCIMAPConnectOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 943F1A9817D964F600F0C798 /* MCIMAPConnectOperation.cpp */; }; + 943F1A9E17D96C5500F0C798 /* MCIMAPConnectOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 943F1A9817D964F600F0C798 /* MCIMAPConnectOperation.cpp */; }; 943F1AA017D9736100F0C798 /* MCIMAPConnectOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 943F1A9917D964F600F0C798 /* MCIMAPConnectOperation.h */; }; 943F1AA117D973A800F0C798 /* MCIMAPConnectOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 943F1A9917D964F600F0C798 /* MCIMAPConnectOperation.h */; }; - 9E774D891767C7F60065EB9B /* MCIMAPFolderStatus.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9E774D881767C7F60065EB9B /* MCIMAPFolderStatus.cc */; }; - 9E774D8A1767C7F60065EB9B /* MCIMAPFolderStatus.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9E774D881767C7F60065EB9B /* MCIMAPFolderStatus.cc */; }; + 9E774D891767C7F60065EB9B /* MCIMAPFolderStatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E774D881767C7F60065EB9B /* MCIMAPFolderStatus.cpp */; }; + 9E774D8A1767C7F60065EB9B /* MCIMAPFolderStatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E774D881767C7F60065EB9B /* MCIMAPFolderStatus.cpp */; }; 9E774D8B1767CD3C0065EB9B /* MCIMAPFolderStatus.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9E774D871767C54E0065EB9B /* MCIMAPFolderStatus.h */; }; 9E774D8C1767CD490065EB9B /* MCIMAPFolderStatus.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9E774D871767C54E0065EB9B /* MCIMAPFolderStatus.h */; }; 9EF9AB09175F2EC60027FA3B /* MCOIMAPFolderStatus.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9EF9AB07175F2EC60027FA3B /* MCOIMAPFolderStatus.mm */; }; 9EF9AB0A175F2EC60027FA3B /* MCOIMAPFolderStatus.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9EF9AB07175F2EC60027FA3B /* MCOIMAPFolderStatus.mm */; }; - 9EF9AB11175F319A0027FA3B /* MCIMAPFolderStatusOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9EF9AB10175F319A0027FA3B /* MCIMAPFolderStatusOperation.cc */; }; - 9EF9AB12175F319A0027FA3B /* MCIMAPFolderStatusOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9EF9AB10175F319A0027FA3B /* MCIMAPFolderStatusOperation.cc */; }; + 9EF9AB11175F319A0027FA3B /* MCIMAPFolderStatusOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9EF9AB10175F319A0027FA3B /* MCIMAPFolderStatusOperation.cpp */; }; + 9EF9AB12175F319A0027FA3B /* MCIMAPFolderStatusOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9EF9AB10175F319A0027FA3B /* MCIMAPFolderStatusOperation.cpp */; }; 9EF9AB19175F36600027FA3B /* MCOIMAPFolderStatusOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9EF9AB18175F36600027FA3B /* MCOIMAPFolderStatusOperation.mm */; }; 9EF9AB1A175F36600027FA3B /* MCOIMAPFolderStatusOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9EF9AB18175F36600027FA3B /* MCOIMAPFolderStatusOperation.mm */; }; 9EF9AB20175F3FD10027FA3B /* MCOIMAPFolderStatus.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9EF9AB06175F2EC60027FA3B /* MCOIMAPFolderStatus.h */; }; @@ -165,17 +165,17 @@ BD49963819FEC6DD000945BC /* ConvertUTF.c in Sources */ = {isa = PBXBuildFile; fileRef = BD49963519FEC6DD000945BC /* ConvertUTF.c */; }; BD6272981A13FF2A00129AA8 /* test-all-mac.mm in Sources */ = {isa = PBXBuildFile; fileRef = BD6272961A13FF2A00129AA8 /* test-all-mac.mm */; }; BD6272991A13FF2A00129AA8 /* test-all-mac.mm in Sources */ = {isa = PBXBuildFile; fileRef = BD6272961A13FF2A00129AA8 /* test-all-mac.mm */; }; - BD63713B177DFF080094121B /* MCLibetpan.cc in Sources */ = {isa = PBXBuildFile; fileRef = BD637139177DFF080094121B /* MCLibetpan.cc */; }; + BD63713B177DFF080094121B /* 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 */; }; - C608167517759967001F1018 /* MCSMTPDisconnectOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C608167317759967001F1018 /* MCSMTPDisconnectOperation.cc */; }; - C608167617759968001F1018 /* MCSMTPDisconnectOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C608167317759967001F1018 /* MCSMTPDisconnectOperation.cc */; }; - C608167B177635D2001F1018 /* MCIMAPDisconnectOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C6081679177635D2001F1018 /* MCIMAPDisconnectOperation.cc */; }; - C608167C177635D2001F1018 /* MCIMAPDisconnectOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C6081679177635D2001F1018 /* MCIMAPDisconnectOperation.cc */; }; + C608167517759967001F1018 /* MCSMTPDisconnectOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C608167317759967001F1018 /* MCSMTPDisconnectOperation.cpp */; }; + C608167617759968001F1018 /* MCSMTPDisconnectOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C608167317759967001F1018 /* MCSMTPDisconnectOperation.cpp */; }; + C608167B177635D2001F1018 /* MCIMAPDisconnectOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6081679177635D2001F1018 /* MCIMAPDisconnectOperation.cpp */; }; + C608167C177635D2001F1018 /* MCIMAPDisconnectOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6081679177635D2001F1018 /* MCIMAPDisconnectOperation.cpp */; }; C6181D3219FE0F8A0088FBBC /* MCOIMAPFetchParsedContentOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8199FBE719FAEA440040BBC3 /* MCOIMAPFetchParsedContentOperation.h */; }; C6181D3319FE0F8D0088FBBC /* MCIMAPFetchParsedContentOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8199FBF019FAF1270040BBC3 /* MCIMAPFetchParsedContentOperation.h */; }; - C61CC25819765763004A28D3 /* MCLibetpan.cc in Sources */ = {isa = PBXBuildFile; fileRef = BD637139177DFF080094121B /* MCLibetpan.cc */; }; + C61CC25819765763004A28D3 /* MCLibetpan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BD637139177DFF080094121B /* MCLibetpan.cpp */; }; C623C58616FD6A50001BBEFC /* MCOConstants.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64BB26D16FD63F6000DB34C /* MCOConstants.h */; }; C623C58716FD6A61001BBEFC /* MCOOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64BB25716FD3BC2000DB34C /* MCOOperation.h */; }; C623C58816FD6DF6001BBEFC /* NSValue+MCO.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64BB25016FC2846000DB34C /* NSValue+MCO.h */; }; @@ -184,9 +184,9 @@ C623C58F16FE6B45001BBEFC /* MCOIMAPOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = C623C58E16FE6B45001BBEFC /* MCOIMAPOperation.mm */; }; C623C59016FE71B2001BBEFC /* MCOIMAPOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C623C58D16FE6B45001BBEFC /* MCOIMAPOperation.h */; }; C623C59316FE750E001BBEFC /* MCOIMAPFolder.mm in Sources */ = {isa = PBXBuildFile; fileRef = C623C59216FE750E001BBEFC /* MCOIMAPFolder.mm */; }; - C62C6ED416A2A0E600737497 /* MCIMAPIdentityOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C62C6ED216A2A0E600737497 /* MCIMAPIdentityOperation.cc */; }; - C62C6ED816A398FA00737497 /* MCIMAPFolderInfoOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C62C6ED616A398FA00737497 /* MCIMAPFolderInfoOperation.cc */; }; - C62C6EDA16A3D60700737497 /* MCIMAPAsyncConnection.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA7FD16A295B500778456 /* MCIMAPAsyncConnection.cc */; }; + C62C6ED416A2A0E600737497 /* MCIMAPIdentityOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C62C6ED216A2A0E600737497 /* MCIMAPIdentityOperation.cpp */; }; + C62C6ED816A398FA00737497 /* MCIMAPFolderInfoOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C62C6ED616A398FA00737497 /* MCIMAPFolderInfoOperation.cpp */; }; + C62C6EDA16A3D60700737497 /* MCIMAPAsyncConnection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA7FD16A295B500778456 /* MCIMAPAsyncConnection.cpp */; }; C62C6EDB16A3FC8700737497 /* MCIMAPOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64EA7F016A15A4D00778456 /* MCIMAPOperation.h */; }; C62C6EE016A696AB00737497 /* MCAsyncIMAP.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64EA7F916A15A9200778456 /* MCAsyncIMAP.h */; }; C62C6EE216A696B400737497 /* MCIMAPFetchFoldersOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64EA7FB16A2959700778456 /* MCIMAPFetchFoldersOperation.h */; }; @@ -200,35 +200,35 @@ C62C6EEA16A6972100737497 /* MCIMAPFetchNamespaceOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64EA82B16A2A01400778456 /* MCIMAPFetchNamespaceOperation.h */; }; C62C6EEB16A6972700737497 /* MCIMAPIdentityOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C62C6ED316A2A0E600737497 /* MCIMAPIdentityOperation.h */; }; C62C6EEC16A69D3D00737497 /* MCIMAPOperationCallback.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64EA7F416A15A6300778456 /* MCIMAPOperationCallback.h */; }; - C62C6EEF16A7B67600737497 /* MCPOPAsyncSession.cc in Sources */ = {isa = PBXBuildFile; fileRef = C62C6EED16A7B67600737497 /* MCPOPAsyncSession.cc */; }; - C62C6EF216A7C6DE00737497 /* MCPOPFetchHeaderOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C62C6EF016A7C6DE00737497 /* MCPOPFetchHeaderOperation.cc */; }; - C62C6EF516A7C6EA00737497 /* MCPOPFetchMessageOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C62C6EF316A7C6E900737497 /* MCPOPFetchMessageOperation.cc */; }; - C62C6EF816A7C6F500737497 /* MCPOPDeleteMessagesOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C62C6EF616A7C6F500737497 /* MCPOPDeleteMessagesOperation.cc */; }; - C62C6EFB16A7C94000737497 /* MCPOPOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C62C6EF916A7C93F00737497 /* MCPOPOperation.cc */; }; + C62C6EEF16A7B67600737497 /* MCPOPAsyncSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C62C6EED16A7B67600737497 /* MCPOPAsyncSession.cpp */; }; + C62C6EF216A7C6DE00737497 /* MCPOPFetchHeaderOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C62C6EF016A7C6DE00737497 /* MCPOPFetchHeaderOperation.cpp */; }; + C62C6EF516A7C6EA00737497 /* MCPOPFetchMessageOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C62C6EF316A7C6E900737497 /* MCPOPFetchMessageOperation.cpp */; }; + C62C6EF816A7C6F500737497 /* MCPOPDeleteMessagesOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C62C6EF616A7C6F500737497 /* MCPOPDeleteMessagesOperation.cpp */; }; + C62C6EFB16A7C94000737497 /* MCPOPOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C62C6EF916A7C93F00737497 /* MCPOPOperation.cpp */; }; C62C6EFE16A7DD0D00737497 /* MCPOPOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C62C6EFA16A7C94000737497 /* MCPOPOperation.h */; }; C62C6EFF16A7E30900737497 /* MCPOPAsyncSession.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C62C6EEE16A7B67600737497 /* MCPOPAsyncSession.h */; }; C62C6F0016A7E32800737497 /* MCPOPFetchHeaderOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C62C6EF116A7C6DE00737497 /* MCPOPFetchHeaderOperation.h */; }; C62C6F0116A7E32F00737497 /* MCPOPFetchMessageOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C62C6EF416A7C6E900737497 /* MCPOPFetchMessageOperation.h */; }; C62C6F0216A7E3A700737497 /* MCAsyncPOP.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C62C6EFD16A7DD0300737497 /* MCAsyncPOP.h */; }; C62C6F0316A7E3B000737497 /* MCPOPOperationCallback.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C62C6EFC16A7CA1500737497 /* MCPOPOperationCallback.h */; }; - C62C6F0616A7E54500737497 /* MCPOPFetchMessagesOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C62C6F0416A7E54200737497 /* MCPOPFetchMessagesOperation.cc */; }; + C62C6F0616A7E54500737497 /* MCPOPFetchMessagesOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C62C6F0416A7E54200737497 /* MCPOPFetchMessagesOperation.cpp */; }; C62C6F0716A7E7CC00737497 /* MCPOPFetchMessagesOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C62C6F0516A7E54400737497 /* MCPOPFetchMessagesOperation.h */; }; - C62C6F0A16A8F58000737497 /* MCIMAPAsyncSession.cc in Sources */ = {isa = PBXBuildFile; fileRef = C62C6F0816A8F57000737497 /* MCIMAPAsyncSession.cc */; }; + C62C6F0A16A8F58000737497 /* MCIMAPAsyncSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C62C6F0816A8F57000737497 /* MCIMAPAsyncSession.cpp */; }; C62C6F0B16A936CA00737497 /* MCIMAPAsyncSession.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C62C6F0916A8F57700737497 /* MCIMAPAsyncSession.h */; }; - C63CD67F16BDCDD400DB18F1 /* MCAddressDisplay.cc in Sources */ = {isa = PBXBuildFile; fileRef = C63CD67716BDCDD400DB18F1 /* MCAddressDisplay.cc */; }; - C63CD68016BDCDD400DB18F1 /* MCDateFormatter.cc in Sources */ = {isa = PBXBuildFile; fileRef = C63CD67916BDCDD400DB18F1 /* MCDateFormatter.cc */; }; - C63CD68116BDCDD400DB18F1 /* MCHTMLRenderer.cc in Sources */ = {isa = PBXBuildFile; fileRef = C63CD67B16BDCDD400DB18F1 /* MCHTMLRenderer.cc */; }; - C63CD68216BDCDD400DB18F1 /* MCSizeFormatter.cc in Sources */ = {isa = PBXBuildFile; fileRef = C63CD67D16BDCDD400DB18F1 /* MCSizeFormatter.cc */; }; - C63CD68616BE148B00DB18F1 /* MCHTMLRendererCallback.cc in Sources */ = {isa = PBXBuildFile; fileRef = C63CD68416BE148B00DB18F1 /* MCHTMLRendererCallback.cc */; }; + C63CD67F16BDCDD400DB18F1 /* MCAddressDisplay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C63CD67716BDCDD400DB18F1 /* MCAddressDisplay.cpp */; }; + C63CD68016BDCDD400DB18F1 /* MCDateFormatter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C63CD67916BDCDD400DB18F1 /* MCDateFormatter.cpp */; }; + C63CD68116BDCDD400DB18F1 /* MCHTMLRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C63CD67B16BDCDD400DB18F1 /* MCHTMLRenderer.cpp */; }; + C63CD68216BDCDD400DB18F1 /* MCSizeFormatter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C63CD67D16BDCDD400DB18F1 /* MCSizeFormatter.cpp */; }; + C63CD68616BE148B00DB18F1 /* MCHTMLRendererCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C63CD68416BE148B00DB18F1 /* MCHTMLRendererCallback.cpp */; }; C63CD68816BE1BBF00DB18F1 /* MCAddressDisplay.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C63CD67816BDCDD400DB18F1 /* MCAddressDisplay.h */; }; C63CD68916BE1BC100DB18F1 /* MCDateFormatter.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C63CD67A16BDCDD400DB18F1 /* MCDateFormatter.h */; }; C63CD68A16BE1BC400DB18F1 /* MCSizeFormatter.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C63CD67E16BDCDD400DB18F1 /* MCSizeFormatter.h */; }; C63CD68C16BE1BC800DB18F1 /* MCHTMLRendererCallback.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C63CD68516BE148B00DB18F1 /* MCHTMLRendererCallback.h */; }; C63CD68D16BE1BCA00DB18F1 /* MCRenderer.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C63CD68716BE1AB600DB18F1 /* MCRenderer.h */; }; C63CD68E16BE324100DB18F1 /* MCOIMAPFetchFoldersOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = F87F190816BB62690012652F /* MCOIMAPFetchFoldersOperation.h */; }; - C63CD69116BE566E00DB18F1 /* MCHTMLCleaner.cc in Sources */ = {isa = PBXBuildFile; fileRef = C63CD68F16BE566D00DB18F1 /* MCHTMLCleaner.cc */; }; - C63D315C17C9155C00A4D993 /* MCIMAPIdentity.cc in Sources */ = {isa = PBXBuildFile; fileRef = C63D315A17C9155C00A4D993 /* MCIMAPIdentity.cc */; }; - C63D315D17C9155C00A4D993 /* MCIMAPIdentity.cc in Sources */ = {isa = PBXBuildFile; fileRef = C63D315A17C9155C00A4D993 /* MCIMAPIdentity.cc */; }; + C63CD69116BE566E00DB18F1 /* MCHTMLCleaner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C63CD68F16BE566D00DB18F1 /* MCHTMLCleaner.cpp */; }; + C63D315C17C9155C00A4D993 /* MCIMAPIdentity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C63D315A17C9155C00A4D993 /* MCIMAPIdentity.cpp */; }; + C63D315D17C9155C00A4D993 /* MCIMAPIdentity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C63D315A17C9155C00A4D993 /* MCIMAPIdentity.cpp */; }; C63D315E17C9279700A4D993 /* MCIMAPIdentity.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C63D315B17C9155C00A4D993 /* MCIMAPIdentity.h */; }; C63D315F17C9279D00A4D993 /* MCIMAPIdentity.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C63D315B17C9155C00A4D993 /* MCIMAPIdentity.h */; }; C63D316217C92D8300A4D993 /* MCOIMAPIdentity.mm in Sources */ = {isa = PBXBuildFile; fileRef = C63D316117C92D8300A4D993 /* MCOIMAPIdentity.mm */; }; @@ -237,9 +237,9 @@ C63D316717C997BA00A4D993 /* MCOIMAPIdentity.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C63D316017C92D8300A4D993 /* MCOIMAPIdentity.h */; }; C643F492189A3D59007EA2F7 /* NSSet+MCO.mm in Sources */ = {isa = PBXBuildFile; fileRef = C643F491189A3D59007EA2F7 /* NSSet+MCO.mm */; }; C643F493189A3D59007EA2F7 /* NSSet+MCO.mm in Sources */ = {isa = PBXBuildFile; fileRef = C643F491189A3D59007EA2F7 /* NSSet+MCO.mm */; }; - C64BB22116E34DCB000DB34C /* MCIMAPSyncResult.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64BB21F16E34DCA000DB34C /* MCIMAPSyncResult.cc */; }; - C64BB22B16E5C0A4000DB34C /* MCIMAPCapabilityOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64BB22916E5C0A3000DB34C /* MCIMAPCapabilityOperation.cc */; }; - C64BB22E16E5C1EE000DB34C /* MCIndexSet.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64BB22C16E5C1EE000DB34C /* MCIndexSet.cc */; }; + C64BB22116E34DCB000DB34C /* MCIMAPSyncResult.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64BB21F16E34DCA000DB34C /* MCIMAPSyncResult.cpp */; }; + C64BB22B16E5C0A4000DB34C /* MCIMAPCapabilityOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64BB22916E5C0A3000DB34C /* MCIMAPCapabilityOperation.cpp */; }; + C64BB22E16E5C1EE000DB34C /* MCIndexSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64BB22C16E5C1EE000DB34C /* MCIndexSet.cpp */; }; C64BB22F16E885C3000DB34C /* MCIndexSet.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64BB22D16E5C1EE000DB34C /* MCIndexSet.h */; }; C64BB23016E8876F000DB34C /* MCIMAPCapabilityOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64BB22A16E5C0A3000DB34C /* MCIMAPCapabilityOperation.h */; }; C64BB23516EDAA17000DB34C /* MCOAbstractMessage.mm in Sources */ = {isa = PBXBuildFile; fileRef = C64BB23416EDAA17000DB34C /* MCOAbstractMessage.mm */; }; @@ -263,43 +263,43 @@ C64BB26416FD43A1000DB34C /* MCOMessageParser.mm in Sources */ = {isa = PBXBuildFile; fileRef = C64BB26316FD43A1000DB34C /* MCOMessageParser.mm */; }; C64BB26716FD43E2000DB34C /* MCOMessagePart.mm in Sources */ = {isa = PBXBuildFile; fileRef = C64BB26616FD43E2000DB34C /* MCOMessagePart.mm */; }; C64BB26A16FD44C2000DB34C /* MCOMultipart.mm in Sources */ = {isa = PBXBuildFile; fileRef = C64BB26916FD44C2000DB34C /* MCOMultipart.mm */; }; - C64EA6F4169E847800778456 /* MCAbstractMessage.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA694169E847800778456 /* MCAbstractMessage.cc */; }; - C64EA6F6169E847800778456 /* MCAbstractMessagePart.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA696169E847800778456 /* MCAbstractMessagePart.cc */; }; - C64EA6F8169E847800778456 /* MCAbstractMultipart.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA698169E847800778456 /* MCAbstractMultipart.cc */; }; - C64EA6FA169E847800778456 /* MCAbstractPart.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA69A169E847800778456 /* MCAbstractPart.cc */; }; - C64EA6FC169E847800778456 /* MCAddress.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA69C169E847800778456 /* MCAddress.cc */; }; - C64EA6FF169E847800778456 /* MCMessageHeader.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA69F169E847800778456 /* MCMessageHeader.cc */; }; - C64EA701169E847800778456 /* MCAutoreleasePool.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6A2169E847800778456 /* MCAutoreleasePool.cc */; }; - C64EA704169E847800778456 /* MCArray.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6A5169E847800778456 /* MCArray.cc */; }; + C64EA6F4169E847800778456 /* MCAbstractMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA694169E847800778456 /* MCAbstractMessage.cpp */; }; + C64EA6F6169E847800778456 /* MCAbstractMessagePart.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA696169E847800778456 /* MCAbstractMessagePart.cpp */; }; + C64EA6F8169E847800778456 /* MCAbstractMultipart.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA698169E847800778456 /* MCAbstractMultipart.cpp */; }; + C64EA6FA169E847800778456 /* MCAbstractPart.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA69A169E847800778456 /* MCAbstractPart.cpp */; }; + C64EA6FC169E847800778456 /* MCAddress.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA69C169E847800778456 /* MCAddress.cpp */; }; + C64EA6FF169E847800778456 /* MCMessageHeader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA69F169E847800778456 /* MCMessageHeader.cpp */; }; + C64EA701169E847800778456 /* MCAutoreleasePool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6A2169E847800778456 /* MCAutoreleasePool.cpp */; }; + C64EA704169E847800778456 /* MCArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6A5169E847800778456 /* MCArray.cpp */; }; C64EA706169E847800778456 /* MCAssert.c in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6A7169E847800778456 /* MCAssert.c */; }; - C64EA708169E847800778456 /* MCData.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6A9169E847800778456 /* MCData.cc */; }; - C64EA70A169E847800778456 /* MCHash.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6AB169E847800778456 /* MCHash.cc */; }; - C64EA70C169E847800778456 /* MCHashMap.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6AD169E847800778456 /* MCHashMap.cc */; }; + C64EA708169E847800778456 /* MCData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6A9169E847800778456 /* MCData.cpp */; }; + C64EA70A169E847800778456 /* MCHash.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6AB169E847800778456 /* MCHash.cpp */; }; + C64EA70C169E847800778456 /* MCHashMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6AD169E847800778456 /* MCHashMap.cpp */; }; C64EA70E169E847800778456 /* MCLog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6AF169E847800778456 /* MCLog.cpp */; }; - C64EA710169E847800778456 /* MCObject.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6B1169E847800778456 /* MCObject.cc */; }; - C64EA712169E847800778456 /* MCRange.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6B3169E847800778456 /* MCRange.cc */; }; - C64EA714169E847800778456 /* MCSet.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6B5169E847800778456 /* MCSet.cc */; }; - C64EA716169E847800778456 /* MCString.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6B7169E847800778456 /* MCString.cc */; }; - C64EA719169E847800778456 /* MCValue.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6BA169E847800778456 /* MCValue.cc */; }; + C64EA710169E847800778456 /* MCObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6B1169E847800778456 /* MCObject.cpp */; }; + C64EA712169E847800778456 /* MCRange.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6B3169E847800778456 /* MCRange.cpp */; }; + C64EA714169E847800778456 /* MCSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6B5169E847800778456 /* MCSet.cpp */; }; + C64EA716169E847800778456 /* MCString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6B7169E847800778456 /* MCString.cpp */; }; + C64EA719169E847800778456 /* MCValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6BA169E847800778456 /* MCValue.cpp */; }; C64EA71C169E847800778456 /* MCMainThreadMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6BD169E847800778456 /* MCMainThreadMac.mm */; }; - C64EA71D169E847800778456 /* MCOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6BE169E847800778456 /* MCOperation.cc */; }; - C64EA720169E847800778456 /* MCOperationQueue.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6C1169E847800778456 /* MCOperationQueue.cc */; }; - C64EA723169E847800778456 /* MCIMAPFolder.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6C5169E847800778456 /* MCIMAPFolder.cc */; }; - C64EA725169E847800778456 /* MCIMAPMessage.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6C7169E847800778456 /* MCIMAPMessage.cc */; }; - C64EA727169E847800778456 /* MCIMAPMessagePart.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6C9169E847800778456 /* MCIMAPMessagePart.cc */; }; - C64EA729169E847800778456 /* MCIMAPMultipart.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6CB169E847800778456 /* MCIMAPMultipart.cc */; }; - C64EA72B169E847800778456 /* MCIMAPNamespace.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6CD169E847800778456 /* MCIMAPNamespace.cc */; }; - C64EA72D169E847800778456 /* MCIMAPNamespaceItem.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6CF169E847800778456 /* MCIMAPNamespaceItem.cc */; }; - C64EA72F169E847800778456 /* MCIMAPPart.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6D1169E847800778456 /* MCIMAPPart.cc */; }; - C64EA732169E847800778456 /* MCIMAPSearchExpression.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6D4169E847800778456 /* MCIMAPSearchExpression.cc */; }; - C64EA734169E847800778456 /* MCIMAPSession.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6D6169E847800778456 /* MCIMAPSession.cc */; }; - C64EA737169E847800778456 /* MCPOPMessageInfo.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6DA169E847800778456 /* MCPOPMessageInfo.cc */; }; - C64EA73A169E847800778456 /* MCPOPSession.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6DD169E847800778456 /* MCPOPSession.cc */; }; - C64EA73C169E847800778456 /* MCAttachment.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6E0169E847800778456 /* MCAttachment.cc */; }; - C64EA73E169E847800778456 /* MCMessageBuilder.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6E2169E847800778456 /* MCMessageBuilder.cc */; }; - C64EA740169E847800778456 /* MCMessageParser.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6E4169E847800778456 /* MCMessageParser.cc */; }; - C64EA742169E847800778456 /* MCMessagePart.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6E6169E847800778456 /* MCMessagePart.cc */; }; - C64EA744169E847800778456 /* MCMultipart.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6E8169E847800778456 /* MCMultipart.cc */; }; + C64EA71D169E847800778456 /* MCOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6BE169E847800778456 /* MCOperation.cpp */; }; + C64EA720169E847800778456 /* MCOperationQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6C1169E847800778456 /* MCOperationQueue.cpp */; }; + C64EA723169E847800778456 /* MCIMAPFolder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6C5169E847800778456 /* MCIMAPFolder.cpp */; }; + C64EA725169E847800778456 /* MCIMAPMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6C7169E847800778456 /* MCIMAPMessage.cpp */; }; + C64EA727169E847800778456 /* MCIMAPMessagePart.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6C9169E847800778456 /* MCIMAPMessagePart.cpp */; }; + C64EA729169E847800778456 /* MCIMAPMultipart.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6CB169E847800778456 /* MCIMAPMultipart.cpp */; }; + C64EA72B169E847800778456 /* MCIMAPNamespace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6CD169E847800778456 /* MCIMAPNamespace.cpp */; }; + C64EA72D169E847800778456 /* MCIMAPNamespaceItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6CF169E847800778456 /* MCIMAPNamespaceItem.cpp */; }; + C64EA72F169E847800778456 /* MCIMAPPart.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6D1169E847800778456 /* MCIMAPPart.cpp */; }; + C64EA732169E847800778456 /* MCIMAPSearchExpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6D4169E847800778456 /* MCIMAPSearchExpression.cpp */; }; + C64EA734169E847800778456 /* MCIMAPSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6D6169E847800778456 /* MCIMAPSession.cpp */; }; + C64EA737169E847800778456 /* MCPOPMessageInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6DA169E847800778456 /* MCPOPMessageInfo.cpp */; }; + C64EA73A169E847800778456 /* MCPOPSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6DD169E847800778456 /* MCPOPSession.cpp */; }; + C64EA73C169E847800778456 /* MCAttachment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6E0169E847800778456 /* MCAttachment.cpp */; }; + C64EA73E169E847800778456 /* MCMessageBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6E2169E847800778456 /* MCMessageBuilder.cpp */; }; + C64EA740169E847800778456 /* MCMessageParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6E4169E847800778456 /* MCMessageParser.cpp */; }; + C64EA742169E847800778456 /* MCMessagePart.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6E6169E847800778456 /* MCMessagePart.cpp */; }; + C64EA744169E847800778456 /* MCMultipart.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6E8169E847800778456 /* MCMultipart.cpp */; }; C64EA74D169E859600778456 /* MCSMTPAsyncSession.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64EA690169E847800778456 /* MCSMTPAsyncSession.h */; }; C64EA74E169E859600778456 /* MCAbstract.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64EA693169E847800778456 /* MCAbstract.h */; }; C64EA74F169E859600778456 /* MCAbstractMessage.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64EA695169E847800778456 /* MCAbstractMessage.h */; }; @@ -351,37 +351,37 @@ C64EA77D169E859600778456 /* MCSMTP.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64EA6EC169E847800778456 /* MCSMTP.h */; }; C64EA77E169E859600778456 /* MCSMTPProgressCallback.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64EA6ED169E847800778456 /* MCSMTPProgressCallback.h */; }; C64EA77F169E859600778456 /* MCSMTPSession.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64EA6EF169E847800778456 /* MCSMTPSession.h */; }; - C64EA781169E89F600778456 /* MCSMTPSession.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6EE169E847800778456 /* MCSMTPSession.cc */; }; + C64EA781169E89F600778456 /* MCSMTPSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6EE169E847800778456 /* MCSMTPSession.cpp */; }; C64EA783169F241300778456 /* MCCore.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64EA782169F23AB00778456 /* MCCore.h */; }; - C64EA784169F24E400778456 /* MCSMTPAsyncSession.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA68F169E847800778456 /* MCSMTPAsyncSession.cc */; }; + C64EA784169F24E400778456 /* MCSMTPAsyncSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA68F169E847800778456 /* MCSMTPAsyncSession.cpp */; }; C64EA790169F259200778456 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C64EA78F169F259200778456 /* Foundation.framework */; }; - C64EA79E169F29A700778456 /* MCSMTPSendWithDataOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA79C169F29A700778456 /* MCSMTPSendWithDataOperation.cc */; }; + C64EA79E169F29A700778456 /* MCSMTPSendWithDataOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA79C169F29A700778456 /* MCSMTPSendWithDataOperation.cpp */; }; C64EA7A5169F2A6100778456 /* MailCore.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64EA7A4169F2A3E00778456 /* MailCore.h */; }; C64EA7AB16A00AF600778456 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA7AA16A00AF600778456 /* main.cpp */; }; C64EA7B116A00BBB00778456 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C64EA7B016A00BBB00778456 /* CoreServices.framework */; }; - C64EA7DA16A1386600778456 /* MCSMTPOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA7D816A1386500778456 /* MCSMTPOperation.cc */; }; + C64EA7DA16A1386600778456 /* MCSMTPOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA7D816A1386500778456 /* MCSMTPOperation.cpp */; }; C64EA7DC16A13A4C00778456 /* MCSMTPOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64EA7D916A1386600778456 /* MCSMTPOperation.h */; }; C64EA7E516A14A5400778456 /* MCAsync.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64EA7E416A14A4500778456 /* MCAsync.h */; }; C64EA7E616A14A6A00778456 /* MCAsyncSMTP.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64EA7E316A149EF00778456 /* MCAsyncSMTP.h */; }; C64EA7E716A14A7400778456 /* MCSMTPOperationCallback.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64EA7E116A1425400778456 /* MCSMTPOperationCallback.h */; }; - C64EA7EA16A154B300778456 /* MCSMTPCheckAccountOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA7E816A154B000778456 /* MCSMTPCheckAccountOperation.cc */; }; - C64EA7F116A15A4D00778456 /* MCIMAPOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA7EF16A15A4D00778456 /* MCIMAPOperation.cc */; }; - C64EA7F816A15A7800778456 /* MCIMAPCheckAccountOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA7F616A15A7800778456 /* MCIMAPCheckAccountOperation.cc */; }; - C64EA7FC16A2959800778456 /* MCIMAPFetchFoldersOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA7FA16A2959700778456 /* MCIMAPFetchFoldersOperation.cc */; }; - C64EA80216A295E400778456 /* MCIMAPRenameFolderOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA80016A295E200778456 /* MCIMAPRenameFolderOperation.cc */; }; - C64EA80516A2997E00778456 /* MCIMAPDeleteFolderOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA80316A2997B00778456 /* MCIMAPDeleteFolderOperation.cc */; }; - C64EA80816A2999A00778456 /* MCIMAPCreateFolderOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA80616A2999800778456 /* MCIMAPCreateFolderOperation.cc */; }; - C64EA80B16A299B700778456 /* MCIMAPSubscribeFolderOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA80916A299B500778456 /* MCIMAPSubscribeFolderOperation.cc */; }; - C64EA81116A299ED00778456 /* MCIMAPAppendMessageOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA80F16A299EA00778456 /* MCIMAPAppendMessageOperation.cc */; }; - C64EA81416A29A2300778456 /* MCIMAPCopyMessagesOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA81216A29A0A00778456 /* MCIMAPCopyMessagesOperation.cc */; }; - C64EA81716A29A8700778456 /* MCIMAPExpungeOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA81516A29A8500778456 /* MCIMAPExpungeOperation.cc */; }; - C64EA81A16A29AF200778456 /* MCIMAPFetchMessagesOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA81816A29AD400778456 /* MCIMAPFetchMessagesOperation.cc */; }; - C64EA81D16A29DC500778456 /* MCIMAPFetchContentOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA81B16A29DC100778456 /* MCIMAPFetchContentOperation.cc */; }; - C64EA82016A29E4100778456 /* MCIMAPStoreFlagsOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA81E16A29E3D00778456 /* MCIMAPStoreFlagsOperation.cc */; }; - C64EA82316A29E5300778456 /* MCIMAPStoreLabelsOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA82116A29E4F00778456 /* MCIMAPStoreLabelsOperation.cc */; }; - C64EA82616A29EE500778456 /* MCIMAPSearchOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA82416A29EE000778456 /* MCIMAPSearchOperation.cc */; }; - C64EA82916A29F2200778456 /* MCIMAPIdleOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA82716A29EF400778456 /* MCIMAPIdleOperation.cc */; }; - C64EA82C16A2A08B00778456 /* MCIMAPFetchNamespaceOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA82A16A29FAA00778456 /* MCIMAPFetchNamespaceOperation.cc */; }; + C64EA7EA16A154B300778456 /* MCSMTPCheckAccountOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA7E816A154B000778456 /* MCSMTPCheckAccountOperation.cpp */; }; + C64EA7F116A15A4D00778456 /* MCIMAPOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA7EF16A15A4D00778456 /* MCIMAPOperation.cpp */; }; + C64EA7F816A15A7800778456 /* MCIMAPCheckAccountOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA7F616A15A7800778456 /* MCIMAPCheckAccountOperation.cpp */; }; + C64EA7FC16A2959800778456 /* MCIMAPFetchFoldersOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA7FA16A2959700778456 /* MCIMAPFetchFoldersOperation.cpp */; }; + C64EA80216A295E400778456 /* MCIMAPRenameFolderOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA80016A295E200778456 /* MCIMAPRenameFolderOperation.cpp */; }; + C64EA80516A2997E00778456 /* MCIMAPDeleteFolderOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA80316A2997B00778456 /* MCIMAPDeleteFolderOperation.cpp */; }; + C64EA80816A2999A00778456 /* MCIMAPCreateFolderOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA80616A2999800778456 /* MCIMAPCreateFolderOperation.cpp */; }; + C64EA80B16A299B700778456 /* MCIMAPSubscribeFolderOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA80916A299B500778456 /* MCIMAPSubscribeFolderOperation.cpp */; }; + C64EA81116A299ED00778456 /* MCIMAPAppendMessageOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA80F16A299EA00778456 /* MCIMAPAppendMessageOperation.cpp */; }; + C64EA81416A29A2300778456 /* MCIMAPCopyMessagesOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA81216A29A0A00778456 /* MCIMAPCopyMessagesOperation.cpp */; }; + C64EA81716A29A8700778456 /* MCIMAPExpungeOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA81516A29A8500778456 /* MCIMAPExpungeOperation.cpp */; }; + C64EA81A16A29AF200778456 /* MCIMAPFetchMessagesOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA81816A29AD400778456 /* MCIMAPFetchMessagesOperation.cpp */; }; + C64EA81D16A29DC500778456 /* MCIMAPFetchContentOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA81B16A29DC100778456 /* MCIMAPFetchContentOperation.cpp */; }; + C64EA82016A29E4100778456 /* MCIMAPStoreFlagsOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA81E16A29E3D00778456 /* MCIMAPStoreFlagsOperation.cpp */; }; + C64EA82316A29E5300778456 /* MCIMAPStoreLabelsOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA82116A29E4F00778456 /* MCIMAPStoreLabelsOperation.cpp */; }; + C64EA82616A29EE500778456 /* MCIMAPSearchOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA82416A29EE000778456 /* MCIMAPSearchOperation.cpp */; }; + C64EA82916A29F2200778456 /* MCIMAPIdleOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA82716A29EF400778456 /* MCIMAPIdleOperation.cpp */; }; + C64EA82C16A2A08B00778456 /* MCIMAPFetchNamespaceOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA82A16A29FAA00778456 /* MCIMAPFetchNamespaceOperation.cpp */; }; C64FF39116B3C13000F8C162 /* MCOObjectWrapper.mm in Sources */ = {isa = PBXBuildFile; fileRef = C64FF39016B3C13000F8C162 /* MCOObjectWrapper.mm */; }; C64FF39316B3C25200F8C162 /* MCOObjectWrapper.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64FF38F16B3C13000F8C162 /* MCOObjectWrapper.h */; }; C668E2C71735C8D500A2BB47 /* MCObjectMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = C668E2C51735C8D500A2BB47 /* MCObjectMac.mm */; }; @@ -393,8 +393,8 @@ C67597C317A8D65000DA69DF /* MCBase64.c in Sources */ = {isa = PBXBuildFile; fileRef = C67597C117A8D65000DA69DF /* MCBase64.c */; }; C68B2AEE1778A865005E61EF /* MCConnectionLogger.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C68B2AEB1778A589005E61EF /* MCConnectionLogger.h */; }; C68B2AEF1778A869005E61EF /* MCConnectionLogger.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C68B2AEB1778A589005E61EF /* MCConnectionLogger.h */; }; - C68B2AF717797389005E61EF /* MCConnectionLoggerUtils.cc in Sources */ = {isa = PBXBuildFile; fileRef = C68B2AF517797389005E61EF /* MCConnectionLoggerUtils.cc */; }; - C68B2AF817797389005E61EF /* MCConnectionLoggerUtils.cc in Sources */ = {isa = PBXBuildFile; fileRef = C68B2AF517797389005E61EF /* MCConnectionLoggerUtils.cc */; }; + C68B2AF717797389005E61EF /* MCConnectionLoggerUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C68B2AF517797389005E61EF /* MCConnectionLoggerUtils.cpp */; }; + C68B2AF817797389005E61EF /* MCConnectionLoggerUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C68B2AF517797389005E61EF /* MCConnectionLoggerUtils.cpp */; }; C69BA85B17DEFCCB00D601B7 /* NSIndexSet+MCO.m in Sources */ = {isa = PBXBuildFile; fileRef = C69BA85A17DEFCCB00D601B7 /* NSIndexSet+MCO.m */; }; C69BA85C17DEFCCB00D601B7 /* NSIndexSet+MCO.m in Sources */ = {isa = PBXBuildFile; fileRef = C69BA85A17DEFCCB00D601B7 /* NSIndexSet+MCO.m */; }; C69BA85D17DEFD9A00D601B7 /* NSIndexSet+MCO.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C69BA85917DEFCCB00D601B7 /* NSIndexSet+MCO.h */; }; @@ -450,8 +450,8 @@ C6A81C031707D96500882C15 /* MCOPOPMessageInfo.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6A81BFE1707CEE400882C15 /* MCOPOPMessageInfo.h */; }; C6A81C04170A82F300882C15 /* MCIMAPSyncResult.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64BB22016E34DCB000DB34C /* MCIMAPSyncResult.h */; }; C6A81C05170A82F600882C15 /* MCIMAPSyncResult.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64BB22016E34DCB000DB34C /* MCIMAPSyncResult.h */; }; - C6AC110017114DAF00B715B7 /* MCPOPCheckAccountOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C6AC10FE17114DAF00B715B7 /* MCPOPCheckAccountOperation.cc */; }; - C6AC110117114DAF00B715B7 /* MCPOPCheckAccountOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C6AC10FE17114DAF00B715B7 /* MCPOPCheckAccountOperation.cc */; }; + C6AC110017114DAF00B715B7 /* MCPOPCheckAccountOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6AC10FE17114DAF00B715B7 /* MCPOPCheckAccountOperation.cpp */; }; + C6AC110117114DAF00B715B7 /* MCPOPCheckAccountOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6AC10FE17114DAF00B715B7 /* MCPOPCheckAccountOperation.cpp */; }; C6AC113417124D0600B715B7 /* MCLibetpanTypes.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6AC1131171249DF00B715B7 /* MCLibetpanTypes.h */; }; C6AC113517124D0A00B715B7 /* MCLibetpanTypes.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6AC1131171249DF00B715B7 /* MCLibetpanTypes.h */; }; C6B5AE0719F630B3001352A6 /* unittest.mm in Sources */ = {isa = PBXBuildFile; fileRef = C6B5AE0619F630B3001352A6 /* unittest.mm */; }; @@ -595,75 +595,75 @@ C6BA2B951705F4E6003F0E9E /* MCSMTPSession.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64EA6EF169E847800778456 /* MCSMTPSession.h */; }; C6BA2B961705F4E6003F0E9E /* MCOIMAPSession.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = F8EA941416BAED6E0011AC6F /* MCOIMAPSession.h */; }; C6BA2B971705F4E6003F0E9E /* NSError+MCO.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C07AD44B013BB42A240B4F04 /* NSError+MCO.h */; }; - C6BA2B991705F4E6003F0E9E /* MCAbstractMessage.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA694169E847800778456 /* MCAbstractMessage.cc */; }; - C6BA2B9A1705F4E6003F0E9E /* MCAbstractMessagePart.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA696169E847800778456 /* MCAbstractMessagePart.cc */; }; - C6BA2B9B1705F4E6003F0E9E /* MCAbstractMultipart.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA698169E847800778456 /* MCAbstractMultipart.cc */; }; - C6BA2B9C1705F4E6003F0E9E /* MCAbstractPart.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA69A169E847800778456 /* MCAbstractPart.cc */; }; - C6BA2B9D1705F4E6003F0E9E /* MCAddress.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA69C169E847800778456 /* MCAddress.cc */; }; - C6BA2B9E1705F4E6003F0E9E /* MCMessageHeader.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA69F169E847800778456 /* MCMessageHeader.cc */; }; - C6BA2B9F1705F4E6003F0E9E /* MCAutoreleasePool.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6A2169E847800778456 /* MCAutoreleasePool.cc */; }; - C6BA2BA01705F4E6003F0E9E /* MCArray.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6A5169E847800778456 /* MCArray.cc */; }; + C6BA2B991705F4E6003F0E9E /* MCAbstractMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA694169E847800778456 /* MCAbstractMessage.cpp */; }; + C6BA2B9A1705F4E6003F0E9E /* MCAbstractMessagePart.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA696169E847800778456 /* MCAbstractMessagePart.cpp */; }; + C6BA2B9B1705F4E6003F0E9E /* MCAbstractMultipart.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA698169E847800778456 /* MCAbstractMultipart.cpp */; }; + C6BA2B9C1705F4E6003F0E9E /* MCAbstractPart.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA69A169E847800778456 /* MCAbstractPart.cpp */; }; + C6BA2B9D1705F4E6003F0E9E /* MCAddress.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA69C169E847800778456 /* MCAddress.cpp */; }; + C6BA2B9E1705F4E6003F0E9E /* MCMessageHeader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA69F169E847800778456 /* MCMessageHeader.cpp */; }; + C6BA2B9F1705F4E6003F0E9E /* MCAutoreleasePool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6A2169E847800778456 /* MCAutoreleasePool.cpp */; }; + C6BA2BA01705F4E6003F0E9E /* MCArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6A5169E847800778456 /* MCArray.cpp */; }; C6BA2BA11705F4E6003F0E9E /* MCAssert.c in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6A7169E847800778456 /* MCAssert.c */; }; - C6BA2BA21705F4E6003F0E9E /* MCData.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6A9169E847800778456 /* MCData.cc */; }; - C6BA2BA31705F4E6003F0E9E /* MCHash.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6AB169E847800778456 /* MCHash.cc */; }; - C6BA2BA41705F4E6003F0E9E /* MCHashMap.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6AD169E847800778456 /* MCHashMap.cc */; }; + C6BA2BA21705F4E6003F0E9E /* MCData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6A9169E847800778456 /* MCData.cpp */; }; + C6BA2BA31705F4E6003F0E9E /* MCHash.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6AB169E847800778456 /* MCHash.cpp */; }; + C6BA2BA41705F4E6003F0E9E /* MCHashMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6AD169E847800778456 /* MCHashMap.cpp */; }; C6BA2BA51705F4E6003F0E9E /* MCLog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6AF169E847800778456 /* MCLog.cpp */; }; - C6BA2BA61705F4E6003F0E9E /* MCObject.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6B1169E847800778456 /* MCObject.cc */; }; - C6BA2BA71705F4E6003F0E9E /* MCRange.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6B3169E847800778456 /* MCRange.cc */; }; - C6BA2BA81705F4E6003F0E9E /* MCSet.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6B5169E847800778456 /* MCSet.cc */; }; - C6BA2BA91705F4E6003F0E9E /* MCString.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6B7169E847800778456 /* MCString.cc */; }; - C6BA2BAA1705F4E6003F0E9E /* MCValue.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6BA169E847800778456 /* MCValue.cc */; }; + C6BA2BA61705F4E6003F0E9E /* MCObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6B1169E847800778456 /* MCObject.cpp */; }; + C6BA2BA71705F4E6003F0E9E /* MCRange.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6B3169E847800778456 /* MCRange.cpp */; }; + C6BA2BA81705F4E6003F0E9E /* MCSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6B5169E847800778456 /* MCSet.cpp */; }; + C6BA2BA91705F4E6003F0E9E /* MCString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6B7169E847800778456 /* MCString.cpp */; }; + C6BA2BAA1705F4E6003F0E9E /* MCValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6BA169E847800778456 /* MCValue.cpp */; }; C6BA2BAB1705F4E6003F0E9E /* MCMainThreadMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6BD169E847800778456 /* MCMainThreadMac.mm */; }; - C6BA2BAC1705F4E6003F0E9E /* MCOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6BE169E847800778456 /* MCOperation.cc */; }; - C6BA2BAD1705F4E6003F0E9E /* MCOperationQueue.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6C1169E847800778456 /* MCOperationQueue.cc */; }; - C6BA2BAE1705F4E6003F0E9E /* MCIMAPFolder.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6C5169E847800778456 /* MCIMAPFolder.cc */; }; - C6BA2BAF1705F4E6003F0E9E /* MCIMAPMessage.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6C7169E847800778456 /* MCIMAPMessage.cc */; }; - C6BA2BB01705F4E6003F0E9E /* MCIMAPMessagePart.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6C9169E847800778456 /* MCIMAPMessagePart.cc */; }; - C6BA2BB11705F4E6003F0E9E /* MCIMAPMultipart.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6CB169E847800778456 /* MCIMAPMultipart.cc */; }; - C6BA2BB21705F4E6003F0E9E /* MCIMAPNamespace.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6CD169E847800778456 /* MCIMAPNamespace.cc */; }; - C6BA2BB31705F4E6003F0E9E /* MCIMAPNamespaceItem.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6CF169E847800778456 /* MCIMAPNamespaceItem.cc */; }; - C6BA2BB41705F4E6003F0E9E /* MCIMAPPart.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6D1169E847800778456 /* MCIMAPPart.cc */; }; - C6BA2BB51705F4E6003F0E9E /* MCIMAPSearchExpression.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6D4169E847800778456 /* MCIMAPSearchExpression.cc */; }; - C6BA2BB61705F4E6003F0E9E /* MCIMAPSession.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6D6169E847800778456 /* MCIMAPSession.cc */; }; - C6BA2BB71705F4E6003F0E9E /* MCPOPMessageInfo.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6DA169E847800778456 /* MCPOPMessageInfo.cc */; }; - C6BA2BB81705F4E6003F0E9E /* MCPOPSession.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6DD169E847800778456 /* MCPOPSession.cc */; }; - C6BA2BB91705F4E6003F0E9E /* MCAttachment.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6E0169E847800778456 /* MCAttachment.cc */; }; - C6BA2BBA1705F4E6003F0E9E /* MCMessageBuilder.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6E2169E847800778456 /* MCMessageBuilder.cc */; }; - C6BA2BBB1705F4E6003F0E9E /* MCMessageParser.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6E4169E847800778456 /* MCMessageParser.cc */; }; - C6BA2BBC1705F4E6003F0E9E /* MCMessagePart.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6E6169E847800778456 /* MCMessagePart.cc */; }; - C6BA2BBD1705F4E6003F0E9E /* MCMultipart.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6E8169E847800778456 /* MCMultipart.cc */; }; - C6BA2BBE1705F4E6003F0E9E /* MCSMTPSession.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6EE169E847800778456 /* MCSMTPSession.cc */; }; - C6BA2BBF1705F4E6003F0E9E /* MCSMTPAsyncSession.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA68F169E847800778456 /* MCSMTPAsyncSession.cc */; }; - C6BA2BC01705F4E6003F0E9E /* MCSMTPSendWithDataOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA79C169F29A700778456 /* MCSMTPSendWithDataOperation.cc */; }; - C6BA2BC11705F4E6003F0E9E /* MCSMTPOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA7D816A1386500778456 /* MCSMTPOperation.cc */; }; - C6BA2BC21705F4E6003F0E9E /* MCSMTPCheckAccountOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA7E816A154B000778456 /* MCSMTPCheckAccountOperation.cc */; }; - C6BA2BC31705F4E6003F0E9E /* MCIMAPOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA7EF16A15A4D00778456 /* MCIMAPOperation.cc */; }; - C6BA2BC41705F4E6003F0E9E /* MCIMAPCheckAccountOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA7F616A15A7800778456 /* MCIMAPCheckAccountOperation.cc */; }; - C6BA2BC51705F4E6003F0E9E /* MCIMAPFetchFoldersOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA7FA16A2959700778456 /* MCIMAPFetchFoldersOperation.cc */; }; - C6BA2BC61705F4E6003F0E9E /* MCIMAPRenameFolderOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA80016A295E200778456 /* MCIMAPRenameFolderOperation.cc */; }; - C6BA2BC71705F4E6003F0E9E /* MCIMAPDeleteFolderOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA80316A2997B00778456 /* MCIMAPDeleteFolderOperation.cc */; }; - C6BA2BC81705F4E6003F0E9E /* MCIMAPCreateFolderOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA80616A2999800778456 /* MCIMAPCreateFolderOperation.cc */; }; - C6BA2BC91705F4E6003F0E9E /* MCIMAPSubscribeFolderOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA80916A299B500778456 /* MCIMAPSubscribeFolderOperation.cc */; }; - C6BA2BCA1705F4E6003F0E9E /* MCIMAPAppendMessageOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA80F16A299EA00778456 /* MCIMAPAppendMessageOperation.cc */; }; - C6BA2BCB1705F4E6003F0E9E /* MCIMAPCopyMessagesOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA81216A29A0A00778456 /* MCIMAPCopyMessagesOperation.cc */; }; - C6BA2BCC1705F4E6003F0E9E /* MCIMAPExpungeOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA81516A29A8500778456 /* MCIMAPExpungeOperation.cc */; }; - C6BA2BCD1705F4E6003F0E9E /* MCIMAPFetchMessagesOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA81816A29AD400778456 /* MCIMAPFetchMessagesOperation.cc */; }; - C6BA2BCE1705F4E6003F0E9E /* MCIMAPFetchContentOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA81B16A29DC100778456 /* MCIMAPFetchContentOperation.cc */; }; - C6BA2BCF1705F4E6003F0E9E /* MCIMAPStoreFlagsOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA81E16A29E3D00778456 /* MCIMAPStoreFlagsOperation.cc */; }; - C6BA2BD01705F4E6003F0E9E /* MCIMAPStoreLabelsOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA82116A29E4F00778456 /* MCIMAPStoreLabelsOperation.cc */; }; - C6BA2BD11705F4E6003F0E9E /* MCIMAPSearchOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA82416A29EE000778456 /* MCIMAPSearchOperation.cc */; }; - C6BA2BD21705F4E6003F0E9E /* MCIMAPIdleOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA82716A29EF400778456 /* MCIMAPIdleOperation.cc */; }; - C6BA2BD31705F4E6003F0E9E /* MCIMAPFetchNamespaceOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA82A16A29FAA00778456 /* MCIMAPFetchNamespaceOperation.cc */; }; - C6BA2BD41705F4E6003F0E9E /* MCIMAPIdentityOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C62C6ED216A2A0E600737497 /* MCIMAPIdentityOperation.cc */; }; - C6BA2BD51705F4E6003F0E9E /* MCIMAPFolderInfoOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C62C6ED616A398FA00737497 /* MCIMAPFolderInfoOperation.cc */; }; - C6BA2BD61705F4E6003F0E9E /* MCIMAPAsyncConnection.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA7FD16A295B500778456 /* MCIMAPAsyncConnection.cc */; }; - C6BA2BD71705F4E6003F0E9E /* MCPOPAsyncSession.cc in Sources */ = {isa = PBXBuildFile; fileRef = C62C6EED16A7B67600737497 /* MCPOPAsyncSession.cc */; }; - C6BA2BD81705F4E6003F0E9E /* MCPOPFetchHeaderOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C62C6EF016A7C6DE00737497 /* MCPOPFetchHeaderOperation.cc */; }; - C6BA2BD91705F4E6003F0E9E /* MCPOPFetchMessageOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C62C6EF316A7C6E900737497 /* MCPOPFetchMessageOperation.cc */; }; - C6BA2BDA1705F4E6003F0E9E /* MCPOPDeleteMessagesOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C62C6EF616A7C6F500737497 /* MCPOPDeleteMessagesOperation.cc */; }; - C6BA2BDB1705F4E6003F0E9E /* MCPOPOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C62C6EF916A7C93F00737497 /* MCPOPOperation.cc */; }; - C6BA2BDC1705F4E6003F0E9E /* MCPOPFetchMessagesOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C62C6F0416A7E54200737497 /* MCPOPFetchMessagesOperation.cc */; }; - C6BA2BDD1705F4E6003F0E9E /* MCIMAPAsyncSession.cc in Sources */ = {isa = PBXBuildFile; fileRef = C62C6F0816A8F57000737497 /* MCIMAPAsyncSession.cc */; }; + C6BA2BAC1705F4E6003F0E9E /* MCOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6BE169E847800778456 /* MCOperation.cpp */; }; + C6BA2BAD1705F4E6003F0E9E /* MCOperationQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6C1169E847800778456 /* MCOperationQueue.cpp */; }; + C6BA2BAE1705F4E6003F0E9E /* MCIMAPFolder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6C5169E847800778456 /* MCIMAPFolder.cpp */; }; + C6BA2BAF1705F4E6003F0E9E /* MCIMAPMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6C7169E847800778456 /* MCIMAPMessage.cpp */; }; + C6BA2BB01705F4E6003F0E9E /* MCIMAPMessagePart.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6C9169E847800778456 /* MCIMAPMessagePart.cpp */; }; + C6BA2BB11705F4E6003F0E9E /* MCIMAPMultipart.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6CB169E847800778456 /* MCIMAPMultipart.cpp */; }; + C6BA2BB21705F4E6003F0E9E /* MCIMAPNamespace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6CD169E847800778456 /* MCIMAPNamespace.cpp */; }; + C6BA2BB31705F4E6003F0E9E /* MCIMAPNamespaceItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6CF169E847800778456 /* MCIMAPNamespaceItem.cpp */; }; + C6BA2BB41705F4E6003F0E9E /* MCIMAPPart.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6D1169E847800778456 /* MCIMAPPart.cpp */; }; + C6BA2BB51705F4E6003F0E9E /* MCIMAPSearchExpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6D4169E847800778456 /* MCIMAPSearchExpression.cpp */; }; + C6BA2BB61705F4E6003F0E9E /* MCIMAPSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6D6169E847800778456 /* MCIMAPSession.cpp */; }; + C6BA2BB71705F4E6003F0E9E /* MCPOPMessageInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6DA169E847800778456 /* MCPOPMessageInfo.cpp */; }; + C6BA2BB81705F4E6003F0E9E /* MCPOPSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6DD169E847800778456 /* MCPOPSession.cpp */; }; + C6BA2BB91705F4E6003F0E9E /* MCAttachment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6E0169E847800778456 /* MCAttachment.cpp */; }; + C6BA2BBA1705F4E6003F0E9E /* MCMessageBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6E2169E847800778456 /* MCMessageBuilder.cpp */; }; + C6BA2BBB1705F4E6003F0E9E /* MCMessageParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6E4169E847800778456 /* MCMessageParser.cpp */; }; + C6BA2BBC1705F4E6003F0E9E /* MCMessagePart.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6E6169E847800778456 /* MCMessagePart.cpp */; }; + C6BA2BBD1705F4E6003F0E9E /* MCMultipart.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6E8169E847800778456 /* MCMultipart.cpp */; }; + C6BA2BBE1705F4E6003F0E9E /* MCSMTPSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA6EE169E847800778456 /* MCSMTPSession.cpp */; }; + C6BA2BBF1705F4E6003F0E9E /* MCSMTPAsyncSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA68F169E847800778456 /* MCSMTPAsyncSession.cpp */; }; + C6BA2BC01705F4E6003F0E9E /* MCSMTPSendWithDataOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA79C169F29A700778456 /* MCSMTPSendWithDataOperation.cpp */; }; + C6BA2BC11705F4E6003F0E9E /* MCSMTPOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA7D816A1386500778456 /* MCSMTPOperation.cpp */; }; + C6BA2BC21705F4E6003F0E9E /* MCSMTPCheckAccountOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA7E816A154B000778456 /* MCSMTPCheckAccountOperation.cpp */; }; + C6BA2BC31705F4E6003F0E9E /* MCIMAPOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA7EF16A15A4D00778456 /* MCIMAPOperation.cpp */; }; + C6BA2BC41705F4E6003F0E9E /* MCIMAPCheckAccountOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA7F616A15A7800778456 /* MCIMAPCheckAccountOperation.cpp */; }; + C6BA2BC51705F4E6003F0E9E /* MCIMAPFetchFoldersOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA7FA16A2959700778456 /* MCIMAPFetchFoldersOperation.cpp */; }; + C6BA2BC61705F4E6003F0E9E /* MCIMAPRenameFolderOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA80016A295E200778456 /* MCIMAPRenameFolderOperation.cpp */; }; + C6BA2BC71705F4E6003F0E9E /* MCIMAPDeleteFolderOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA80316A2997B00778456 /* MCIMAPDeleteFolderOperation.cpp */; }; + C6BA2BC81705F4E6003F0E9E /* MCIMAPCreateFolderOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA80616A2999800778456 /* MCIMAPCreateFolderOperation.cpp */; }; + C6BA2BC91705F4E6003F0E9E /* MCIMAPSubscribeFolderOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA80916A299B500778456 /* MCIMAPSubscribeFolderOperation.cpp */; }; + C6BA2BCA1705F4E6003F0E9E /* MCIMAPAppendMessageOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA80F16A299EA00778456 /* MCIMAPAppendMessageOperation.cpp */; }; + C6BA2BCB1705F4E6003F0E9E /* MCIMAPCopyMessagesOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA81216A29A0A00778456 /* MCIMAPCopyMessagesOperation.cpp */; }; + C6BA2BCC1705F4E6003F0E9E /* MCIMAPExpungeOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA81516A29A8500778456 /* MCIMAPExpungeOperation.cpp */; }; + C6BA2BCD1705F4E6003F0E9E /* MCIMAPFetchMessagesOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA81816A29AD400778456 /* MCIMAPFetchMessagesOperation.cpp */; }; + C6BA2BCE1705F4E6003F0E9E /* MCIMAPFetchContentOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA81B16A29DC100778456 /* MCIMAPFetchContentOperation.cpp */; }; + C6BA2BCF1705F4E6003F0E9E /* MCIMAPStoreFlagsOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA81E16A29E3D00778456 /* MCIMAPStoreFlagsOperation.cpp */; }; + C6BA2BD01705F4E6003F0E9E /* MCIMAPStoreLabelsOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA82116A29E4F00778456 /* MCIMAPStoreLabelsOperation.cpp */; }; + C6BA2BD11705F4E6003F0E9E /* MCIMAPSearchOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA82416A29EE000778456 /* MCIMAPSearchOperation.cpp */; }; + C6BA2BD21705F4E6003F0E9E /* MCIMAPIdleOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA82716A29EF400778456 /* MCIMAPIdleOperation.cpp */; }; + C6BA2BD31705F4E6003F0E9E /* MCIMAPFetchNamespaceOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA82A16A29FAA00778456 /* MCIMAPFetchNamespaceOperation.cpp */; }; + C6BA2BD41705F4E6003F0E9E /* MCIMAPIdentityOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C62C6ED216A2A0E600737497 /* MCIMAPIdentityOperation.cpp */; }; + C6BA2BD51705F4E6003F0E9E /* MCIMAPFolderInfoOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C62C6ED616A398FA00737497 /* MCIMAPFolderInfoOperation.cpp */; }; + C6BA2BD61705F4E6003F0E9E /* MCIMAPAsyncConnection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64EA7FD16A295B500778456 /* MCIMAPAsyncConnection.cpp */; }; + C6BA2BD71705F4E6003F0E9E /* MCPOPAsyncSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C62C6EED16A7B67600737497 /* MCPOPAsyncSession.cpp */; }; + C6BA2BD81705F4E6003F0E9E /* MCPOPFetchHeaderOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C62C6EF016A7C6DE00737497 /* MCPOPFetchHeaderOperation.cpp */; }; + C6BA2BD91705F4E6003F0E9E /* MCPOPFetchMessageOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C62C6EF316A7C6E900737497 /* MCPOPFetchMessageOperation.cpp */; }; + C6BA2BDA1705F4E6003F0E9E /* MCPOPDeleteMessagesOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C62C6EF616A7C6F500737497 /* MCPOPDeleteMessagesOperation.cpp */; }; + C6BA2BDB1705F4E6003F0E9E /* MCPOPOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C62C6EF916A7C93F00737497 /* MCPOPOperation.cpp */; }; + C6BA2BDC1705F4E6003F0E9E /* MCPOPFetchMessagesOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C62C6F0416A7E54200737497 /* MCPOPFetchMessagesOperation.cpp */; }; + C6BA2BDD1705F4E6003F0E9E /* MCIMAPAsyncSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C62C6F0816A8F57000737497 /* MCIMAPAsyncSession.cpp */; }; C6BA2BDE1705F4E6003F0E9E /* NSData+MCO.mm in Sources */ = {isa = PBXBuildFile; fileRef = C6D42C1A16AE03D6002BB4F9 /* NSData+MCO.mm */; }; C6BA2BDF1705F4E6003F0E9E /* NSString+MCO.mm in Sources */ = {isa = PBXBuildFile; fileRef = C6D42C1C16AE03D6002BB4F9 /* NSString+MCO.mm */; }; C6BA2BE01705F4E6003F0E9E /* MCOObjectWrapper.mm in Sources */ = {isa = PBXBuildFile; fileRef = C64FF39016B3C13000F8C162 /* MCOObjectWrapper.mm */; }; @@ -673,15 +673,15 @@ C6BA2BE41705F4E6003F0E9E /* NSDictionary+MCO.mm in Sources */ = {isa = PBXBuildFile; fileRef = C6EB30F616B8C9480091F4F1 /* NSDictionary+MCO.mm */; }; C6BA2BE51705F4E6003F0E9E /* NSArray+MCO.mm in Sources */ = {isa = PBXBuildFile; fileRef = C6EB30FC16B8E50F0091F4F1 /* NSArray+MCO.mm */; }; C6BA2BE61705F4E6003F0E9E /* NSObject+MCO.mm in Sources */ = {isa = PBXBuildFile; fileRef = C6EB310016B8E6E50091F4F1 /* NSObject+MCO.mm */; }; - C6BA2BE71705F4E6003F0E9E /* MCAddressDisplay.cc in Sources */ = {isa = PBXBuildFile; fileRef = C63CD67716BDCDD400DB18F1 /* MCAddressDisplay.cc */; }; - C6BA2BE81705F4E6003F0E9E /* MCDateFormatter.cc in Sources */ = {isa = PBXBuildFile; fileRef = C63CD67916BDCDD400DB18F1 /* MCDateFormatter.cc */; }; - C6BA2BE91705F4E6003F0E9E /* MCHTMLRenderer.cc in Sources */ = {isa = PBXBuildFile; fileRef = C63CD67B16BDCDD400DB18F1 /* MCHTMLRenderer.cc */; }; - C6BA2BEA1705F4E6003F0E9E /* MCSizeFormatter.cc in Sources */ = {isa = PBXBuildFile; fileRef = C63CD67D16BDCDD400DB18F1 /* MCSizeFormatter.cc */; }; - C6BA2BEB1705F4E6003F0E9E /* MCHTMLRendererCallback.cc in Sources */ = {isa = PBXBuildFile; fileRef = C63CD68416BE148B00DB18F1 /* MCHTMLRendererCallback.cc */; }; - C6BA2BEC1705F4E6003F0E9E /* MCHTMLCleaner.cc in Sources */ = {isa = PBXBuildFile; fileRef = C63CD68F16BE566D00DB18F1 /* MCHTMLCleaner.cc */; }; - C6BA2BED1705F4E6003F0E9E /* MCIMAPSyncResult.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64BB21F16E34DCA000DB34C /* MCIMAPSyncResult.cc */; }; - C6BA2BEE1705F4E6003F0E9E /* MCIMAPCapabilityOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64BB22916E5C0A3000DB34C /* MCIMAPCapabilityOperation.cc */; }; - C6BA2BEF1705F4E6003F0E9E /* MCIndexSet.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64BB22C16E5C1EE000DB34C /* MCIndexSet.cc */; }; + C6BA2BE71705F4E6003F0E9E /* MCAddressDisplay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C63CD67716BDCDD400DB18F1 /* MCAddressDisplay.cpp */; }; + C6BA2BE81705F4E6003F0E9E /* MCDateFormatter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C63CD67916BDCDD400DB18F1 /* MCDateFormatter.cpp */; }; + C6BA2BE91705F4E6003F0E9E /* MCHTMLRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C63CD67B16BDCDD400DB18F1 /* MCHTMLRenderer.cpp */; }; + C6BA2BEA1705F4E6003F0E9E /* MCSizeFormatter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C63CD67D16BDCDD400DB18F1 /* MCSizeFormatter.cpp */; }; + C6BA2BEB1705F4E6003F0E9E /* MCHTMLRendererCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C63CD68416BE148B00DB18F1 /* MCHTMLRendererCallback.cpp */; }; + C6BA2BEC1705F4E6003F0E9E /* MCHTMLCleaner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C63CD68F16BE566D00DB18F1 /* MCHTMLCleaner.cpp */; }; + C6BA2BED1705F4E6003F0E9E /* MCIMAPSyncResult.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64BB21F16E34DCA000DB34C /* MCIMAPSyncResult.cpp */; }; + C6BA2BEE1705F4E6003F0E9E /* MCIMAPCapabilityOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64BB22916E5C0A3000DB34C /* MCIMAPCapabilityOperation.cpp */; }; + C6BA2BEF1705F4E6003F0E9E /* MCIndexSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C64BB22C16E5C1EE000DB34C /* MCIndexSet.cpp */; }; C6BA2BF01705F4E6003F0E9E /* MCOAbstractMessage.mm in Sources */ = {isa = PBXBuildFile; fileRef = C64BB23416EDAA17000DB34C /* MCOAbstractMessage.mm */; }; C6BA2BF11705F4E6003F0E9E /* MCOAbstractMessagePart.mm in Sources */ = {isa = PBXBuildFile; fileRef = C64BB23816EDAA3F000DB34C /* MCOAbstractMessagePart.mm */; }; C6BA2BF21705F4E6003F0E9E /* MCOAbstractMultipart.mm in Sources */ = {isa = PBXBuildFile; fileRef = C64BB23B16EDAAC7000DB34C /* MCOAbstractMultipart.mm */; }; @@ -732,12 +732,12 @@ C6CF62BC175324CE006398B9 /* MCOMailProvidersManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = C6CF62B5175324CE006398B9 /* MCOMailProvidersManager.mm */; }; C6CF62BD175324CE006398B9 /* MCONetService.mm in Sources */ = {isa = PBXBuildFile; fileRef = C6CF62B7175324CE006398B9 /* MCONetService.mm */; }; C6CF62BE175324CE006398B9 /* MCONetService.mm in Sources */ = {isa = PBXBuildFile; fileRef = C6CF62B7175324CE006398B9 /* MCONetService.mm */; }; - C6CF62C6175324F0006398B9 /* MCMailProvider.cc in Sources */ = {isa = PBXBuildFile; fileRef = C6CF62BF175324F0006398B9 /* MCMailProvider.cc */; }; - C6CF62C7175324F0006398B9 /* MCMailProvider.cc in Sources */ = {isa = PBXBuildFile; fileRef = C6CF62BF175324F0006398B9 /* MCMailProvider.cc */; }; - C6CF62C8175324F0006398B9 /* MCMailProvidersManager.cc in Sources */ = {isa = PBXBuildFile; fileRef = C6CF62C1175324F0006398B9 /* MCMailProvidersManager.cc */; }; - C6CF62C9175324F0006398B9 /* MCMailProvidersManager.cc in Sources */ = {isa = PBXBuildFile; fileRef = C6CF62C1175324F0006398B9 /* MCMailProvidersManager.cc */; }; - C6CF62CA175324F0006398B9 /* MCNetService.cc in Sources */ = {isa = PBXBuildFile; fileRef = C6CF62C3175324F0006398B9 /* MCNetService.cc */; }; - C6CF62CB175324F0006398B9 /* MCNetService.cc in Sources */ = {isa = PBXBuildFile; fileRef = C6CF62C3175324F0006398B9 /* MCNetService.cc */; }; + C6CF62C6175324F0006398B9 /* MCMailProvider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6CF62BF175324F0006398B9 /* MCMailProvider.cpp */; }; + C6CF62C7175324F0006398B9 /* MCMailProvider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6CF62BF175324F0006398B9 /* MCMailProvider.cpp */; }; + C6CF62C8175324F0006398B9 /* MCMailProvidersManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6CF62C1175324F0006398B9 /* MCMailProvidersManager.cpp */; }; + C6CF62C9175324F0006398B9 /* MCMailProvidersManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6CF62C1175324F0006398B9 /* MCMailProvidersManager.cpp */; }; + C6CF62CA175324F0006398B9 /* MCNetService.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6CF62C3175324F0006398B9 /* MCNetService.cpp */; }; + C6CF62CB175324F0006398B9 /* MCNetService.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6CF62C3175324F0006398B9 /* MCNetService.cpp */; }; C6CF62CD1753250E006398B9 /* MCOMailProvider.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6CF62B2175324CE006398B9 /* MCOMailProvider.h */; }; C6CF62CE17532510006398B9 /* MCOMailProvidersManager.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6CF62B4175324CE006398B9 /* MCOMailProvidersManager.h */; }; C6CF62CF17532514006398B9 /* MCONetService.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6CF62B6175324CE006398B9 /* MCONetService.h */; }; @@ -770,28 +770,28 @@ C6D4FD4019FB7786001F7E01 /* MCMessageParserMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = C6D4FD3E19FB7534001F7E01 /* MCMessageParserMac.mm */; }; C6D4FD4319FB7DAA001F7E01 /* MCDataMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = C6D4FD4219FB7DAA001F7E01 /* MCDataMac.mm */; }; C6D4FD4419FB7DB2001F7E01 /* MCDataMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = C6D4FD4219FB7DAA001F7E01 /* MCDataMac.mm */; }; - C6D6F7F9171E595D006F5B28 /* MCJSON.cc in Sources */ = {isa = PBXBuildFile; fileRef = C6D6F7F7171E595D006F5B28 /* MCJSON.cc */; }; - C6D6F7FA171E595D006F5B28 /* MCJSON.cc in Sources */ = {isa = PBXBuildFile; fileRef = C6D6F7F7171E595D006F5B28 /* MCJSON.cc */; }; - C6D6F954171E5CB8006F5B28 /* MCMD5.cc in Sources */ = {isa = PBXBuildFile; fileRef = C6D6F950171E5CB8006F5B28 /* MCMD5.cc */; }; - C6D6F955171E5CB8006F5B28 /* MCMD5.cc in Sources */ = {isa = PBXBuildFile; fileRef = C6D6F950171E5CB8006F5B28 /* MCMD5.cc */; }; - C6D6F956171E5CB8006F5B28 /* MCNull.cc in Sources */ = {isa = PBXBuildFile; fileRef = C6D6F952171E5CB8006F5B28 /* MCNull.cc */; }; - C6D6F957171E5CB8006F5B28 /* MCNull.cc in Sources */ = {isa = PBXBuildFile; fileRef = C6D6F952171E5CB8006F5B28 /* MCNull.cc */; }; + C6D6F7F9171E595D006F5B28 /* MCJSON.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6D6F7F7171E595D006F5B28 /* MCJSON.cpp */; }; + C6D6F7FA171E595D006F5B28 /* MCJSON.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6D6F7F7171E595D006F5B28 /* MCJSON.cpp */; }; + C6D6F954171E5CB8006F5B28 /* MCMD5.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6D6F950171E5CB8006F5B28 /* MCMD5.cpp */; }; + C6D6F955171E5CB8006F5B28 /* MCMD5.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6D6F950171E5CB8006F5B28 /* MCMD5.cpp */; }; + C6D6F956171E5CB8006F5B28 /* MCNull.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6D6F952171E5CB8006F5B28 /* MCNull.cpp */; }; + C6D6F957171E5CB8006F5B28 /* MCNull.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6D6F952171E5CB8006F5B28 /* MCNull.cpp */; }; C6D6F958171E5D5C006F5B28 /* MCNull.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6D6F953171E5CB8006F5B28 /* MCNull.h */; }; C6D6F959171E5D5E006F5B28 /* MCMD5.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6D6F951171E5CB8006F5B28 /* MCMD5.h */; }; C6D6F95A171E5D60006F5B28 /* MCJSON.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6D6F7F8171E595D006F5B28 /* MCJSON.h */; }; C6D6F95B171E5D63006F5B28 /* MCNull.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6D6F953171E5CB8006F5B28 /* MCNull.h */; }; C6D6F95C171E5D65006F5B28 /* MCJSON.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6D6F7F8171E595D006F5B28 /* MCJSON.h */; }; C6D6F95D171E5D67006F5B28 /* MCMD5.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6D6F951171E5CB8006F5B28 /* MCMD5.h */; }; - C6D6F967171FCF9F006F5B28 /* MCJSONParser.cc in Sources */ = {isa = PBXBuildFile; fileRef = C6D6F965171FCF9F006F5B28 /* MCJSONParser.cc */; }; - C6D6F968171FCF9F006F5B28 /* MCJSONParser.cc in Sources */ = {isa = PBXBuildFile; fileRef = C6D6F965171FCF9F006F5B28 /* MCJSONParser.cc */; }; + C6D6F967171FCF9F006F5B28 /* MCJSONParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6D6F965171FCF9F006F5B28 /* MCJSONParser.cpp */; }; + C6D6F968171FCF9F006F5B28 /* MCJSONParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6D6F965171FCF9F006F5B28 /* MCJSONParser.cpp */; }; C6D6F96A1720F92B006F5B28 /* MCICUTypes.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6D6F9691720F8F4006F5B28 /* MCICUTypes.h */; }; C6D6F96B1720F92D006F5B28 /* MCICUTypes.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6D6F9691720F8F4006F5B28 /* MCICUTypes.h */; }; C6D6F97017211173006F5B28 /* MCIterator.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6D6F96D1721028D006F5B28 /* MCIterator.h */; }; C6D6F97117211177006F5B28 /* MCIterator.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6D6F96D1721028D006F5B28 /* MCIterator.h */; }; C6E665001790963E0063F2CF /* MCIMAPMessageRenderingOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DA0F1C7A177C07B300F0D3B4 /* MCIMAPMessageRenderingOperation.h */; }; C6E6652F1791B2530063F2CF /* MCIMAPMessageRenderingOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DA0F1C7A177C07B300F0D3B4 /* MCIMAPMessageRenderingOperation.h */; }; - C6E665B51796500B0063F2CF /* MCZip.cc in Sources */ = {isa = PBXBuildFile; fileRef = C6E665AA1796500B0063F2CF /* MCZip.cc */; }; - C6E665B61796500B0063F2CF /* MCZip.cc in Sources */ = {isa = PBXBuildFile; fileRef = C6E665AA1796500B0063F2CF /* MCZip.cc */; }; + C6E665B51796500B0063F2CF /* MCZip.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6E665AA1796500B0063F2CF /* MCZip.cpp */; }; + C6E665B61796500B0063F2CF /* MCZip.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6E665AA1796500B0063F2CF /* MCZip.cpp */; }; C6E665B71796500B0063F2CF /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = C6E665AD1796500B0063F2CF /* ioapi.c */; }; C6E665B81796500B0063F2CF /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = C6E665AD1796500B0063F2CF /* ioapi.c */; }; C6E665BB1796500C0063F2CF /* unzip.c in Sources */ = {isa = PBXBuildFile; fileRef = C6E665B11796500B0063F2CF /* unzip.c */; }; @@ -808,8 +808,8 @@ C6ED6D1A17A1919500A4A14C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C6ED6D1917A1919500A4A14C /* Security.framework */; }; C6ED6D1B17A191B100A4A14C /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C64EA7B016A00BBB00778456 /* CoreServices.framework */; }; C6ED6D1D17A191BF00A4A14C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C6ED6D1C17A191BF00A4A14C /* Security.framework */; }; - C6EFFBC8182BBF5700CFF656 /* MCIMAPMultiDisconnectOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C6EFFBC6182BBF5700CFF656 /* MCIMAPMultiDisconnectOperation.cc */; }; - C6EFFBC9182BBF5700CFF656 /* MCIMAPMultiDisconnectOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = C6EFFBC6182BBF5700CFF656 /* MCIMAPMultiDisconnectOperation.cc */; }; + C6EFFBC8182BBF5700CFF656 /* MCIMAPMultiDisconnectOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6EFFBC6182BBF5700CFF656 /* MCIMAPMultiDisconnectOperation.cpp */; }; + C6EFFBC9182BBF5700CFF656 /* MCIMAPMultiDisconnectOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6EFFBC6182BBF5700CFF656 /* MCIMAPMultiDisconnectOperation.cpp */; }; C6EFFBCC1833334900CFF656 /* MCOIMAPMultiDisconnectOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = C6EFFBCB1833334900CFF656 /* MCOIMAPMultiDisconnectOperation.mm */; }; C6EFFBCD1833334900CFF656 /* MCOIMAPMultiDisconnectOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = C6EFFBCB1833334900CFF656 /* MCOIMAPMultiDisconnectOperation.mm */; }; C6F5B9E216FEA1E800D9DABD /* MCOIMAPMessage.mm in Sources */ = {isa = PBXBuildFile; fileRef = C6F5B9E116FEA1E800D9DABD /* MCOIMAPMessage.mm */; }; @@ -860,16 +860,16 @@ C6F61FB21702886B0073032E /* MCORFC822.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C64BB26B16FD4C3B000DB34C /* MCORFC822.h */; }; C6F61FB51702AB340073032E /* MCOIMAPBaseOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = C6F61FB41702AB2F0073032E /* MCOIMAPBaseOperation.mm */; }; C6F61FB61702B5290073032E /* MCOIMAPBaseOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6F61FB31702AB2A0073032E /* MCOIMAPBaseOperation.h */; }; - C6F7B19F17A1C15200BE78BB /* MCCertificateUtils.cc in Sources */ = {isa = PBXBuildFile; fileRef = C6F7B19D17A1C15200BE78BB /* MCCertificateUtils.cc */; }; - C6F7B1A017A1C15200BE78BB /* MCCertificateUtils.cc in Sources */ = {isa = PBXBuildFile; fileRef = C6F7B19D17A1C15200BE78BB /* MCCertificateUtils.cc */; }; - DA0F1C7B177C07B300F0D3B4 /* MCIMAPMessageRenderingOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = DA0F1C79177C07B300F0D3B4 /* MCIMAPMessageRenderingOperation.cc */; }; - DA0F1C7C177C07B300F0D3B4 /* MCIMAPMessageRenderingOperation.cc in Sources */ = {isa = PBXBuildFile; fileRef = DA0F1C79177C07B300F0D3B4 /* MCIMAPMessageRenderingOperation.cc */; }; + C6F7B19F17A1C15200BE78BB /* MCCertificateUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6F7B19D17A1C15200BE78BB /* MCCertificateUtils.cpp */; }; + C6F7B1A017A1C15200BE78BB /* MCCertificateUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6F7B19D17A1C15200BE78BB /* MCCertificateUtils.cpp */; }; + DA0F1C7B177C07B300F0D3B4 /* MCIMAPMessageRenderingOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DA0F1C79177C07B300F0D3B4 /* MCIMAPMessageRenderingOperation.cpp */; }; + DA0F1C7C177C07B300F0D3B4 /* MCIMAPMessageRenderingOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DA0F1C79177C07B300F0D3B4 /* MCIMAPMessageRenderingOperation.cpp */; }; DA89896D178A47D200F6D90A /* MCOIMAPMessageRenderingOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA89896C178A47D200F6D90A /* MCOIMAPMessageRenderingOperation.mm */; }; DA89896E178A47D200F6D90A /* MCOIMAPMessageRenderingOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA89896C178A47D200F6D90A /* MCOIMAPMessageRenderingOperation.mm */; }; - DAACAD5117886807000B4517 /* MCHTMLRendererIMAPDataCallback.cc in Sources */ = {isa = PBXBuildFile; fileRef = DAACAD4F17886807000B4517 /* MCHTMLRendererIMAPDataCallback.cc */; }; - DAACAD5217886807000B4517 /* MCHTMLRendererIMAPDataCallback.cc in Sources */ = {isa = PBXBuildFile; fileRef = DAACAD4F17886807000B4517 /* MCHTMLRendererIMAPDataCallback.cc */; }; - DAD28C8B1783CFFC00F2BB8F /* MCHTMLBodyRendererTemplateCallback.cc in Sources */ = {isa = PBXBuildFile; fileRef = DAD28C891783CFFC00F2BB8F /* MCHTMLBodyRendererTemplateCallback.cc */; }; - DAD28C8C1783CFFC00F2BB8F /* MCHTMLBodyRendererTemplateCallback.cc in Sources */ = {isa = PBXBuildFile; fileRef = DAD28C891783CFFC00F2BB8F /* MCHTMLBodyRendererTemplateCallback.cc */; }; + DAACAD5117886807000B4517 /* MCHTMLRendererIMAPDataCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DAACAD4F17886807000B4517 /* MCHTMLRendererIMAPDataCallback.cpp */; }; + DAACAD5217886807000B4517 /* MCHTMLRendererIMAPDataCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DAACAD4F17886807000B4517 /* MCHTMLRendererIMAPDataCallback.cpp */; }; + DAD28C8B1783CFFC00F2BB8F /* MCHTMLBodyRendererTemplateCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DAD28C891783CFFC00F2BB8F /* MCHTMLBodyRendererTemplateCallback.cpp */; }; + DAD28C8C1783CFFC00F2BB8F /* MCHTMLBodyRendererTemplateCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DAD28C891783CFFC00F2BB8F /* MCHTMLBodyRendererTemplateCallback.cpp */; }; DAE42E89178F7E1800E0DB8F /* MCOIMAPMessageRenderingOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DA89896B178A47D200F6D90A /* MCOIMAPMessageRenderingOperation.h */; }; DAE42E8A178F7E2200E0DB8F /* MCOIMAPMessageRenderingOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DA89896B178A47D200F6D90A /* MCOIMAPMessageRenderingOperation.h */; }; F87F190C16BB62B00012652F /* MCOIMAPFetchFoldersOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = F87F190B16BB62B00012652F /* MCOIMAPFetchFoldersOperation.mm */; }; @@ -1370,56 +1370,56 @@ 27780D3419CFA19500C77E44 /* libstdc++.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libstdc++.dylib"; path = "Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.0.sdk/usr/lib/libstdc++.dylib"; sourceTree = DEVELOPER_DIR; }; 4B3C1BDC17ABF306008BBF4C /* MCOIMAPQuotaOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOIMAPQuotaOperation.h; sourceTree = ""; }; 4B3C1BDD17ABF307008BBF4C /* MCOIMAPQuotaOperation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOIMAPQuotaOperation.mm; sourceTree = ""; }; - 4B3C1BDF17ABF4BB008BBF4C /* MCIMAPQuotaOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPQuotaOperation.cc; sourceTree = ""; }; + 4B3C1BDF17ABF4BB008BBF4C /* MCIMAPQuotaOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPQuotaOperation.cpp; sourceTree = ""; }; 4B3C1BE017ABF4BC008BBF4C /* MCIMAPQuotaOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPQuotaOperation.h; sourceTree = ""; }; 8199FBE719FAEA440040BBC3 /* MCOIMAPFetchParsedContentOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOIMAPFetchParsedContentOperation.h; sourceTree = ""; }; 8199FBE819FAEA440040BBC3 /* MCOIMAPFetchParsedContentOperation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOIMAPFetchParsedContentOperation.mm; sourceTree = ""; }; - 8199FBEF19FAF1270040BBC3 /* MCIMAPFetchParsedContentOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPFetchParsedContentOperation.cc; sourceTree = ""; }; + 8199FBEF19FAF1270040BBC3 /* MCIMAPFetchParsedContentOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPFetchParsedContentOperation.cpp; sourceTree = ""; }; 8199FBF019FAF1270040BBC3 /* MCIMAPFetchParsedContentOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPFetchParsedContentOperation.h; sourceTree = ""; }; 8416A99B17F284F400B3C7DA /* MCOSMTPNoopOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOSMTPNoopOperation.h; sourceTree = ""; }; 8416A99C17F284F400B3C7DA /* MCOSMTPNoopOperation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOSMTPNoopOperation.mm; sourceTree = ""; }; 8416A99F17F2871D00B3C7DA /* MCOIMAPNoopOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOIMAPNoopOperation.h; sourceTree = ""; }; 8416A9A017F2871D00B3C7DA /* MCOIMAPNoopOperation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOIMAPNoopOperation.mm; sourceTree = ""; }; 8491899C18C93F92002063A3 /* MCNNTP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MCNNTP.h; path = nntp/MCNNTP.h; sourceTree = ""; }; - 8491899F18C93FB7002063A3 /* MCNNTPSession.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MCNNTPSession.cc; path = nntp/MCNNTPSession.cc; sourceTree = ""; }; + 8491899F18C93FB7002063A3 /* MCNNTPSession.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MCNNTPSession.cpp; path = nntp/MCNNTPSession.cpp; sourceTree = ""; }; 849189A018C93FB7002063A3 /* MCNNTPSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MCNNTPSession.h; path = nntp/MCNNTPSession.h; sourceTree = ""; }; - 849189A918C94986002063A3 /* MCNNTPGroupInfo.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MCNNTPGroupInfo.cc; path = nntp/MCNNTPGroupInfo.cc; sourceTree = ""; }; + 849189A918C94986002063A3 /* MCNNTPGroupInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MCNNTPGroupInfo.cpp; path = nntp/MCNNTPGroupInfo.cpp; sourceTree = ""; }; 849189AA18C94986002063A3 /* MCNNTPGroupInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MCNNTPGroupInfo.h; path = nntp/MCNNTPGroupInfo.h; sourceTree = ""; }; 84AF9E7D172DBAF600E60AA3 /* providers.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = providers.json; path = ../resources/providers.json; sourceTree = ""; }; - 84B639E117F279BB003B5BA2 /* MCSMTPNoopOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCSMTPNoopOperation.cc; sourceTree = ""; }; + 84B639E117F279BB003B5BA2 /* MCSMTPNoopOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCSMTPNoopOperation.cpp; sourceTree = ""; }; 84B639E217F279BB003B5BA2 /* MCSMTPNoopOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCSMTPNoopOperation.h; sourceTree = ""; }; - 84B639E617F27EBD003B5BA2 /* MCPOPNoopOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCPOPNoopOperation.cc; sourceTree = ""; }; + 84B639E617F27EBD003B5BA2 /* MCPOPNoopOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCPOPNoopOperation.cpp; sourceTree = ""; }; 84B639E717F27EBD003B5BA2 /* MCPOPNoopOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCPOPNoopOperation.h; sourceTree = ""; }; - 84B639EB17F280F3003B5BA2 /* MCIMAPNoopOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPNoopOperation.cc; sourceTree = ""; }; + 84B639EB17F280F3003B5BA2 /* MCIMAPNoopOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPNoopOperation.cpp; sourceTree = ""; }; 84B639EC17F280F3003B5BA2 /* MCIMAPNoopOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPNoopOperation.h; sourceTree = ""; }; 84B639EF17F282B4003B5BA2 /* MCOPOPNoopOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOPOPNoopOperation.h; sourceTree = ""; }; 84B639F017F282B4003B5BA2 /* MCOPOPNoopOperation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOPOPNoopOperation.mm; sourceTree = ""; }; 84CFA98119F7153B00FE35D2 /* MCONNTPFetchOverviewOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCONNTPFetchOverviewOperation.h; sourceTree = ""; }; 84CFA98219F7153B00FE35D2 /* MCONNTPFetchOverviewOperation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCONNTPFetchOverviewOperation.mm; sourceTree = ""; }; - 84CFA98519F7159700FE35D2 /* MCNNTPFetchOverviewOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCNNTPFetchOverviewOperation.cc; sourceTree = ""; }; + 84CFA98519F7159700FE35D2 /* MCNNTPFetchOverviewOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCNNTPFetchOverviewOperation.cpp; sourceTree = ""; }; 84CFA98619F7159700FE35D2 /* MCNNTPFetchOverviewOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCNNTPFetchOverviewOperation.h; sourceTree = ""; }; - 84CFA98D19F724E500FE35D2 /* MCNNTPFetchServerTimeOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCNNTPFetchServerTimeOperation.cc; sourceTree = ""; }; + 84CFA98D19F724E500FE35D2 /* MCNNTPFetchServerTimeOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCNNTPFetchServerTimeOperation.cpp; sourceTree = ""; }; 84CFA98E19F724E500FE35D2 /* MCNNTPFetchServerTimeOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCNNTPFetchServerTimeOperation.h; sourceTree = ""; }; 84CFA99319F725CB00FE35D2 /* MCONNTPFetchServerTimeOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCONNTPFetchServerTimeOperation.h; sourceTree = ""; }; 84CFA99419F725CB00FE35D2 /* MCONNTPFetchServerTimeOperation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCONNTPFetchServerTimeOperation.mm; sourceTree = ""; }; 84D73729199BF63F005124E5 /* MCAsyncNNTP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = MCAsyncNNTP.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; - 84D7372A199BF66C005124E5 /* MCNNTPAsyncSession.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = MCNNTPAsyncSession.cc; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 84D7372A199BF66C005124E5 /* MCNNTPAsyncSession.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = MCNNTPAsyncSession.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 84D7372B199BF66C005124E5 /* MCNNTPAsyncSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCNNTPAsyncSession.h; sourceTree = ""; }; - 84D7372E199BF704005124E5 /* MCNNTPOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCNNTPOperation.cc; sourceTree = ""; }; + 84D7372E199BF704005124E5 /* MCNNTPOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCNNTPOperation.cpp; sourceTree = ""; }; 84D7372F199BF704005124E5 /* MCNNTPOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCNNTPOperation.h; sourceTree = ""; }; 84D73732199BF754005124E5 /* MCNNTPProgressCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MCNNTPProgressCallback.h; path = nntp/MCNNTPProgressCallback.h; sourceTree = ""; }; - 84D73735199BF7F2005124E5 /* MCNNTPFetchHeaderOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCNNTPFetchHeaderOperation.cc; sourceTree = ""; }; + 84D73735199BF7F2005124E5 /* MCNNTPFetchHeaderOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCNNTPFetchHeaderOperation.cpp; sourceTree = ""; }; 84D73736199BF7F2005124E5 /* MCNNTPFetchHeaderOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCNNTPFetchHeaderOperation.h; sourceTree = ""; }; - 84D7373B199BF83B005124E5 /* MCNNTPFetchArticleOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = MCNNTPFetchArticleOperation.cc; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 84D7373B199BF83B005124E5 /* MCNNTPFetchArticleOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = MCNNTPFetchArticleOperation.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 84D7373C199BF83B005124E5 /* MCNNTPFetchArticleOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = MCNNTPFetchArticleOperation.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 84D7373F199BF887005124E5 /* MCNNTPOperationCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCNNTPOperationCallback.h; sourceTree = ""; }; - 84D73740199BF963005124E5 /* MCNNTPFetchAllArticlesOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = MCNNTPFetchAllArticlesOperation.cc; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 84D73740199BF963005124E5 /* MCNNTPFetchAllArticlesOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = MCNNTPFetchAllArticlesOperation.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 84D73741199BF963005124E5 /* MCNNTPFetchAllArticlesOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = MCNNTPFetchAllArticlesOperation.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; - 84D73744199BFA8C005124E5 /* MCNNTPCheckAccountOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCNNTPCheckAccountOperation.cc; sourceTree = ""; }; + 84D73744199BFA8C005124E5 /* MCNNTPCheckAccountOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCNNTPCheckAccountOperation.cpp; sourceTree = ""; }; 84D73745199BFA8C005124E5 /* MCNNTPCheckAccountOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCNNTPCheckAccountOperation.h; sourceTree = ""; }; - 84D73756199BFC8A005124E5 /* MCNNTPDisconnectOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCNNTPDisconnectOperation.cc; sourceTree = ""; }; + 84D73756199BFC8A005124E5 /* MCNNTPDisconnectOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCNNTPDisconnectOperation.cpp; sourceTree = ""; }; 84D73757199BFC8A005124E5 /* MCNNTPDisconnectOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCNNTPDisconnectOperation.h; sourceTree = ""; }; - 84D7375A199BFDCA005124E5 /* MCNNTPListNewsgroupsOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCNNTPListNewsgroupsOperation.cc; sourceTree = ""; }; + 84D7375A199BFDCA005124E5 /* MCNNTPListNewsgroupsOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCNNTPListNewsgroupsOperation.cpp; sourceTree = ""; }; 84D7375B199BFDCA005124E5 /* MCNNTPListNewsgroupsOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCNNTPListNewsgroupsOperation.h; sourceTree = ""; }; 84D73761199BFF80005124E5 /* MCONNTP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCONNTP.h; sourceTree = ""; }; 84D73762199BFFC7005124E5 /* MCONNTPSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCONNTPSession.h; sourceTree = ""; }; @@ -1439,18 +1439,18 @@ 84D7378E199C02A8005124E5 /* MCONNTPDisconnectOperation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCONNTPDisconnectOperation.mm; sourceTree = ""; }; 84D73791199C0511005124E5 /* MCONNTPGroupInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCONNTPGroupInfo.h; sourceTree = ""; }; 84D73792199C0511005124E5 /* MCONNTPGroupInfo.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCONNTPGroupInfo.mm; sourceTree = ""; }; - 8B0095C71A00DDC500F84BC0 /* MCSMTPLoginOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCSMTPLoginOperation.cc; sourceTree = ""; }; + 8B0095C71A00DDC500F84BC0 /* MCSMTPLoginOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCSMTPLoginOperation.cpp; sourceTree = ""; }; 8B0095C81A00DDC500F84BC0 /* MCSMTPLoginOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCSMTPLoginOperation.h; sourceTree = ""; }; 8B0095CA1A00DDE700F84BC0 /* MCOSMTPLoginOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOSMTPLoginOperation.h; sourceTree = ""; }; 8B0095CB1A00DDE700F84BC0 /* MCOSMTPLoginOperation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOSMTPLoginOperation.mm; sourceTree = ""; }; - 943F1A9817D964F600F0C798 /* MCIMAPConnectOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPConnectOperation.cc; sourceTree = ""; }; + 943F1A9817D964F600F0C798 /* MCIMAPConnectOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPConnectOperation.cpp; sourceTree = ""; }; 943F1A9917D964F600F0C798 /* MCIMAPConnectOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPConnectOperation.h; sourceTree = ""; }; 9E774D871767C54E0065EB9B /* MCIMAPFolderStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPFolderStatus.h; sourceTree = ""; }; - 9E774D881767C7F60065EB9B /* MCIMAPFolderStatus.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPFolderStatus.cc; sourceTree = ""; }; + 9E774D881767C7F60065EB9B /* MCIMAPFolderStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPFolderStatus.cpp; sourceTree = ""; }; 9EF9AB06175F2EC60027FA3B /* MCOIMAPFolderStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOIMAPFolderStatus.h; sourceTree = ""; }; 9EF9AB07175F2EC60027FA3B /* MCOIMAPFolderStatus.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOIMAPFolderStatus.mm; sourceTree = ""; }; 9EF9AB0E175F30C20027FA3B /* MCIMAPFolderStatusOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPFolderStatusOperation.h; sourceTree = ""; }; - 9EF9AB10175F319A0027FA3B /* MCIMAPFolderStatusOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPFolderStatusOperation.cc; sourceTree = ""; }; + 9EF9AB10175F319A0027FA3B /* MCIMAPFolderStatusOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPFolderStatusOperation.cpp; sourceTree = ""; }; 9EF9AB16175F35C60027FA3B /* MCOIMAPFolderStatusOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOIMAPFolderStatusOperation.h; sourceTree = ""; }; 9EF9AB18175F36600027FA3B /* MCOIMAPFolderStatusOperation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOIMAPFolderStatusOperation.mm; sourceTree = ""; }; BD49963519FEC6DD000945BC /* ConvertUTF.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ConvertUTF.c; sourceTree = ""; }; @@ -1460,17 +1460,17 @@ BD62729A1A158DA000129AA8 /* MCDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCDefines.h; sourceTree = ""; }; BD62729B1A158DA900129AA8 /* MCWin32.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCWin32.cpp; sourceTree = ""; }; BD62729C1A158DA900129AA8 /* MCWin32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCWin32.h; sourceTree = ""; }; - BD637139177DFF080094121B /* MCLibetpan.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCLibetpan.cc; sourceTree = ""; }; + BD637139177DFF080094121B /* MCLibetpan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCLibetpan.cpp; sourceTree = ""; }; BD63713A177DFF080094121B /* MCLibetpan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCLibetpan.h; sourceTree = ""; }; C07AD057D3C8FBDC7AC95733 /* MCOIMAPSession.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOIMAPSession.mm; sourceTree = ""; }; C07AD44B013BB42A240B4F04 /* NSError+MCO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSError+MCO.h"; sourceTree = ""; }; C07ADFE43E22B38EFF23ADB5 /* NSError+MCO.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSError+MCO.mm"; sourceTree = ""; }; C60136941776B96600A5AF45 /* MCOSMTPOperation+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MCOSMTPOperation+Private.h"; sourceTree = ""; }; C60136951776C31000A5AF45 /* MCOPOPOperation+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MCOPOPOperation+Private.h"; sourceTree = ""; }; - C608167317759967001F1018 /* MCSMTPDisconnectOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCSMTPDisconnectOperation.cc; sourceTree = ""; }; + C608167317759967001F1018 /* MCSMTPDisconnectOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCSMTPDisconnectOperation.cpp; sourceTree = ""; }; C608167417759967001F1018 /* MCSMTPDisconnectOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCSMTPDisconnectOperation.h; sourceTree = ""; }; C6081678177625AD001F1018 /* MCOperationQueueCallback.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCOperationQueueCallback.h; sourceTree = ""; }; - C6081679177635D2001F1018 /* MCIMAPDisconnectOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPDisconnectOperation.cc; sourceTree = ""; }; + C6081679177635D2001F1018 /* MCIMAPDisconnectOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPDisconnectOperation.cpp; sourceTree = ""; }; C608167A177635D2001F1018 /* MCIMAPDisconnectOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPDisconnectOperation.h; sourceTree = ""; }; C608167F17766FC5001F1018 /* MCOIMAPBaseOperation+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MCOIMAPBaseOperation+Private.h"; sourceTree = ""; }; C623C58A16FD8C22001BBEFC /* MCOAbstractMessage+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MCOAbstractMessage+Private.h"; sourceTree = ""; }; @@ -1479,50 +1479,50 @@ C623C58E16FE6B45001BBEFC /* MCOIMAPOperation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOIMAPOperation.mm; sourceTree = ""; }; C623C59116FE750D001BBEFC /* MCOIMAPFolder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOIMAPFolder.h; sourceTree = ""; }; C623C59216FE750E001BBEFC /* MCOIMAPFolder.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOIMAPFolder.mm; sourceTree = ""; }; - C62C6ED216A2A0E600737497 /* MCIMAPIdentityOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPIdentityOperation.cc; sourceTree = ""; }; + C62C6ED216A2A0E600737497 /* MCIMAPIdentityOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPIdentityOperation.cpp; sourceTree = ""; }; C62C6ED316A2A0E600737497 /* MCIMAPIdentityOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPIdentityOperation.h; sourceTree = ""; }; - C62C6ED616A398FA00737497 /* MCIMAPFolderInfoOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPFolderInfoOperation.cc; sourceTree = ""; }; + C62C6ED616A398FA00737497 /* MCIMAPFolderInfoOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPFolderInfoOperation.cpp; sourceTree = ""; }; C62C6ED716A398FA00737497 /* MCIMAPFolderInfoOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPFolderInfoOperation.h; sourceTree = ""; }; - C62C6EED16A7B67600737497 /* MCPOPAsyncSession.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCPOPAsyncSession.cc; sourceTree = ""; }; + C62C6EED16A7B67600737497 /* MCPOPAsyncSession.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCPOPAsyncSession.cpp; sourceTree = ""; }; C62C6EEE16A7B67600737497 /* MCPOPAsyncSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCPOPAsyncSession.h; sourceTree = ""; }; - C62C6EF016A7C6DE00737497 /* MCPOPFetchHeaderOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCPOPFetchHeaderOperation.cc; sourceTree = ""; }; + C62C6EF016A7C6DE00737497 /* MCPOPFetchHeaderOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCPOPFetchHeaderOperation.cpp; sourceTree = ""; }; C62C6EF116A7C6DE00737497 /* MCPOPFetchHeaderOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCPOPFetchHeaderOperation.h; sourceTree = ""; }; - C62C6EF316A7C6E900737497 /* MCPOPFetchMessageOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCPOPFetchMessageOperation.cc; sourceTree = ""; }; + C62C6EF316A7C6E900737497 /* MCPOPFetchMessageOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCPOPFetchMessageOperation.cpp; sourceTree = ""; }; C62C6EF416A7C6E900737497 /* MCPOPFetchMessageOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCPOPFetchMessageOperation.h; sourceTree = ""; }; - C62C6EF616A7C6F500737497 /* MCPOPDeleteMessagesOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCPOPDeleteMessagesOperation.cc; sourceTree = ""; }; + C62C6EF616A7C6F500737497 /* MCPOPDeleteMessagesOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCPOPDeleteMessagesOperation.cpp; sourceTree = ""; }; C62C6EF716A7C6F500737497 /* MCPOPDeleteMessagesOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCPOPDeleteMessagesOperation.h; sourceTree = ""; }; - C62C6EF916A7C93F00737497 /* MCPOPOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCPOPOperation.cc; sourceTree = ""; }; + C62C6EF916A7C93F00737497 /* MCPOPOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCPOPOperation.cpp; sourceTree = ""; }; C62C6EFA16A7C94000737497 /* MCPOPOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCPOPOperation.h; sourceTree = ""; }; C62C6EFC16A7CA1500737497 /* MCPOPOperationCallback.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCPOPOperationCallback.h; sourceTree = ""; }; C62C6EFD16A7DD0300737497 /* MCAsyncPOP.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCAsyncPOP.h; sourceTree = ""; }; - C62C6F0416A7E54200737497 /* MCPOPFetchMessagesOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCPOPFetchMessagesOperation.cc; sourceTree = ""; }; + C62C6F0416A7E54200737497 /* MCPOPFetchMessagesOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCPOPFetchMessagesOperation.cpp; sourceTree = ""; }; C62C6F0516A7E54400737497 /* MCPOPFetchMessagesOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCPOPFetchMessagesOperation.h; sourceTree = ""; }; - C62C6F0816A8F57000737497 /* MCIMAPAsyncSession.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPAsyncSession.cc; sourceTree = ""; }; + C62C6F0816A8F57000737497 /* MCIMAPAsyncSession.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPAsyncSession.cpp; sourceTree = ""; }; C62C6F0916A8F57700737497 /* MCIMAPAsyncSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPAsyncSession.h; sourceTree = ""; }; - C63CD67716BDCDD400DB18F1 /* MCAddressDisplay.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCAddressDisplay.cc; sourceTree = ""; }; + C63CD67716BDCDD400DB18F1 /* MCAddressDisplay.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCAddressDisplay.cpp; sourceTree = ""; }; C63CD67816BDCDD400DB18F1 /* MCAddressDisplay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCAddressDisplay.h; sourceTree = ""; }; - C63CD67916BDCDD400DB18F1 /* MCDateFormatter.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCDateFormatter.cc; sourceTree = ""; }; + C63CD67916BDCDD400DB18F1 /* MCDateFormatter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCDateFormatter.cpp; sourceTree = ""; }; C63CD67A16BDCDD400DB18F1 /* MCDateFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCDateFormatter.h; sourceTree = ""; }; - C63CD67B16BDCDD400DB18F1 /* MCHTMLRenderer.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCHTMLRenderer.cc; sourceTree = ""; }; + C63CD67B16BDCDD400DB18F1 /* MCHTMLRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCHTMLRenderer.cpp; sourceTree = ""; }; C63CD67C16BDCDD400DB18F1 /* MCHTMLRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCHTMLRenderer.h; sourceTree = ""; }; - C63CD67D16BDCDD400DB18F1 /* MCSizeFormatter.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCSizeFormatter.cc; sourceTree = ""; }; + C63CD67D16BDCDD400DB18F1 /* MCSizeFormatter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCSizeFormatter.cpp; sourceTree = ""; }; C63CD67E16BDCDD400DB18F1 /* MCSizeFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCSizeFormatter.h; sourceTree = ""; }; - C63CD68416BE148B00DB18F1 /* MCHTMLRendererCallback.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCHTMLRendererCallback.cc; sourceTree = ""; }; + C63CD68416BE148B00DB18F1 /* MCHTMLRendererCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCHTMLRendererCallback.cpp; sourceTree = ""; }; C63CD68516BE148B00DB18F1 /* MCHTMLRendererCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCHTMLRendererCallback.h; sourceTree = ""; }; C63CD68716BE1AB600DB18F1 /* MCRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCRenderer.h; sourceTree = ""; }; - C63CD68F16BE566D00DB18F1 /* MCHTMLCleaner.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCHTMLCleaner.cc; sourceTree = ""; }; + C63CD68F16BE566D00DB18F1 /* MCHTMLCleaner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCHTMLCleaner.cpp; sourceTree = ""; }; C63CD69016BE566E00DB18F1 /* MCHTMLCleaner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCHTMLCleaner.h; sourceTree = ""; }; - C63D315A17C9155C00A4D993 /* MCIMAPIdentity.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPIdentity.cc; sourceTree = ""; }; + C63D315A17C9155C00A4D993 /* MCIMAPIdentity.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPIdentity.cpp; sourceTree = ""; }; C63D315B17C9155C00A4D993 /* MCIMAPIdentity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPIdentity.h; sourceTree = ""; }; C63D316017C92D8300A4D993 /* MCOIMAPIdentity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOIMAPIdentity.h; sourceTree = ""; }; C63D316117C92D8300A4D993 /* MCOIMAPIdentity.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOIMAPIdentity.mm; sourceTree = ""; }; C643F490189A3D59007EA2F7 /* NSSet+MCO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSSet+MCO.h"; sourceTree = ""; }; C643F491189A3D59007EA2F7 /* NSSet+MCO.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSSet+MCO.mm"; sourceTree = ""; }; - C64BB21F16E34DCA000DB34C /* MCIMAPSyncResult.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPSyncResult.cc; sourceTree = ""; }; + C64BB21F16E34DCA000DB34C /* MCIMAPSyncResult.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPSyncResult.cpp; sourceTree = ""; }; C64BB22016E34DCB000DB34C /* MCIMAPSyncResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPSyncResult.h; sourceTree = ""; }; - C64BB22916E5C0A3000DB34C /* MCIMAPCapabilityOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPCapabilityOperation.cc; sourceTree = ""; }; + C64BB22916E5C0A3000DB34C /* MCIMAPCapabilityOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPCapabilityOperation.cpp; sourceTree = ""; }; C64BB22A16E5C0A3000DB34C /* MCIMAPCapabilityOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPCapabilityOperation.h; sourceTree = ""; }; - C64BB22C16E5C1EE000DB34C /* MCIndexSet.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIndexSet.cc; sourceTree = ""; }; + C64BB22C16E5C1EE000DB34C /* MCIndexSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIndexSet.cpp; sourceTree = ""; }; C64BB22D16E5C1EE000DB34C /* MCIndexSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIndexSet.h; sourceTree = ""; }; C64BB23316EDAA17000DB34C /* MCOAbstractMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOAbstractMessage.h; sourceTree = ""; }; C64BB23416EDAA17000DB34C /* MCOAbstractMessage.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOAbstractMessage.mm; sourceTree = ""; }; @@ -1562,147 +1562,147 @@ C64BB26D16FD63F6000DB34C /* MCOConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOConstants.h; sourceTree = ""; }; C64EA537169E772200778456 /* libMailCore.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libMailCore.a; sourceTree = BUILT_PRODUCTS_DIR; }; C64EA68C169E847800778456 /* MCIMAPAsyncConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPAsyncConnection.h; sourceTree = ""; }; - C64EA68F169E847800778456 /* MCSMTPAsyncSession.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCSMTPAsyncSession.cc; sourceTree = ""; }; + C64EA68F169E847800778456 /* MCSMTPAsyncSession.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCSMTPAsyncSession.cpp; sourceTree = ""; }; C64EA690169E847800778456 /* MCSMTPAsyncSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCSMTPAsyncSession.h; sourceTree = ""; }; C64EA693169E847800778456 /* MCAbstract.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCAbstract.h; sourceTree = ""; }; - C64EA694169E847800778456 /* MCAbstractMessage.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = MCAbstractMessage.cc; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + C64EA694169E847800778456 /* MCAbstractMessage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = MCAbstractMessage.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C64EA695169E847800778456 /* MCAbstractMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = MCAbstractMessage.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; - C64EA696169E847800778456 /* MCAbstractMessagePart.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = MCAbstractMessagePart.cc; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + C64EA696169E847800778456 /* MCAbstractMessagePart.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = MCAbstractMessagePart.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C64EA697169E847800778456 /* MCAbstractMessagePart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCAbstractMessagePart.h; sourceTree = ""; }; - C64EA698169E847800778456 /* MCAbstractMultipart.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCAbstractMultipart.cc; sourceTree = ""; }; + C64EA698169E847800778456 /* MCAbstractMultipart.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCAbstractMultipart.cpp; sourceTree = ""; }; C64EA699169E847800778456 /* MCAbstractMultipart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCAbstractMultipart.h; sourceTree = ""; }; - C64EA69A169E847800778456 /* MCAbstractPart.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCAbstractPart.cc; sourceTree = ""; }; + C64EA69A169E847800778456 /* MCAbstractPart.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCAbstractPart.cpp; sourceTree = ""; }; C64EA69B169E847800778456 /* MCAbstractPart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCAbstractPart.h; sourceTree = ""; }; - C64EA69C169E847800778456 /* MCAddress.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCAddress.cc; sourceTree = ""; }; + C64EA69C169E847800778456 /* MCAddress.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCAddress.cpp; sourceTree = ""; }; C64EA69D169E847800778456 /* MCAddress.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCAddress.h; sourceTree = ""; }; C64EA69E169E847800778456 /* MCMessageConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCMessageConstants.h; sourceTree = ""; }; - C64EA69F169E847800778456 /* MCMessageHeader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCMessageHeader.cc; sourceTree = ""; }; + C64EA69F169E847800778456 /* MCMessageHeader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCMessageHeader.cpp; sourceTree = ""; }; C64EA6A0169E847800778456 /* MCMessageHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCMessageHeader.h; sourceTree = ""; }; - C64EA6A2169E847800778456 /* MCAutoreleasePool.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCAutoreleasePool.cc; sourceTree = ""; }; + C64EA6A2169E847800778456 /* MCAutoreleasePool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCAutoreleasePool.cpp; sourceTree = ""; }; C64EA6A3169E847800778456 /* MCAutoreleasePool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCAutoreleasePool.h; sourceTree = ""; }; C64EA6A4169E847800778456 /* MCBaseTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCBaseTypes.h; sourceTree = ""; }; - C64EA6A5169E847800778456 /* MCArray.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCArray.cc; sourceTree = ""; }; + C64EA6A5169E847800778456 /* MCArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCArray.cpp; sourceTree = ""; }; C64EA6A6169E847800778456 /* MCArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCArray.h; sourceTree = ""; }; C64EA6A7169E847800778456 /* MCAssert.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = MCAssert.c; sourceTree = ""; }; C64EA6A8169E847800778456 /* MCAssert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCAssert.h; sourceTree = ""; }; - C64EA6A9169E847800778456 /* MCData.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCData.cc; sourceTree = ""; }; + C64EA6A9169E847800778456 /* MCData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCData.cpp; sourceTree = ""; }; C64EA6AA169E847800778456 /* MCData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCData.h; sourceTree = ""; }; - C64EA6AB169E847800778456 /* MCHash.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCHash.cc; sourceTree = ""; }; + C64EA6AB169E847800778456 /* MCHash.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCHash.cpp; sourceTree = ""; }; C64EA6AC169E847800778456 /* MCHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCHash.h; sourceTree = ""; }; - C64EA6AD169E847800778456 /* MCHashMap.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCHashMap.cc; sourceTree = ""; }; + C64EA6AD169E847800778456 /* MCHashMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCHashMap.cpp; sourceTree = ""; }; C64EA6AE169E847800778456 /* MCHashMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCHashMap.h; sourceTree = ""; }; C64EA6AF169E847800778456 /* MCLog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCLog.cpp; sourceTree = ""; }; C64EA6B0169E847800778456 /* MCLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCLog.h; sourceTree = ""; }; - C64EA6B1169E847800778456 /* MCObject.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCObject.cc; sourceTree = ""; }; + C64EA6B1169E847800778456 /* MCObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCObject.cpp; sourceTree = ""; }; C64EA6B2169E847800778456 /* MCObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCObject.h; sourceTree = ""; }; - C64EA6B3169E847800778456 /* MCRange.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCRange.cc; sourceTree = ""; }; + C64EA6B3169E847800778456 /* MCRange.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCRange.cpp; sourceTree = ""; }; C64EA6B4169E847800778456 /* MCRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCRange.h; sourceTree = ""; }; - C64EA6B5169E847800778456 /* MCSet.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCSet.cc; sourceTree = ""; }; + C64EA6B5169E847800778456 /* MCSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCSet.cpp; sourceTree = ""; }; C64EA6B6169E847800778456 /* MCSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCSet.h; sourceTree = ""; }; - C64EA6B7169E847800778456 /* MCString.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCString.cc; sourceTree = ""; }; + C64EA6B7169E847800778456 /* MCString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCString.cpp; sourceTree = ""; }; C64EA6B8169E847800778456 /* MCString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCString.h; sourceTree = ""; }; C64EA6B9169E847800778456 /* MCUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCUtils.h; sourceTree = ""; }; - C64EA6BA169E847800778456 /* MCValue.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCValue.cc; sourceTree = ""; }; + C64EA6BA169E847800778456 /* MCValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCValue.cpp; sourceTree = ""; }; C64EA6BB169E847800778456 /* MCValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCValue.h; sourceTree = ""; }; C64EA6BC169E847800778456 /* MCMainThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCMainThread.h; sourceTree = ""; }; C64EA6BD169E847800778456 /* MCMainThreadMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCMainThreadMac.mm; sourceTree = ""; }; - C64EA6BE169E847800778456 /* MCOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCOperation.cc; sourceTree = ""; }; + C64EA6BE169E847800778456 /* MCOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCOperation.cpp; sourceTree = ""; }; C64EA6BF169E847800778456 /* MCOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOperation.h; sourceTree = ""; }; C64EA6C0169E847800778456 /* MCOperationCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOperationCallback.h; sourceTree = ""; }; - C64EA6C1169E847800778456 /* MCOperationQueue.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCOperationQueue.cc; sourceTree = ""; }; + C64EA6C1169E847800778456 /* MCOperationQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCOperationQueue.cpp; sourceTree = ""; }; C64EA6C2169E847800778456 /* MCOperationQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOperationQueue.h; sourceTree = ""; }; C64EA6C4169E847800778456 /* MCIMAP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAP.h; sourceTree = ""; }; - C64EA6C5169E847800778456 /* MCIMAPFolder.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPFolder.cc; sourceTree = ""; }; + C64EA6C5169E847800778456 /* MCIMAPFolder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPFolder.cpp; sourceTree = ""; }; C64EA6C6169E847800778456 /* MCIMAPFolder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPFolder.h; sourceTree = ""; }; - C64EA6C7169E847800778456 /* MCIMAPMessage.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPMessage.cc; sourceTree = ""; }; + C64EA6C7169E847800778456 /* MCIMAPMessage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPMessage.cpp; sourceTree = ""; }; C64EA6C8169E847800778456 /* MCIMAPMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPMessage.h; sourceTree = ""; }; - C64EA6C9169E847800778456 /* MCIMAPMessagePart.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPMessagePart.cc; sourceTree = ""; }; + C64EA6C9169E847800778456 /* MCIMAPMessagePart.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPMessagePart.cpp; sourceTree = ""; }; C64EA6CA169E847800778456 /* MCIMAPMessagePart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPMessagePart.h; sourceTree = ""; }; - C64EA6CB169E847800778456 /* MCIMAPMultipart.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPMultipart.cc; sourceTree = ""; }; + C64EA6CB169E847800778456 /* MCIMAPMultipart.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPMultipart.cpp; sourceTree = ""; }; C64EA6CC169E847800778456 /* MCIMAPMultipart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPMultipart.h; sourceTree = ""; }; - C64EA6CD169E847800778456 /* MCIMAPNamespace.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPNamespace.cc; sourceTree = ""; }; + C64EA6CD169E847800778456 /* MCIMAPNamespace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPNamespace.cpp; sourceTree = ""; }; C64EA6CE169E847800778456 /* MCIMAPNamespace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPNamespace.h; sourceTree = ""; }; - C64EA6CF169E847800778456 /* MCIMAPNamespaceItem.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPNamespaceItem.cc; sourceTree = ""; }; + C64EA6CF169E847800778456 /* MCIMAPNamespaceItem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPNamespaceItem.cpp; sourceTree = ""; }; C64EA6D0169E847800778456 /* MCIMAPNamespaceItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPNamespaceItem.h; sourceTree = ""; }; - C64EA6D1169E847800778456 /* MCIMAPPart.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPPart.cc; sourceTree = ""; }; + C64EA6D1169E847800778456 /* MCIMAPPart.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPPart.cpp; sourceTree = ""; }; C64EA6D2169E847800778456 /* MCIMAPPart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPPart.h; sourceTree = ""; }; C64EA6D3169E847800778456 /* MCIMAPProgressCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPProgressCallback.h; sourceTree = ""; }; - C64EA6D4169E847800778456 /* MCIMAPSearchExpression.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPSearchExpression.cc; sourceTree = ""; }; + C64EA6D4169E847800778456 /* MCIMAPSearchExpression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPSearchExpression.cpp; sourceTree = ""; }; C64EA6D5169E847800778456 /* MCIMAPSearchExpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPSearchExpression.h; sourceTree = ""; }; - C64EA6D6169E847800778456 /* MCIMAPSession.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPSession.cc; sourceTree = ""; }; + C64EA6D6169E847800778456 /* MCIMAPSession.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPSession.cpp; sourceTree = ""; }; C64EA6D7169E847800778456 /* MCIMAPSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPSession.h; sourceTree = ""; }; C64EA6D9169E847800778456 /* MCPOP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCPOP.h; sourceTree = ""; }; - C64EA6DA169E847800778456 /* MCPOPMessageInfo.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCPOPMessageInfo.cc; sourceTree = ""; }; + C64EA6DA169E847800778456 /* MCPOPMessageInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCPOPMessageInfo.cpp; sourceTree = ""; }; C64EA6DB169E847800778456 /* MCPOPMessageInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCPOPMessageInfo.h; sourceTree = ""; }; C64EA6DC169E847800778456 /* MCPOPProgressCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCPOPProgressCallback.h; sourceTree = ""; }; - C64EA6DD169E847800778456 /* MCPOPSession.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCPOPSession.cc; sourceTree = ""; }; + C64EA6DD169E847800778456 /* MCPOPSession.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCPOPSession.cpp; sourceTree = ""; }; C64EA6DE169E847800778456 /* MCPOPSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCPOPSession.h; sourceTree = ""; }; - C64EA6E0169E847800778456 /* MCAttachment.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCAttachment.cc; sourceTree = ""; }; + C64EA6E0169E847800778456 /* MCAttachment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCAttachment.cpp; sourceTree = ""; }; C64EA6E1169E847800778456 /* MCAttachment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCAttachment.h; sourceTree = ""; }; - C64EA6E2169E847800778456 /* MCMessageBuilder.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCMessageBuilder.cc; sourceTree = ""; }; + C64EA6E2169E847800778456 /* MCMessageBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCMessageBuilder.cpp; sourceTree = ""; }; C64EA6E3169E847800778456 /* MCMessageBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCMessageBuilder.h; sourceTree = ""; }; - C64EA6E4169E847800778456 /* MCMessageParser.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCMessageParser.cc; sourceTree = ""; }; + C64EA6E4169E847800778456 /* MCMessageParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCMessageParser.cpp; sourceTree = ""; }; C64EA6E5169E847800778456 /* MCMessageParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCMessageParser.h; sourceTree = ""; }; - C64EA6E6169E847800778456 /* MCMessagePart.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCMessagePart.cc; sourceTree = ""; }; + C64EA6E6169E847800778456 /* MCMessagePart.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCMessagePart.cpp; sourceTree = ""; }; C64EA6E7169E847800778456 /* MCMessagePart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCMessagePart.h; sourceTree = ""; }; - C64EA6E8169E847800778456 /* MCMultipart.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCMultipart.cc; sourceTree = ""; }; + C64EA6E8169E847800778456 /* MCMultipart.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCMultipart.cpp; sourceTree = ""; }; C64EA6E9169E847800778456 /* MCMultipart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCMultipart.h; sourceTree = ""; }; C64EA6EA169E847800778456 /* MCRFC822.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCRFC822.h; sourceTree = ""; }; C64EA6EC169E847800778456 /* MCSMTP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCSMTP.h; sourceTree = ""; }; C64EA6ED169E847800778456 /* MCSMTPProgressCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCSMTPProgressCallback.h; sourceTree = ""; }; - C64EA6EE169E847800778456 /* MCSMTPSession.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCSMTPSession.cc; sourceTree = ""; }; + C64EA6EE169E847800778456 /* MCSMTPSession.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCSMTPSession.cpp; sourceTree = ""; }; C64EA6EF169E847800778456 /* MCSMTPSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCSMTPSession.h; sourceTree = ""; }; C64EA782169F23AB00778456 /* MCCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCCore.h; sourceTree = ""; }; C64EA78C169F259200778456 /* tests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tests; sourceTree = BUILT_PRODUCTS_DIR; }; C64EA78F169F259200778456 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - C64EA79C169F29A700778456 /* MCSMTPSendWithDataOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCSMTPSendWithDataOperation.cc; sourceTree = ""; }; + C64EA79C169F29A700778456 /* MCSMTPSendWithDataOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCSMTPSendWithDataOperation.cpp; sourceTree = ""; }; C64EA79D169F29A700778456 /* MCSMTPSendWithDataOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCSMTPSendWithDataOperation.h; sourceTree = ""; }; C64EA7A4169F2A3E00778456 /* MailCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MailCore.h; sourceTree = ""; }; C64EA7AA16A00AF600778456 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; C64EA7B016A00BBB00778456 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; }; - C64EA7D816A1386500778456 /* MCSMTPOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCSMTPOperation.cc; sourceTree = ""; }; + C64EA7D816A1386500778456 /* MCSMTPOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCSMTPOperation.cpp; sourceTree = ""; }; C64EA7D916A1386600778456 /* MCSMTPOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCSMTPOperation.h; sourceTree = ""; }; C64EA7E116A1425400778456 /* MCSMTPOperationCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCSMTPOperationCallback.h; sourceTree = ""; }; C64EA7E316A149EF00778456 /* MCAsyncSMTP.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCAsyncSMTP.h; sourceTree = ""; }; C64EA7E416A14A4500778456 /* MCAsync.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCAsync.h; sourceTree = ""; }; - C64EA7E816A154B000778456 /* MCSMTPCheckAccountOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCSMTPCheckAccountOperation.cc; sourceTree = ""; }; + C64EA7E816A154B000778456 /* MCSMTPCheckAccountOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCSMTPCheckAccountOperation.cpp; sourceTree = ""; }; C64EA7E916A154B200778456 /* MCSMTPCheckAccountOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCSMTPCheckAccountOperation.h; sourceTree = ""; }; - C64EA7EF16A15A4D00778456 /* MCIMAPOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPOperation.cc; sourceTree = ""; }; + C64EA7EF16A15A4D00778456 /* MCIMAPOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPOperation.cpp; sourceTree = ""; }; C64EA7F016A15A4D00778456 /* MCIMAPOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPOperation.h; sourceTree = ""; }; C64EA7F416A15A6300778456 /* MCIMAPOperationCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPOperationCallback.h; sourceTree = ""; }; - C64EA7F616A15A7800778456 /* MCIMAPCheckAccountOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPCheckAccountOperation.cc; sourceTree = ""; }; + C64EA7F616A15A7800778456 /* MCIMAPCheckAccountOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPCheckAccountOperation.cpp; sourceTree = ""; }; C64EA7F716A15A7800778456 /* MCIMAPCheckAccountOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPCheckAccountOperation.h; sourceTree = ""; }; C64EA7F916A15A9200778456 /* MCAsyncIMAP.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCAsyncIMAP.h; sourceTree = ""; }; - C64EA7FA16A2959700778456 /* MCIMAPFetchFoldersOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPFetchFoldersOperation.cc; sourceTree = ""; }; + C64EA7FA16A2959700778456 /* MCIMAPFetchFoldersOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPFetchFoldersOperation.cpp; sourceTree = ""; }; C64EA7FB16A2959700778456 /* MCIMAPFetchFoldersOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPFetchFoldersOperation.h; sourceTree = ""; }; - C64EA7FD16A295B500778456 /* MCIMAPAsyncConnection.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPAsyncConnection.cc; sourceTree = ""; }; - C64EA80016A295E200778456 /* MCIMAPRenameFolderOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPRenameFolderOperation.cc; sourceTree = ""; }; + C64EA7FD16A295B500778456 /* MCIMAPAsyncConnection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPAsyncConnection.cpp; sourceTree = ""; }; + C64EA80016A295E200778456 /* MCIMAPRenameFolderOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPRenameFolderOperation.cpp; sourceTree = ""; }; C64EA80116A295E300778456 /* MCIMAPRenameFolderOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPRenameFolderOperation.h; sourceTree = ""; }; - C64EA80316A2997B00778456 /* MCIMAPDeleteFolderOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPDeleteFolderOperation.cc; sourceTree = ""; }; + C64EA80316A2997B00778456 /* MCIMAPDeleteFolderOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPDeleteFolderOperation.cpp; sourceTree = ""; }; C64EA80416A2997D00778456 /* MCIMAPDeleteFolderOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPDeleteFolderOperation.h; sourceTree = ""; }; - C64EA80616A2999800778456 /* MCIMAPCreateFolderOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPCreateFolderOperation.cc; sourceTree = ""; }; + C64EA80616A2999800778456 /* MCIMAPCreateFolderOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPCreateFolderOperation.cpp; sourceTree = ""; }; C64EA80716A2999900778456 /* MCIMAPCreateFolderOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPCreateFolderOperation.h; sourceTree = ""; }; - C64EA80916A299B500778456 /* MCIMAPSubscribeFolderOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPSubscribeFolderOperation.cc; sourceTree = ""; }; + C64EA80916A299B500778456 /* MCIMAPSubscribeFolderOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPSubscribeFolderOperation.cpp; sourceTree = ""; }; C64EA80A16A299B600778456 /* MCIMAPSubscribeFolderOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPSubscribeFolderOperation.h; sourceTree = ""; }; - C64EA80F16A299EA00778456 /* MCIMAPAppendMessageOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPAppendMessageOperation.cc; sourceTree = ""; }; + C64EA80F16A299EA00778456 /* MCIMAPAppendMessageOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPAppendMessageOperation.cpp; sourceTree = ""; }; C64EA81016A299EB00778456 /* MCIMAPAppendMessageOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPAppendMessageOperation.h; sourceTree = ""; }; - C64EA81216A29A0A00778456 /* MCIMAPCopyMessagesOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPCopyMessagesOperation.cc; sourceTree = ""; }; + C64EA81216A29A0A00778456 /* MCIMAPCopyMessagesOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPCopyMessagesOperation.cpp; sourceTree = ""; }; C64EA81316A29A1000778456 /* MCIMAPCopyMessagesOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPCopyMessagesOperation.h; sourceTree = ""; }; - C64EA81516A29A8500778456 /* MCIMAPExpungeOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPExpungeOperation.cc; sourceTree = ""; }; + C64EA81516A29A8500778456 /* MCIMAPExpungeOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPExpungeOperation.cpp; sourceTree = ""; }; C64EA81616A29A8600778456 /* MCIMAPExpungeOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPExpungeOperation.h; sourceTree = ""; }; - C64EA81816A29AD400778456 /* MCIMAPFetchMessagesOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPFetchMessagesOperation.cc; sourceTree = ""; }; + C64EA81816A29AD400778456 /* MCIMAPFetchMessagesOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPFetchMessagesOperation.cpp; sourceTree = ""; }; C64EA81916A29ADB00778456 /* MCIMAPFetchMessagesOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPFetchMessagesOperation.h; sourceTree = ""; }; - C64EA81B16A29DC100778456 /* MCIMAPFetchContentOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPFetchContentOperation.cc; sourceTree = ""; }; + C64EA81B16A29DC100778456 /* MCIMAPFetchContentOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPFetchContentOperation.cpp; sourceTree = ""; }; C64EA81C16A29DC400778456 /* MCIMAPFetchContentOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPFetchContentOperation.h; sourceTree = ""; }; - C64EA81E16A29E3D00778456 /* MCIMAPStoreFlagsOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPStoreFlagsOperation.cc; sourceTree = ""; }; + C64EA81E16A29E3D00778456 /* MCIMAPStoreFlagsOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPStoreFlagsOperation.cpp; sourceTree = ""; }; C64EA81F16A29E3F00778456 /* MCIMAPStoreFlagsOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPStoreFlagsOperation.h; sourceTree = ""; }; - C64EA82116A29E4F00778456 /* MCIMAPStoreLabelsOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPStoreLabelsOperation.cc; sourceTree = ""; }; + C64EA82116A29E4F00778456 /* MCIMAPStoreLabelsOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPStoreLabelsOperation.cpp; sourceTree = ""; }; C64EA82216A29E5200778456 /* MCIMAPStoreLabelsOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPStoreLabelsOperation.h; sourceTree = ""; }; - C64EA82416A29EE000778456 /* MCIMAPSearchOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPSearchOperation.cc; sourceTree = ""; }; + C64EA82416A29EE000778456 /* MCIMAPSearchOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPSearchOperation.cpp; sourceTree = ""; }; C64EA82516A29EE300778456 /* MCIMAPSearchOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPSearchOperation.h; sourceTree = ""; }; - C64EA82716A29EF400778456 /* MCIMAPIdleOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPIdleOperation.cc; sourceTree = ""; }; + C64EA82716A29EF400778456 /* MCIMAPIdleOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPIdleOperation.cpp; sourceTree = ""; }; C64EA82816A29F0300778456 /* MCIMAPIdleOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPIdleOperation.h; sourceTree = ""; }; - C64EA82A16A29FAA00778456 /* MCIMAPFetchNamespaceOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPFetchNamespaceOperation.cc; sourceTree = ""; }; + C64EA82A16A29FAA00778456 /* MCIMAPFetchNamespaceOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPFetchNamespaceOperation.cpp; sourceTree = ""; }; C64EA82B16A2A01400778456 /* MCIMAPFetchNamespaceOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPFetchNamespaceOperation.h; sourceTree = ""; }; C64FF38F16B3C13000F8C162 /* MCOObjectWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOObjectWrapper.h; sourceTree = ""; }; C64FF39016B3C13000F8C162 /* MCOObjectWrapper.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOObjectWrapper.mm; sourceTree = ""; }; @@ -1711,7 +1711,7 @@ C67597C117A8D65000DA69DF /* MCBase64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = MCBase64.c; sourceTree = ""; }; C67597C417A8D66000DA69DF /* MCBase64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCBase64.h; sourceTree = ""; }; C68B2AEB1778A589005E61EF /* MCConnectionLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCConnectionLogger.h; sourceTree = ""; }; - C68B2AF517797389005E61EF /* MCConnectionLoggerUtils.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCConnectionLoggerUtils.cc; sourceTree = ""; }; + C68B2AF517797389005E61EF /* MCConnectionLoggerUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCConnectionLoggerUtils.cpp; sourceTree = ""; }; C68B2AF617797389005E61EF /* MCConnectionLoggerUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCConnectionLoggerUtils.h; sourceTree = ""; }; C69BA85917DEFCCB00D601B7 /* NSIndexSet+MCO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSIndexSet+MCO.h"; sourceTree = ""; }; C69BA85A17DEFCCB00D601B7 /* NSIndexSet+MCO.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSIndexSet+MCO.m"; sourceTree = ""; }; @@ -1745,7 +1745,7 @@ C6A81BFB170781BC00882C15 /* MCOPOP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOPOP.h; sourceTree = ""; }; C6A81BFE1707CEE400882C15 /* MCOPOPMessageInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOPOPMessageInfo.h; sourceTree = ""; }; C6A81BFF1707CEE500882C15 /* MCOPOPMessageInfo.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOPOPMessageInfo.mm; sourceTree = ""; }; - C6AC10FE17114DAF00B715B7 /* MCPOPCheckAccountOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCPOPCheckAccountOperation.cc; sourceTree = ""; }; + C6AC10FE17114DAF00B715B7 /* MCPOPCheckAccountOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCPOPCheckAccountOperation.cpp; sourceTree = ""; }; C6AC10FF17114DAF00B715B7 /* MCPOPCheckAccountOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCPOPCheckAccountOperation.h; sourceTree = ""; }; C6AC1131171249DF00B715B7 /* MCLibetpanTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCLibetpanTypes.h; sourceTree = ""; }; C6B5AE0219F630B3001352A6 /* unittest.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = unittest.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1773,11 +1773,11 @@ C6CF62B6175324CE006398B9 /* MCONetService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCONetService.h; sourceTree = ""; }; C6CF62B7175324CE006398B9 /* MCONetService.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCONetService.mm; sourceTree = ""; }; C6CF62B8175324CE006398B9 /* MCOProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOProvider.h; sourceTree = ""; }; - C6CF62BF175324F0006398B9 /* MCMailProvider.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCMailProvider.cc; sourceTree = ""; }; + C6CF62BF175324F0006398B9 /* MCMailProvider.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCMailProvider.cpp; sourceTree = ""; }; C6CF62C0175324F0006398B9 /* MCMailProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCMailProvider.h; sourceTree = ""; }; - C6CF62C1175324F0006398B9 /* MCMailProvidersManager.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCMailProvidersManager.cc; sourceTree = ""; }; + C6CF62C1175324F0006398B9 /* MCMailProvidersManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCMailProvidersManager.cpp; sourceTree = ""; }; C6CF62C2175324F0006398B9 /* MCMailProvidersManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCMailProvidersManager.h; sourceTree = ""; }; - C6CF62C3175324F0006398B9 /* MCNetService.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCNetService.cc; sourceTree = ""; }; + C6CF62C3175324F0006398B9 /* MCNetService.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCNetService.cpp; sourceTree = ""; }; C6CF62C4175324F0006398B9 /* MCNetService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCNetService.h; sourceTree = ""; }; C6CF62C5175324F0006398B9 /* MCProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCProvider.h; sourceTree = ""; }; C6D42C1916AE03D6002BB4F9 /* NSData+MCO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+MCO.h"; sourceTree = ""; }; @@ -1786,17 +1786,17 @@ C6D42C1C16AE03D6002BB4F9 /* NSString+MCO.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSString+MCO.mm"; sourceTree = ""; }; C6D4FD3E19FB7534001F7E01 /* MCMessageParserMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCMessageParserMac.mm; sourceTree = ""; }; C6D4FD4219FB7DAA001F7E01 /* MCDataMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCDataMac.mm; sourceTree = ""; }; - C6D6F7F7171E595D006F5B28 /* MCJSON.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCJSON.cc; sourceTree = ""; }; + C6D6F7F7171E595D006F5B28 /* MCJSON.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCJSON.cpp; sourceTree = ""; }; C6D6F7F8171E595D006F5B28 /* MCJSON.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCJSON.h; sourceTree = ""; }; - C6D6F950171E5CB8006F5B28 /* MCMD5.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCMD5.cc; sourceTree = ""; }; + C6D6F950171E5CB8006F5B28 /* MCMD5.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCMD5.cpp; sourceTree = ""; }; C6D6F951171E5CB8006F5B28 /* MCMD5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCMD5.h; sourceTree = ""; }; - C6D6F952171E5CB8006F5B28 /* MCNull.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCNull.cc; sourceTree = ""; }; + C6D6F952171E5CB8006F5B28 /* MCNull.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCNull.cpp; sourceTree = ""; }; C6D6F953171E5CB8006F5B28 /* MCNull.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCNull.h; sourceTree = ""; }; - C6D6F965171FCF9F006F5B28 /* MCJSONParser.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCJSONParser.cc; sourceTree = ""; }; + C6D6F965171FCF9F006F5B28 /* MCJSONParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCJSONParser.cpp; sourceTree = ""; }; C6D6F966171FCF9F006F5B28 /* MCJSONParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCJSONParser.h; sourceTree = ""; }; C6D6F9691720F8F4006F5B28 /* MCICUTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCICUTypes.h; sourceTree = ""; }; C6D6F96D1721028D006F5B28 /* MCIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIterator.h; sourceTree = ""; }; - C6E665AA1796500B0063F2CF /* MCZip.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCZip.cc; sourceTree = ""; }; + C6E665AA1796500B0063F2CF /* MCZip.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCZip.cpp; sourceTree = ""; }; C6E665AB1796500B0063F2CF /* MCZip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCZip.h; sourceTree = ""; }; C6E665AD1796500B0063F2CF /* ioapi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioapi.c; sourceTree = ""; }; C6E665AE1796500B0063F2CF /* ioapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ioapi.h; sourceTree = ""; }; @@ -1813,7 +1813,7 @@ C6EB310016B8E6E50091F4F1 /* NSObject+MCO.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSObject+MCO.mm"; sourceTree = ""; }; C6ED6D1917A1919500A4A14C /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; C6ED6D1C17A191BF00A4A14C /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; - C6EFFBC6182BBF5700CFF656 /* MCIMAPMultiDisconnectOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPMultiDisconnectOperation.cc; sourceTree = ""; }; + C6EFFBC6182BBF5700CFF656 /* MCIMAPMultiDisconnectOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPMultiDisconnectOperation.cpp; sourceTree = ""; }; C6EFFBC7182BBF5700CFF656 /* MCIMAPMultiDisconnectOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPMultiDisconnectOperation.h; sourceTree = ""; }; C6EFFBCA1833334900CFF656 /* MCOIMAPMultiDisconnectOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOIMAPMultiDisconnectOperation.h; sourceTree = ""; }; C6EFFBCB1833334900CFF656 /* MCOIMAPMultiDisconnectOperation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOIMAPMultiDisconnectOperation.mm; sourceTree = ""; }; @@ -1860,15 +1860,15 @@ C6F61F9E17016EA00073032E /* MCOIMAPFolderInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCOIMAPFolderInfo.m; sourceTree = ""; }; C6F61FB31702AB2A0073032E /* MCOIMAPBaseOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOIMAPBaseOperation.h; sourceTree = ""; }; C6F61FB41702AB2F0073032E /* MCOIMAPBaseOperation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOIMAPBaseOperation.mm; sourceTree = ""; }; - C6F7B19D17A1C15200BE78BB /* MCCertificateUtils.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCCertificateUtils.cc; sourceTree = ""; }; + C6F7B19D17A1C15200BE78BB /* MCCertificateUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCCertificateUtils.cpp; sourceTree = ""; }; C6F7B19E17A1C15200BE78BB /* MCCertificateUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCCertificateUtils.h; sourceTree = ""; }; - DA0F1C79177C07B300F0D3B4 /* MCIMAPMessageRenderingOperation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPMessageRenderingOperation.cc; sourceTree = ""; }; + DA0F1C79177C07B300F0D3B4 /* MCIMAPMessageRenderingOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPMessageRenderingOperation.cpp; sourceTree = ""; }; DA0F1C7A177C07B300F0D3B4 /* MCIMAPMessageRenderingOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPMessageRenderingOperation.h; sourceTree = ""; }; DA89896B178A47D200F6D90A /* MCOIMAPMessageRenderingOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOIMAPMessageRenderingOperation.h; sourceTree = ""; }; DA89896C178A47D200F6D90A /* MCOIMAPMessageRenderingOperation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOIMAPMessageRenderingOperation.mm; sourceTree = ""; }; - DAACAD4F17886807000B4517 /* MCHTMLRendererIMAPDataCallback.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCHTMLRendererIMAPDataCallback.cc; sourceTree = ""; }; + DAACAD4F17886807000B4517 /* MCHTMLRendererIMAPDataCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCHTMLRendererIMAPDataCallback.cpp; sourceTree = ""; }; DAACAD5017886807000B4517 /* MCHTMLRendererIMAPDataCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCHTMLRendererIMAPDataCallback.h; sourceTree = ""; }; - DAD28C891783CFFC00F2BB8F /* MCHTMLBodyRendererTemplateCallback.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCHTMLBodyRendererTemplateCallback.cc; sourceTree = ""; }; + DAD28C891783CFFC00F2BB8F /* MCHTMLBodyRendererTemplateCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCHTMLBodyRendererTemplateCallback.cpp; sourceTree = ""; }; DAD28C8A1783CFFC00F2BB8F /* MCHTMLBodyRendererTemplateCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCHTMLBodyRendererTemplateCallback.h; sourceTree = ""; }; F87F190816BB62690012652F /* MCOIMAPFetchFoldersOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOIMAPFetchFoldersOperation.h; sourceTree = ""; }; F87F190B16BB62B00012652F /* MCOIMAPFetchFoldersOperation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOIMAPFetchFoldersOperation.mm; sourceTree = ""; }; @@ -1949,10 +1949,10 @@ isa = PBXGroup; children = ( 8491899C18C93F92002063A3 /* MCNNTP.h */, - 849189A918C94986002063A3 /* MCNNTPGroupInfo.cc */, + 849189A918C94986002063A3 /* MCNNTPGroupInfo.cpp */, 849189AA18C94986002063A3 /* MCNNTPGroupInfo.h */, 84D73732199BF754005124E5 /* MCNNTPProgressCallback.h */, - 8491899F18C93FB7002063A3 /* MCNNTPSession.cc */, + 8491899F18C93FB7002063A3 /* MCNNTPSession.cpp */, 849189A018C93FB7002063A3 /* MCNNTPSession.h */, ); name = nntp; @@ -1961,11 +1961,11 @@ 84AF9E72172DACC900E60AA3 /* provider */ = { isa = PBXGroup; children = ( - C6CF62BF175324F0006398B9 /* MCMailProvider.cc */, + C6CF62BF175324F0006398B9 /* MCMailProvider.cpp */, C6CF62C0175324F0006398B9 /* MCMailProvider.h */, - C6CF62C1175324F0006398B9 /* MCMailProvidersManager.cc */, + C6CF62C1175324F0006398B9 /* MCMailProvidersManager.cpp */, C6CF62C2175324F0006398B9 /* MCMailProvidersManager.h */, - C6CF62C3175324F0006398B9 /* MCNetService.cc */, + C6CF62C3175324F0006398B9 /* MCNetService.cpp */, C6CF62C4175324F0006398B9 /* MCNetService.h */, C6CF62C5175324F0006398B9 /* MCProvider.h */, ); @@ -1990,25 +1990,25 @@ isa = PBXGroup; children = ( 84D73729199BF63F005124E5 /* MCAsyncNNTP.h */, - 84D7372A199BF66C005124E5 /* MCNNTPAsyncSession.cc */, + 84D7372A199BF66C005124E5 /* MCNNTPAsyncSession.cpp */, 84D7372B199BF66C005124E5 /* MCNNTPAsyncSession.h */, - 84D73735199BF7F2005124E5 /* MCNNTPFetchHeaderOperation.cc */, + 84D73735199BF7F2005124E5 /* MCNNTPFetchHeaderOperation.cpp */, 84D73736199BF7F2005124E5 /* MCNNTPFetchHeaderOperation.h */, - 84D7373B199BF83B005124E5 /* MCNNTPFetchArticleOperation.cc */, + 84D7373B199BF83B005124E5 /* MCNNTPFetchArticleOperation.cpp */, 84D7373C199BF83B005124E5 /* MCNNTPFetchArticleOperation.h */, - 84D7375A199BFDCA005124E5 /* MCNNTPListNewsgroupsOperation.cc */, + 84D7375A199BFDCA005124E5 /* MCNNTPListNewsgroupsOperation.cpp */, 84D7375B199BFDCA005124E5 /* MCNNTPListNewsgroupsOperation.h */, - 84CFA98519F7159700FE35D2 /* MCNNTPFetchOverviewOperation.cc */, + 84CFA98519F7159700FE35D2 /* MCNNTPFetchOverviewOperation.cpp */, 84CFA98619F7159700FE35D2 /* MCNNTPFetchOverviewOperation.h */, - 84D73740199BF963005124E5 /* MCNNTPFetchAllArticlesOperation.cc */, + 84D73740199BF963005124E5 /* MCNNTPFetchAllArticlesOperation.cpp */, 84D73741199BF963005124E5 /* MCNNTPFetchAllArticlesOperation.h */, - 84CFA98D19F724E500FE35D2 /* MCNNTPFetchServerTimeOperation.cc */, + 84CFA98D19F724E500FE35D2 /* MCNNTPFetchServerTimeOperation.cpp */, 84CFA98E19F724E500FE35D2 /* MCNNTPFetchServerTimeOperation.h */, - 84D73744199BFA8C005124E5 /* MCNNTPCheckAccountOperation.cc */, + 84D73744199BFA8C005124E5 /* MCNNTPCheckAccountOperation.cpp */, 84D73745199BFA8C005124E5 /* MCNNTPCheckAccountOperation.h */, - 84D73756199BFC8A005124E5 /* MCNNTPDisconnectOperation.cc */, + 84D73756199BFC8A005124E5 /* MCNNTPDisconnectOperation.cpp */, 84D73757199BFC8A005124E5 /* MCNNTPDisconnectOperation.h */, - 84D7372E199BF704005124E5 /* MCNNTPOperation.cc */, + 84D7372E199BF704005124E5 /* MCNNTPOperation.cpp */, 84D7372F199BF704005124E5 /* MCNNTPOperation.h */, 84D7373F199BF887005124E5 /* MCNNTPOperationCallback.h */, ); @@ -2047,20 +2047,20 @@ C63CD67616BDCDD300DB18F1 /* renderer */ = { isa = PBXGroup; children = ( - C63CD67716BDCDD400DB18F1 /* MCAddressDisplay.cc */, + C63CD67716BDCDD400DB18F1 /* MCAddressDisplay.cpp */, C63CD67816BDCDD400DB18F1 /* MCAddressDisplay.h */, - C63CD67916BDCDD400DB18F1 /* MCDateFormatter.cc */, + C63CD67916BDCDD400DB18F1 /* MCDateFormatter.cpp */, C63CD67A16BDCDD400DB18F1 /* MCDateFormatter.h */, - C63CD67D16BDCDD400DB18F1 /* MCSizeFormatter.cc */, + C63CD67D16BDCDD400DB18F1 /* MCSizeFormatter.cpp */, C63CD67E16BDCDD400DB18F1 /* MCSizeFormatter.h */, - C63CD67B16BDCDD400DB18F1 /* MCHTMLRenderer.cc */, + C63CD67B16BDCDD400DB18F1 /* MCHTMLRenderer.cpp */, C63CD67C16BDCDD400DB18F1 /* MCHTMLRenderer.h */, - C63CD68416BE148B00DB18F1 /* MCHTMLRendererCallback.cc */, + C63CD68416BE148B00DB18F1 /* MCHTMLRendererCallback.cpp */, C63CD68516BE148B00DB18F1 /* MCHTMLRendererCallback.h */, C63CD68716BE1AB600DB18F1 /* MCRenderer.h */, - DAD28C891783CFFC00F2BB8F /* MCHTMLBodyRendererTemplateCallback.cc */, + DAD28C891783CFFC00F2BB8F /* MCHTMLBodyRendererTemplateCallback.cpp */, DAD28C8A1783CFFC00F2BB8F /* MCHTMLBodyRendererTemplateCallback.h */, - DAACAD4F17886807000B4517 /* MCHTMLRendererIMAPDataCallback.cc */, + DAACAD4F17886807000B4517 /* MCHTMLRendererIMAPDataCallback.cpp */, DAACAD5017886807000B4517 /* MCHTMLRendererIMAPDataCallback.h */, ); path = renderer; @@ -2168,66 +2168,66 @@ isa = PBXGroup; children = ( C64EA7F916A15A9200778456 /* MCAsyncIMAP.h */, - C64EA7FD16A295B500778456 /* MCIMAPAsyncConnection.cc */, + C64EA7FD16A295B500778456 /* MCIMAPAsyncConnection.cpp */, C64EA68C169E847800778456 /* MCIMAPAsyncConnection.h */, - C62C6F0816A8F57000737497 /* MCIMAPAsyncSession.cc */, + C62C6F0816A8F57000737497 /* MCIMAPAsyncSession.cpp */, C62C6F0916A8F57700737497 /* MCIMAPAsyncSession.h */, - C64EA7EF16A15A4D00778456 /* MCIMAPOperation.cc */, + C64EA7EF16A15A4D00778456 /* MCIMAPOperation.cpp */, C64EA7F016A15A4D00778456 /* MCIMAPOperation.h */, C64EA7F416A15A6300778456 /* MCIMAPOperationCallback.h */, - C64EA7F616A15A7800778456 /* MCIMAPCheckAccountOperation.cc */, + C64EA7F616A15A7800778456 /* MCIMAPCheckAccountOperation.cpp */, C64EA7F716A15A7800778456 /* MCIMAPCheckAccountOperation.h */, - 943F1A9817D964F600F0C798 /* MCIMAPConnectOperation.cc */, + 943F1A9817D964F600F0C798 /* MCIMAPConnectOperation.cpp */, 943F1A9917D964F600F0C798 /* MCIMAPConnectOperation.h */, - C64EA7FA16A2959700778456 /* MCIMAPFetchFoldersOperation.cc */, + C64EA7FA16A2959700778456 /* MCIMAPFetchFoldersOperation.cpp */, C64EA7FB16A2959700778456 /* MCIMAPFetchFoldersOperation.h */, - C64EA80016A295E200778456 /* MCIMAPRenameFolderOperation.cc */, + C64EA80016A295E200778456 /* MCIMAPRenameFolderOperation.cpp */, C64EA80116A295E300778456 /* MCIMAPRenameFolderOperation.h */, - C64EA80316A2997B00778456 /* MCIMAPDeleteFolderOperation.cc */, + C64EA80316A2997B00778456 /* MCIMAPDeleteFolderOperation.cpp */, C64EA80416A2997D00778456 /* MCIMAPDeleteFolderOperation.h */, - C64EA80616A2999800778456 /* MCIMAPCreateFolderOperation.cc */, + C64EA80616A2999800778456 /* MCIMAPCreateFolderOperation.cpp */, C64EA80716A2999900778456 /* MCIMAPCreateFolderOperation.h */, - C64EA80916A299B500778456 /* MCIMAPSubscribeFolderOperation.cc */, + C64EA80916A299B500778456 /* MCIMAPSubscribeFolderOperation.cpp */, C64EA80A16A299B600778456 /* MCIMAPSubscribeFolderOperation.h */, - C64EA80F16A299EA00778456 /* MCIMAPAppendMessageOperation.cc */, + C64EA80F16A299EA00778456 /* MCIMAPAppendMessageOperation.cpp */, C64EA81016A299EB00778456 /* MCIMAPAppendMessageOperation.h */, - C64EA81216A29A0A00778456 /* MCIMAPCopyMessagesOperation.cc */, + C64EA81216A29A0A00778456 /* MCIMAPCopyMessagesOperation.cpp */, C64EA81316A29A1000778456 /* MCIMAPCopyMessagesOperation.h */, - C64EA81516A29A8500778456 /* MCIMAPExpungeOperation.cc */, + C64EA81516A29A8500778456 /* MCIMAPExpungeOperation.cpp */, C64EA81616A29A8600778456 /* MCIMAPExpungeOperation.h */, - C64EA81816A29AD400778456 /* MCIMAPFetchMessagesOperation.cc */, + C64EA81816A29AD400778456 /* MCIMAPFetchMessagesOperation.cpp */, C64EA81916A29ADB00778456 /* MCIMAPFetchMessagesOperation.h */, - C64EA81B16A29DC100778456 /* MCIMAPFetchContentOperation.cc */, + C64EA81B16A29DC100778456 /* MCIMAPFetchContentOperation.cpp */, C64EA81C16A29DC400778456 /* MCIMAPFetchContentOperation.h */, - 8199FBEF19FAF1270040BBC3 /* MCIMAPFetchParsedContentOperation.cc */, + 8199FBEF19FAF1270040BBC3 /* MCIMAPFetchParsedContentOperation.cpp */, 8199FBF019FAF1270040BBC3 /* MCIMAPFetchParsedContentOperation.h */, - C64EA81E16A29E3D00778456 /* MCIMAPStoreFlagsOperation.cc */, + C64EA81E16A29E3D00778456 /* MCIMAPStoreFlagsOperation.cpp */, C64EA81F16A29E3F00778456 /* MCIMAPStoreFlagsOperation.h */, - C64EA82116A29E4F00778456 /* MCIMAPStoreLabelsOperation.cc */, + C64EA82116A29E4F00778456 /* MCIMAPStoreLabelsOperation.cpp */, C64EA82216A29E5200778456 /* MCIMAPStoreLabelsOperation.h */, - C64EA82416A29EE000778456 /* MCIMAPSearchOperation.cc */, + C64EA82416A29EE000778456 /* MCIMAPSearchOperation.cpp */, C64EA82516A29EE300778456 /* MCIMAPSearchOperation.h */, - C64EA82716A29EF400778456 /* MCIMAPIdleOperation.cc */, + C64EA82716A29EF400778456 /* MCIMAPIdleOperation.cpp */, C64EA82816A29F0300778456 /* MCIMAPIdleOperation.h */, - C64EA82A16A29FAA00778456 /* MCIMAPFetchNamespaceOperation.cc */, + C64EA82A16A29FAA00778456 /* MCIMAPFetchNamespaceOperation.cpp */, C64EA82B16A2A01400778456 /* MCIMAPFetchNamespaceOperation.h */, - C62C6ED216A2A0E600737497 /* MCIMAPIdentityOperation.cc */, + C62C6ED216A2A0E600737497 /* MCIMAPIdentityOperation.cpp */, C62C6ED316A2A0E600737497 /* MCIMAPIdentityOperation.h */, - C62C6ED616A398FA00737497 /* MCIMAPFolderInfoOperation.cc */, + C62C6ED616A398FA00737497 /* MCIMAPFolderInfoOperation.cpp */, C62C6ED716A398FA00737497 /* MCIMAPFolderInfoOperation.h */, - C64BB22916E5C0A3000DB34C /* MCIMAPCapabilityOperation.cc */, + C64BB22916E5C0A3000DB34C /* MCIMAPCapabilityOperation.cpp */, C64BB22A16E5C0A3000DB34C /* MCIMAPCapabilityOperation.h */, - 4B3C1BDF17ABF4BB008BBF4C /* MCIMAPQuotaOperation.cc */, + 4B3C1BDF17ABF4BB008BBF4C /* MCIMAPQuotaOperation.cpp */, 4B3C1BE017ABF4BC008BBF4C /* MCIMAPQuotaOperation.h */, - 9EF9AB10175F319A0027FA3B /* MCIMAPFolderStatusOperation.cc */, + 9EF9AB10175F319A0027FA3B /* MCIMAPFolderStatusOperation.cpp */, 9EF9AB0E175F30C20027FA3B /* MCIMAPFolderStatusOperation.h */, - C6081679177635D2001F1018 /* MCIMAPDisconnectOperation.cc */, + C6081679177635D2001F1018 /* MCIMAPDisconnectOperation.cpp */, C608167A177635D2001F1018 /* MCIMAPDisconnectOperation.h */, - DA0F1C79177C07B300F0D3B4 /* MCIMAPMessageRenderingOperation.cc */, + DA0F1C79177C07B300F0D3B4 /* MCIMAPMessageRenderingOperation.cpp */, DA0F1C7A177C07B300F0D3B4 /* MCIMAPMessageRenderingOperation.h */, - 84B639EB17F280F3003B5BA2 /* MCIMAPNoopOperation.cc */, + 84B639EB17F280F3003B5BA2 /* MCIMAPNoopOperation.cpp */, 84B639EC17F280F3003B5BA2 /* MCIMAPNoopOperation.h */, - C6EFFBC6182BBF5700CFF656 /* MCIMAPMultiDisconnectOperation.cc */, + C6EFFBC6182BBF5700CFF656 /* MCIMAPMultiDisconnectOperation.cpp */, C6EFFBC7182BBF5700CFF656 /* MCIMAPMultiDisconnectOperation.h */, ); path = imap; @@ -2237,21 +2237,21 @@ isa = PBXGroup; children = ( C62C6EFD16A7DD0300737497 /* MCAsyncPOP.h */, - C62C6EED16A7B67600737497 /* MCPOPAsyncSession.cc */, + C62C6EED16A7B67600737497 /* MCPOPAsyncSession.cpp */, C62C6EEE16A7B67600737497 /* MCPOPAsyncSession.h */, - C62C6EF016A7C6DE00737497 /* MCPOPFetchHeaderOperation.cc */, + C62C6EF016A7C6DE00737497 /* MCPOPFetchHeaderOperation.cpp */, C62C6EF116A7C6DE00737497 /* MCPOPFetchHeaderOperation.h */, - C62C6EF316A7C6E900737497 /* MCPOPFetchMessageOperation.cc */, + C62C6EF316A7C6E900737497 /* MCPOPFetchMessageOperation.cpp */, C62C6EF416A7C6E900737497 /* MCPOPFetchMessageOperation.h */, - C62C6EF616A7C6F500737497 /* MCPOPDeleteMessagesOperation.cc */, + C62C6EF616A7C6F500737497 /* MCPOPDeleteMessagesOperation.cpp */, C62C6EF716A7C6F500737497 /* MCPOPDeleteMessagesOperation.h */, - C62C6F0416A7E54200737497 /* MCPOPFetchMessagesOperation.cc */, + C62C6F0416A7E54200737497 /* MCPOPFetchMessagesOperation.cpp */, C62C6F0516A7E54400737497 /* MCPOPFetchMessagesOperation.h */, - C6AC10FE17114DAF00B715B7 /* MCPOPCheckAccountOperation.cc */, + C6AC10FE17114DAF00B715B7 /* MCPOPCheckAccountOperation.cpp */, C6AC10FF17114DAF00B715B7 /* MCPOPCheckAccountOperation.h */, - 84B639E617F27EBD003B5BA2 /* MCPOPNoopOperation.cc */, + 84B639E617F27EBD003B5BA2 /* MCPOPNoopOperation.cpp */, 84B639E717F27EBD003B5BA2 /* MCPOPNoopOperation.h */, - C62C6EF916A7C93F00737497 /* MCPOPOperation.cc */, + C62C6EF916A7C93F00737497 /* MCPOPOperation.cpp */, C62C6EFA16A7C94000737497 /* MCPOPOperation.h */, C62C6EFC16A7CA1500737497 /* MCPOPOperationCallback.h */, ); @@ -2262,20 +2262,20 @@ isa = PBXGroup; children = ( C64EA7E316A149EF00778456 /* MCAsyncSMTP.h */, - C64EA68F169E847800778456 /* MCSMTPAsyncSession.cc */, + C64EA68F169E847800778456 /* MCSMTPAsyncSession.cpp */, C64EA690169E847800778456 /* MCSMTPAsyncSession.h */, - 8B0095C71A00DDC500F84BC0 /* MCSMTPLoginOperation.cc */, + 8B0095C71A00DDC500F84BC0 /* MCSMTPLoginOperation.cpp */, 8B0095C81A00DDC500F84BC0 /* MCSMTPLoginOperation.h */, - C64EA79C169F29A700778456 /* MCSMTPSendWithDataOperation.cc */, + C64EA79C169F29A700778456 /* MCSMTPSendWithDataOperation.cpp */, C64EA79D169F29A700778456 /* MCSMTPSendWithDataOperation.h */, - C608167317759967001F1018 /* MCSMTPDisconnectOperation.cc */, + C608167317759967001F1018 /* MCSMTPDisconnectOperation.cpp */, C608167417759967001F1018 /* MCSMTPDisconnectOperation.h */, - 84B639E117F279BB003B5BA2 /* MCSMTPNoopOperation.cc */, + 84B639E117F279BB003B5BA2 /* MCSMTPNoopOperation.cpp */, 84B639E217F279BB003B5BA2 /* MCSMTPNoopOperation.h */, - C64EA7D816A1386500778456 /* MCSMTPOperation.cc */, + C64EA7D816A1386500778456 /* MCSMTPOperation.cpp */, C64EA7D916A1386600778456 /* MCSMTPOperation.h */, C64EA7E116A1425400778456 /* MCSMTPOperationCallback.h */, - C64EA7E816A154B000778456 /* MCSMTPCheckAccountOperation.cc */, + C64EA7E816A154B000778456 /* MCSMTPCheckAccountOperation.cpp */, C64EA7E916A154B200778456 /* MCSMTPCheckAccountOperation.h */, ); path = smtp; @@ -2304,18 +2304,18 @@ isa = PBXGroup; children = ( C64EA693169E847800778456 /* MCAbstract.h */, - C64EA694169E847800778456 /* MCAbstractMessage.cc */, + C64EA694169E847800778456 /* MCAbstractMessage.cpp */, C64EA695169E847800778456 /* MCAbstractMessage.h */, - C64EA696169E847800778456 /* MCAbstractMessagePart.cc */, + C64EA696169E847800778456 /* MCAbstractMessagePart.cpp */, C64EA697169E847800778456 /* MCAbstractMessagePart.h */, - C64EA698169E847800778456 /* MCAbstractMultipart.cc */, + C64EA698169E847800778456 /* MCAbstractMultipart.cpp */, C64EA699169E847800778456 /* MCAbstractMultipart.h */, - C64EA69A169E847800778456 /* MCAbstractPart.cc */, + C64EA69A169E847800778456 /* MCAbstractPart.cpp */, C64EA69B169E847800778456 /* MCAbstractPart.h */, - C64EA69C169E847800778456 /* MCAddress.cc */, + C64EA69C169E847800778456 /* MCAddress.cpp */, C64EA69D169E847800778456 /* MCAddress.h */, C64EA69E169E847800778456 /* MCMessageConstants.h */, - C64EA69F169E847800778456 /* MCMessageHeader.cc */, + C64EA69F169E847800778456 /* MCMessageHeader.cpp */, C64EA6A0169E847800778456 /* MCMessageHeader.h */, ); path = abstract; @@ -2329,64 +2329,64 @@ BD62729A1A158DA000129AA8 /* MCDefines.h */, BD49963519FEC6DD000945BC /* ConvertUTF.c */, BD49963619FEC6DD000945BC /* ConvertUTF.h */, - C64EA6A5169E847800778456 /* MCArray.cc */, + C64EA6A5169E847800778456 /* MCArray.cpp */, C64EA6A6169E847800778456 /* MCArray.h */, C64EA6A7169E847800778456 /* MCAssert.c */, C64EA6A8169E847800778456 /* MCAssert.h */, - C64EA6A2169E847800778456 /* MCAutoreleasePool.cc */, + C64EA6A2169E847800778456 /* MCAutoreleasePool.cpp */, C64EA6A3169E847800778456 /* MCAutoreleasePool.h */, C668E2CA1735CB8900A2BB47 /* MCAutoreleasePoolMac.mm */, C67597C117A8D65000DA69DF /* MCBase64.c */, C67597C417A8D66000DA69DF /* MCBase64.h */, C64EA6A4169E847800778456 /* MCBaseTypes.h */, C68B2AEB1778A589005E61EF /* MCConnectionLogger.h */, - C68B2AF517797389005E61EF /* MCConnectionLoggerUtils.cc */, + C68B2AF517797389005E61EF /* MCConnectionLoggerUtils.cpp */, C68B2AF617797389005E61EF /* MCConnectionLoggerUtils.h */, - C64EA6A9169E847800778456 /* MCData.cc */, + C64EA6A9169E847800778456 /* MCData.cpp */, C64EA6AA169E847800778456 /* MCData.h */, C6D4FD4219FB7DAA001F7E01 /* MCDataMac.mm */, - C64EA6AB169E847800778456 /* MCHash.cc */, + C64EA6AB169E847800778456 /* MCHash.cpp */, C64EA6AC169E847800778456 /* MCHash.h */, - C64EA6AD169E847800778456 /* MCHashMap.cc */, + C64EA6AD169E847800778456 /* MCHashMap.cpp */, C64EA6AE169E847800778456 /* MCHashMap.h */, - C63CD68F16BE566D00DB18F1 /* MCHTMLCleaner.cc */, + C63CD68F16BE566D00DB18F1 /* MCHTMLCleaner.cpp */, C63CD69016BE566E00DB18F1 /* MCHTMLCleaner.h */, C6D6F9691720F8F4006F5B28 /* MCICUTypes.h */, - C64BB22C16E5C1EE000DB34C /* MCIndexSet.cc */, + C64BB22C16E5C1EE000DB34C /* MCIndexSet.cpp */, C64BB22D16E5C1EE000DB34C /* MCIndexSet.h */, C6D6F96D1721028D006F5B28 /* MCIterator.h */, - C6D6F7F7171E595D006F5B28 /* MCJSON.cc */, + C6D6F7F7171E595D006F5B28 /* MCJSON.cpp */, C6D6F7F8171E595D006F5B28 /* MCJSON.h */, - C6D6F965171FCF9F006F5B28 /* MCJSONParser.cc */, + C6D6F965171FCF9F006F5B28 /* MCJSONParser.cpp */, C6D6F966171FCF9F006F5B28 /* MCJSONParser.h */, - BD637139177DFF080094121B /* MCLibetpan.cc */, + BD637139177DFF080094121B /* MCLibetpan.cpp */, BD63713A177DFF080094121B /* MCLibetpan.h */, C6AC1131171249DF00B715B7 /* MCLibetpanTypes.h */, C64EA6AF169E847800778456 /* MCLog.cpp */, C64EA6B0169E847800778456 /* MCLog.h */, C64EA6BC169E847800778456 /* MCMainThread.h */, C64EA6BD169E847800778456 /* MCMainThreadMac.mm */, - C6D6F950171E5CB8006F5B28 /* MCMD5.cc */, + C6D6F950171E5CB8006F5B28 /* MCMD5.cpp */, C6D6F951171E5CB8006F5B28 /* MCMD5.h */, - C6D6F952171E5CB8006F5B28 /* MCNull.cc */, + C6D6F952171E5CB8006F5B28 /* MCNull.cpp */, C6D6F953171E5CB8006F5B28 /* MCNull.h */, - C64EA6B1169E847800778456 /* MCObject.cc */, + C64EA6B1169E847800778456 /* MCObject.cpp */, C64EA6B2169E847800778456 /* MCObject.h */, C668E2C51735C8D500A2BB47 /* MCObjectMac.mm */, - C64EA6BE169E847800778456 /* MCOperation.cc */, + C64EA6BE169E847800778456 /* MCOperation.cpp */, C64EA6BF169E847800778456 /* MCOperation.h */, C64EA6C0169E847800778456 /* MCOperationCallback.h */, - C64EA6C1169E847800778456 /* MCOperationQueue.cc */, + C64EA6C1169E847800778456 /* MCOperationQueue.cpp */, C64EA6C2169E847800778456 /* MCOperationQueue.h */, C6081678177625AD001F1018 /* MCOperationQueueCallback.h */, - C64EA6B3169E847800778456 /* MCRange.cc */, + C64EA6B3169E847800778456 /* MCRange.cpp */, C64EA6B4169E847800778456 /* MCRange.h */, - C64EA6B5169E847800778456 /* MCSet.cc */, + C64EA6B5169E847800778456 /* MCSet.cpp */, C64EA6B6169E847800778456 /* MCSet.h */, - C64EA6B7169E847800778456 /* MCString.cc */, + C64EA6B7169E847800778456 /* MCString.cpp */, C64EA6B8169E847800778456 /* MCString.h */, C64EA6B9169E847800778456 /* MCUtils.h */, - C64EA6BA169E847800778456 /* MCValue.cc */, + C64EA6BA169E847800778456 /* MCValue.cpp */, C64EA6BB169E847800778456 /* MCValue.h */, C64BB25316FC2AA0000DB34C /* MCValuePrivate.h */, ); @@ -2397,31 +2397,31 @@ isa = PBXGroup; children = ( C64EA6C4169E847800778456 /* MCIMAP.h */, - C64EA6C5169E847800778456 /* MCIMAPFolder.cc */, + C64EA6C5169E847800778456 /* MCIMAPFolder.cpp */, C64EA6C6169E847800778456 /* MCIMAPFolder.h */, - C64EA6C7169E847800778456 /* MCIMAPMessage.cc */, + C64EA6C7169E847800778456 /* MCIMAPMessage.cpp */, C64EA6C8169E847800778456 /* MCIMAPMessage.h */, - C64EA6C9169E847800778456 /* MCIMAPMessagePart.cc */, + C64EA6C9169E847800778456 /* MCIMAPMessagePart.cpp */, C64EA6CA169E847800778456 /* MCIMAPMessagePart.h */, - C64EA6CB169E847800778456 /* MCIMAPMultipart.cc */, + C64EA6CB169E847800778456 /* MCIMAPMultipart.cpp */, C64EA6CC169E847800778456 /* MCIMAPMultipart.h */, - C64EA6CD169E847800778456 /* MCIMAPNamespace.cc */, + C64EA6CD169E847800778456 /* MCIMAPNamespace.cpp */, C64EA6CE169E847800778456 /* MCIMAPNamespace.h */, - C64EA6CF169E847800778456 /* MCIMAPNamespaceItem.cc */, + C64EA6CF169E847800778456 /* MCIMAPNamespaceItem.cpp */, C64EA6D0169E847800778456 /* MCIMAPNamespaceItem.h */, - C64EA6D1169E847800778456 /* MCIMAPPart.cc */, + C64EA6D1169E847800778456 /* MCIMAPPart.cpp */, C64EA6D2169E847800778456 /* MCIMAPPart.h */, C64EA6D3169E847800778456 /* MCIMAPProgressCallback.h */, - C64EA6D4169E847800778456 /* MCIMAPSearchExpression.cc */, + C64EA6D4169E847800778456 /* MCIMAPSearchExpression.cpp */, C64EA6D5169E847800778456 /* MCIMAPSearchExpression.h */, - C64EA6D6169E847800778456 /* MCIMAPSession.cc */, + C64EA6D6169E847800778456 /* MCIMAPSession.cpp */, C64EA6D7169E847800778456 /* MCIMAPSession.h */, - C64BB21F16E34DCA000DB34C /* MCIMAPSyncResult.cc */, + C64BB21F16E34DCA000DB34C /* MCIMAPSyncResult.cpp */, C64BB22016E34DCB000DB34C /* MCIMAPSyncResult.h */, 9E774D871767C54E0065EB9B /* MCIMAPFolderStatus.h */, - 9E774D881767C7F60065EB9B /* MCIMAPFolderStatus.cc */, + 9E774D881767C7F60065EB9B /* MCIMAPFolderStatus.cpp */, C63D315B17C9155C00A4D993 /* MCIMAPIdentity.h */, - C63D315A17C9155C00A4D993 /* MCIMAPIdentity.cc */, + C63D315A17C9155C00A4D993 /* MCIMAPIdentity.cpp */, ); path = imap; sourceTree = ""; @@ -2430,10 +2430,10 @@ isa = PBXGroup; children = ( C64EA6D9169E847800778456 /* MCPOP.h */, - C64EA6DA169E847800778456 /* MCPOPMessageInfo.cc */, + C64EA6DA169E847800778456 /* MCPOPMessageInfo.cpp */, C64EA6DB169E847800778456 /* MCPOPMessageInfo.h */, C64EA6DC169E847800778456 /* MCPOPProgressCallback.h */, - C64EA6DD169E847800778456 /* MCPOPSession.cc */, + C64EA6DD169E847800778456 /* MCPOPSession.cpp */, C64EA6DE169E847800778456 /* MCPOPSession.h */, ); path = pop; @@ -2442,16 +2442,16 @@ C64EA6DF169E847800778456 /* rfc822 */ = { isa = PBXGroup; children = ( - C64EA6E0169E847800778456 /* MCAttachment.cc */, + C64EA6E0169E847800778456 /* MCAttachment.cpp */, C64EA6E1169E847800778456 /* MCAttachment.h */, - C64EA6E2169E847800778456 /* MCMessageBuilder.cc */, + C64EA6E2169E847800778456 /* MCMessageBuilder.cpp */, C64EA6E3169E847800778456 /* MCMessageBuilder.h */, - C64EA6E4169E847800778456 /* MCMessageParser.cc */, + C64EA6E4169E847800778456 /* MCMessageParser.cpp */, C64EA6E5169E847800778456 /* MCMessageParser.h */, C6D4FD3E19FB7534001F7E01 /* MCMessageParserMac.mm */, - C64EA6E6169E847800778456 /* MCMessagePart.cc */, + C64EA6E6169E847800778456 /* MCMessagePart.cpp */, C64EA6E7169E847800778456 /* MCMessagePart.h */, - C64EA6E8169E847800778456 /* MCMultipart.cc */, + C64EA6E8169E847800778456 /* MCMultipart.cpp */, C64EA6E9169E847800778456 /* MCMultipart.h */, C64EA6EA169E847800778456 /* MCRFC822.h */, ); @@ -2463,7 +2463,7 @@ children = ( C64EA6EC169E847800778456 /* MCSMTP.h */, C64EA6ED169E847800778456 /* MCSMTPProgressCallback.h */, - C64EA6EE169E847800778456 /* MCSMTPSession.cc */, + C64EA6EE169E847800778456 /* MCSMTPSession.cpp */, C64EA6EF169E847800778456 /* MCSMTPSession.h */, ); path = smtp; @@ -2609,7 +2609,7 @@ C6E665A91796500B0063F2CF /* zip */ = { isa = PBXGroup; children = ( - C6E665AA1796500B0063F2CF /* MCZip.cc */, + C6E665AA1796500B0063F2CF /* MCZip.cpp */, C6E665AB1796500B0063F2CF /* MCZip.h */, C6E665AC1796500B0063F2CF /* MiniZip */, ); @@ -2674,7 +2674,7 @@ C6F7B19C17A1C11F00BE78BB /* security */ = { isa = PBXGroup; children = ( - C6F7B19D17A1C15200BE78BB /* MCCertificateUtils.cc */, + C6F7B19D17A1C15200BE78BB /* MCCertificateUtils.cpp */, C6F7B19E17A1C15200BE78BB /* MCCertificateUtils.h */, ); path = security; @@ -3057,106 +3057,106 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 84D7373D199BF83B005124E5 /* MCNNTPFetchArticleOperation.cc in Sources */, - C64EA6F4169E847800778456 /* MCAbstractMessage.cc in Sources */, - C64EA6F6169E847800778456 /* MCAbstractMessagePart.cc in Sources */, - 84B639ED17F280F3003B5BA2 /* MCIMAPNoopOperation.cc in Sources */, - C64EA6F8169E847800778456 /* MCAbstractMultipart.cc in Sources */, - C64EA6FA169E847800778456 /* MCAbstractPart.cc in Sources */, - C64EA6FC169E847800778456 /* MCAddress.cc in Sources */, - C64EA6FF169E847800778456 /* MCMessageHeader.cc in Sources */, - C64EA701169E847800778456 /* MCAutoreleasePool.cc in Sources */, - C64EA704169E847800778456 /* MCArray.cc in Sources */, - C6E665B51796500B0063F2CF /* MCZip.cc in Sources */, - 84B639E317F279BB003B5BA2 /* MCSMTPNoopOperation.cc in Sources */, + 84D7373D199BF83B005124E5 /* MCNNTPFetchArticleOperation.cpp in Sources */, + C64EA6F4169E847800778456 /* MCAbstractMessage.cpp in Sources */, + C64EA6F6169E847800778456 /* MCAbstractMessagePart.cpp in Sources */, + 84B639ED17F280F3003B5BA2 /* MCIMAPNoopOperation.cpp in Sources */, + C64EA6F8169E847800778456 /* MCAbstractMultipart.cpp in Sources */, + C64EA6FA169E847800778456 /* MCAbstractPart.cpp in Sources */, + C64EA6FC169E847800778456 /* MCAddress.cpp in Sources */, + C64EA6FF169E847800778456 /* MCMessageHeader.cpp in Sources */, + C64EA701169E847800778456 /* MCAutoreleasePool.cpp in Sources */, + C64EA704169E847800778456 /* MCArray.cpp in Sources */, + C6E665B51796500B0063F2CF /* MCZip.cpp in Sources */, + 84B639E317F279BB003B5BA2 /* MCSMTPNoopOperation.cpp in Sources */, 84CFA98319F7153B00FE35D2 /* MCONNTPFetchOverviewOperation.mm in Sources */, 8199FBEB19FAEA440040BBC3 /* MCOIMAPFetchParsedContentOperation.mm in Sources */, C64EA706169E847800778456 /* MCAssert.c in Sources */, 84D73793199C0511005124E5 /* MCONNTPGroupInfo.mm in Sources */, - C64EA708169E847800778456 /* MCData.cc in Sources */, - C64EA70A169E847800778456 /* MCHash.cc in Sources */, - C64EA70C169E847800778456 /* MCHashMap.cc in Sources */, + C64EA708169E847800778456 /* MCData.cpp in Sources */, + C64EA70A169E847800778456 /* MCHash.cpp in Sources */, + C64EA70C169E847800778456 /* MCHashMap.cpp in Sources */, C64EA70E169E847800778456 /* MCLog.cpp in Sources */, - C64EA710169E847800778456 /* MCObject.cc in Sources */, - C64EA712169E847800778456 /* MCRange.cc in Sources */, - C64EA714169E847800778456 /* MCSet.cc in Sources */, - C64EA716169E847800778456 /* MCString.cc in Sources */, - C64EA719169E847800778456 /* MCValue.cc in Sources */, + C64EA710169E847800778456 /* MCObject.cpp in Sources */, + C64EA712169E847800778456 /* MCRange.cpp in Sources */, + C64EA714169E847800778456 /* MCSet.cpp in Sources */, + C64EA716169E847800778456 /* MCString.cpp in Sources */, + C64EA719169E847800778456 /* MCValue.cpp in Sources */, C64EA71C169E847800778456 /* MCMainThreadMac.mm in Sources */, - C64EA71D169E847800778456 /* MCOperation.cc in Sources */, - C64EA720169E847800778456 /* MCOperationQueue.cc in Sources */, - C64EA723169E847800778456 /* MCIMAPFolder.cc in Sources */, - C64EA725169E847800778456 /* MCIMAPMessage.cc in Sources */, - C64EA727169E847800778456 /* MCIMAPMessagePart.cc in Sources */, + C64EA71D169E847800778456 /* MCOperation.cpp in Sources */, + C64EA720169E847800778456 /* MCOperationQueue.cpp in Sources */, + C64EA723169E847800778456 /* MCIMAPFolder.cpp in Sources */, + C64EA725169E847800778456 /* MCIMAPMessage.cpp in Sources */, + C64EA727169E847800778456 /* MCIMAPMessagePart.cpp in Sources */, 84D73775199C00AB005124E5 /* MCONNTPFetchAllArticlesOperation.mm in Sources */, - C64EA729169E847800778456 /* MCIMAPMultipart.cc in Sources */, + C64EA729169E847800778456 /* MCIMAPMultipart.cpp in Sources */, 84CFA99519F725CB00FE35D2 /* MCONNTPFetchServerTimeOperation.mm in Sources */, - C64EA72B169E847800778456 /* MCIMAPNamespace.cc in Sources */, - C64EA72D169E847800778456 /* MCIMAPNamespaceItem.cc in Sources */, - C64EA72F169E847800778456 /* MCIMAPPart.cc in Sources */, - C64EA732169E847800778456 /* MCIMAPSearchExpression.cc in Sources */, - C64EA734169E847800778456 /* MCIMAPSession.cc in Sources */, - C68B2AF717797389005E61EF /* MCConnectionLoggerUtils.cc in Sources */, - C64EA737169E847800778456 /* MCPOPMessageInfo.cc in Sources */, - C64EA73A169E847800778456 /* MCPOPSession.cc in Sources */, - 84D7375C199BFDCA005124E5 /* MCNNTPListNewsgroupsOperation.cc in Sources */, - C64EA73C169E847800778456 /* MCAttachment.cc in Sources */, - C64EA73E169E847800778456 /* MCMessageBuilder.cc in Sources */, - C64EA740169E847800778456 /* MCMessageParser.cc in Sources */, - C64EA742169E847800778456 /* MCMessagePart.cc in Sources */, + C64EA72B169E847800778456 /* MCIMAPNamespace.cpp in Sources */, + C64EA72D169E847800778456 /* MCIMAPNamespaceItem.cpp in Sources */, + C64EA72F169E847800778456 /* MCIMAPPart.cpp in Sources */, + C64EA732169E847800778456 /* MCIMAPSearchExpression.cpp in Sources */, + C64EA734169E847800778456 /* MCIMAPSession.cpp in Sources */, + C68B2AF717797389005E61EF /* MCConnectionLoggerUtils.cpp in Sources */, + C64EA737169E847800778456 /* MCPOPMessageInfo.cpp in Sources */, + C64EA73A169E847800778456 /* MCPOPSession.cpp in Sources */, + 84D7375C199BFDCA005124E5 /* MCNNTPListNewsgroupsOperation.cpp in Sources */, + C64EA73C169E847800778456 /* MCAttachment.cpp in Sources */, + C64EA73E169E847800778456 /* MCMessageBuilder.cpp in Sources */, + C64EA740169E847800778456 /* MCMessageParser.cpp in Sources */, + C64EA742169E847800778456 /* MCMessagePart.cpp in Sources */, 84D7378B199C0260005124E5 /* MCONNTPListNewsgroupsOperation.mm in Sources */, - C64EA744169E847800778456 /* MCMultipart.cc in Sources */, - C64EA781169E89F600778456 /* MCSMTPSession.cc in Sources */, + C64EA744169E847800778456 /* MCMultipart.cpp in Sources */, + C64EA781169E89F600778456 /* MCSMTPSession.cpp in Sources */, 8416A9A117F2871D00B3C7DA /* MCOIMAPNoopOperation.mm in Sources */, - C64EA784169F24E400778456 /* MCSMTPAsyncSession.cc in Sources */, - C6F7B19F17A1C15200BE78BB /* MCCertificateUtils.cc in Sources */, - 8B0095C91A00DDC500F84BC0 /* MCSMTPLoginOperation.cc in Sources */, - C64EA79E169F29A700778456 /* MCSMTPSendWithDataOperation.cc in Sources */, - C64EA7DA16A1386600778456 /* MCSMTPOperation.cc in Sources */, - C64EA7EA16A154B300778456 /* MCSMTPCheckAccountOperation.cc in Sources */, - C64EA7F116A15A4D00778456 /* MCIMAPOperation.cc in Sources */, - C64EA7F816A15A7800778456 /* MCIMAPCheckAccountOperation.cc in Sources */, - 943F1A9A17D964F600F0C798 /* MCIMAPConnectOperation.cc in Sources */, - C64EA7FC16A2959800778456 /* MCIMAPFetchFoldersOperation.cc in Sources */, - C64EA80216A295E400778456 /* MCIMAPRenameFolderOperation.cc in Sources */, - C64EA80516A2997E00778456 /* MCIMAPDeleteFolderOperation.cc in Sources */, + C64EA784169F24E400778456 /* MCSMTPAsyncSession.cpp in Sources */, + C6F7B19F17A1C15200BE78BB /* MCCertificateUtils.cpp in Sources */, + 8B0095C91A00DDC500F84BC0 /* MCSMTPLoginOperation.cpp in Sources */, + C64EA79E169F29A700778456 /* MCSMTPSendWithDataOperation.cpp in Sources */, + C64EA7DA16A1386600778456 /* MCSMTPOperation.cpp in Sources */, + C64EA7EA16A154B300778456 /* MCSMTPCheckAccountOperation.cpp in Sources */, + C64EA7F116A15A4D00778456 /* MCIMAPOperation.cpp in Sources */, + C64EA7F816A15A7800778456 /* MCIMAPCheckAccountOperation.cpp in Sources */, + 943F1A9A17D964F600F0C798 /* MCIMAPConnectOperation.cpp in Sources */, + C64EA7FC16A2959800778456 /* MCIMAPFetchFoldersOperation.cpp in Sources */, + C64EA80216A295E400778456 /* MCIMAPRenameFolderOperation.cpp in Sources */, + C64EA80516A2997E00778456 /* MCIMAPDeleteFolderOperation.cpp in Sources */, BD49963719FEC6DD000945BC /* ConvertUTF.c in Sources */, - C63D315C17C9155C00A4D993 /* MCIMAPIdentity.cc in Sources */, - 84D73742199BF963005124E5 /* MCNNTPFetchAllArticlesOperation.cc in Sources */, - C64EA80816A2999A00778456 /* MCIMAPCreateFolderOperation.cc in Sources */, - C64EA80B16A299B700778456 /* MCIMAPSubscribeFolderOperation.cc in Sources */, - 84D7372C199BF66C005124E5 /* MCNNTPAsyncSession.cc in Sources */, - C64EA81116A299ED00778456 /* MCIMAPAppendMessageOperation.cc in Sources */, - C64EA81416A29A2300778456 /* MCIMAPCopyMessagesOperation.cc in Sources */, - C64EA81716A29A8700778456 /* MCIMAPExpungeOperation.cc in Sources */, + C63D315C17C9155C00A4D993 /* MCIMAPIdentity.cpp in Sources */, + 84D73742199BF963005124E5 /* MCNNTPFetchAllArticlesOperation.cpp in Sources */, + C64EA80816A2999A00778456 /* MCIMAPCreateFolderOperation.cpp in Sources */, + C64EA80B16A299B700778456 /* MCIMAPSubscribeFolderOperation.cpp in Sources */, + 84D7372C199BF66C005124E5 /* MCNNTPAsyncSession.cpp in Sources */, + C64EA81116A299ED00778456 /* MCIMAPAppendMessageOperation.cpp in Sources */, + C64EA81416A29A2300778456 /* MCIMAPCopyMessagesOperation.cpp in Sources */, + C64EA81716A29A8700778456 /* MCIMAPExpungeOperation.cpp in Sources */, C69BA85B17DEFCCB00D601B7 /* NSIndexSet+MCO.m in Sources */, - C64EA81A16A29AF200778456 /* MCIMAPFetchMessagesOperation.cc in Sources */, - C64EA81D16A29DC500778456 /* MCIMAPFetchContentOperation.cc in Sources */, - 84D73746199BFA8C005124E5 /* MCNNTPCheckAccountOperation.cc in Sources */, - C64EA82016A29E4100778456 /* MCIMAPStoreFlagsOperation.cc in Sources */, - C64EA82316A29E5300778456 /* MCIMAPStoreLabelsOperation.cc in Sources */, + C64EA81A16A29AF200778456 /* MCIMAPFetchMessagesOperation.cpp in Sources */, + C64EA81D16A29DC500778456 /* MCIMAPFetchContentOperation.cpp in Sources */, + 84D73746199BFA8C005124E5 /* MCNNTPCheckAccountOperation.cpp in Sources */, + C64EA82016A29E4100778456 /* MCIMAPStoreFlagsOperation.cpp in Sources */, + C64EA82316A29E5300778456 /* MCIMAPStoreLabelsOperation.cpp in Sources */, C643F492189A3D59007EA2F7 /* NSSet+MCO.mm in Sources */, - C64EA82616A29EE500778456 /* MCIMAPSearchOperation.cc in Sources */, + C64EA82616A29EE500778456 /* MCIMAPSearchOperation.cpp in Sources */, C6E665BD1796500C0063F2CF /* zip.c in Sources */, - C64EA82916A29F2200778456 /* MCIMAPIdleOperation.cc in Sources */, - C64EA82C16A2A08B00778456 /* MCIMAPFetchNamespaceOperation.cc in Sources */, - 84D73758199BFC8A005124E5 /* MCNNTPDisconnectOperation.cc in Sources */, - 84B639E817F27EBD003B5BA2 /* MCPOPNoopOperation.cc in Sources */, - 849189A118C93FB7002063A3 /* MCNNTPSession.cc in Sources */, - C62C6ED416A2A0E600737497 /* MCIMAPIdentityOperation.cc in Sources */, - C62C6ED816A398FA00737497 /* MCIMAPFolderInfoOperation.cc in Sources */, - C62C6EDA16A3D60700737497 /* MCIMAPAsyncConnection.cc in Sources */, - C62C6EEF16A7B67600737497 /* MCPOPAsyncSession.cc in Sources */, - C62C6EF216A7C6DE00737497 /* MCPOPFetchHeaderOperation.cc in Sources */, - C62C6EF516A7C6EA00737497 /* MCPOPFetchMessageOperation.cc in Sources */, - C62C6EF816A7C6F500737497 /* MCPOPDeleteMessagesOperation.cc in Sources */, - C62C6EFB16A7C94000737497 /* MCPOPOperation.cc in Sources */, - C62C6F0616A7E54500737497 /* MCPOPFetchMessagesOperation.cc in Sources */, - C62C6F0A16A8F58000737497 /* MCIMAPAsyncSession.cc in Sources */, + C64EA82916A29F2200778456 /* MCIMAPIdleOperation.cpp in Sources */, + C64EA82C16A2A08B00778456 /* MCIMAPFetchNamespaceOperation.cpp in Sources */, + 84D73758199BFC8A005124E5 /* MCNNTPDisconnectOperation.cpp in Sources */, + 84B639E817F27EBD003B5BA2 /* MCPOPNoopOperation.cpp in Sources */, + 849189A118C93FB7002063A3 /* MCNNTPSession.cpp in Sources */, + C62C6ED416A2A0E600737497 /* MCIMAPIdentityOperation.cpp in Sources */, + C62C6ED816A398FA00737497 /* MCIMAPFolderInfoOperation.cpp in Sources */, + C62C6EDA16A3D60700737497 /* MCIMAPAsyncConnection.cpp in Sources */, + C62C6EEF16A7B67600737497 /* MCPOPAsyncSession.cpp in Sources */, + C62C6EF216A7C6DE00737497 /* MCPOPFetchHeaderOperation.cpp in Sources */, + C62C6EF516A7C6EA00737497 /* MCPOPFetchMessageOperation.cpp in Sources */, + C62C6EF816A7C6F500737497 /* MCPOPDeleteMessagesOperation.cpp in Sources */, + C62C6EFB16A7C94000737497 /* MCPOPOperation.cpp in Sources */, + C62C6F0616A7E54500737497 /* MCPOPFetchMessagesOperation.cpp in Sources */, + C62C6F0A16A8F58000737497 /* MCIMAPAsyncSession.cpp in Sources */, C6D42C1D16AE03D6002BB4F9 /* NSData+MCO.mm in Sources */, C6D42C1E16AE03D6002BB4F9 /* NSString+MCO.mm in Sources */, C64FF39116B3C13000F8C162 /* MCOObjectWrapper.mm in Sources */, - 84D73737199BF7F2005124E5 /* MCNNTPFetchHeaderOperation.cc in Sources */, + 84D73737199BF7F2005124E5 /* MCNNTPFetchHeaderOperation.cpp in Sources */, 84D7376D199C005A005124E5 /* MCONNTPFetchHeaderOperation.mm in Sources */, C6E665B71796500B0063F2CF /* ioapi.c in Sources */, C07ADC28B83E7959BF114D46 /* MCOIMAPSession.mm in Sources */, @@ -3164,19 +3164,19 @@ F87F190C16BB62B00012652F /* MCOIMAPFetchFoldersOperation.mm in Sources */, 84B639F117F282B4003B5BA2 /* MCOPOPNoopOperation.mm in Sources */, C6EB30F716B8C9480091F4F1 /* NSDictionary+MCO.mm in Sources */, - 8199FBF119FAF1270040BBC3 /* MCIMAPFetchParsedContentOperation.cc in Sources */, + 8199FBF119FAF1270040BBC3 /* MCIMAPFetchParsedContentOperation.cpp in Sources */, C6EB30FE16B8E50F0091F4F1 /* NSArray+MCO.mm in Sources */, C6EB310116B8E6E60091F4F1 /* NSObject+MCO.mm in Sources */, - C63CD67F16BDCDD400DB18F1 /* MCAddressDisplay.cc in Sources */, - C63CD68016BDCDD400DB18F1 /* MCDateFormatter.cc in Sources */, - C63CD68116BDCDD400DB18F1 /* MCHTMLRenderer.cc in Sources */, - C63CD68216BDCDD400DB18F1 /* MCSizeFormatter.cc in Sources */, - C63CD68616BE148B00DB18F1 /* MCHTMLRendererCallback.cc in Sources */, - 84CFA98F19F724E500FE35D2 /* MCNNTPFetchServerTimeOperation.cc in Sources */, - C63CD69116BE566E00DB18F1 /* MCHTMLCleaner.cc in Sources */, - C64BB22116E34DCB000DB34C /* MCIMAPSyncResult.cc in Sources */, - C64BB22B16E5C0A4000DB34C /* MCIMAPCapabilityOperation.cc in Sources */, - C64BB22E16E5C1EE000DB34C /* MCIndexSet.cc in Sources */, + C63CD67F16BDCDD400DB18F1 /* MCAddressDisplay.cpp in Sources */, + C63CD68016BDCDD400DB18F1 /* MCDateFormatter.cpp in Sources */, + C63CD68116BDCDD400DB18F1 /* MCHTMLRenderer.cpp in Sources */, + C63CD68216BDCDD400DB18F1 /* MCSizeFormatter.cpp in Sources */, + C63CD68616BE148B00DB18F1 /* MCHTMLRendererCallback.cpp in Sources */, + 84CFA98F19F724E500FE35D2 /* MCNNTPFetchServerTimeOperation.cpp in Sources */, + C63CD69116BE566E00DB18F1 /* MCHTMLCleaner.cpp in Sources */, + C64BB22116E34DCB000DB34C /* MCIMAPSyncResult.cpp in Sources */, + C64BB22B16E5C0A4000DB34C /* MCIMAPCapabilityOperation.cpp in Sources */, + C64BB22E16E5C1EE000DB34C /* MCIndexSet.cpp in Sources */, 84D73764199BFFC7005124E5 /* MCONNTPSession.mm in Sources */, C64BB23516EDAA17000DB34C /* MCOAbstractMessage.mm in Sources */, C64BB23916EDAA3F000DB34C /* MCOAbstractMessagePart.mm in Sources */, @@ -3202,14 +3202,14 @@ C6F5B9EE16FEA3C400D9DABD /* MCOIMAPNamespaceItem.mm in Sources */, C6F5B9F116FEA3D700D9DABD /* MCOIMAPPart.mm in Sources */, C6F5B9F416FEAC6C00D9DABD /* MCOIndexSet.mm in Sources */, - 849189AB18C94986002063A3 /* MCNNTPGroupInfo.cc in Sources */, + 849189AB18C94986002063A3 /* MCNNTPGroupInfo.cpp in Sources */, C6F5B9FE16FED18600D9DABD /* MCOAbstractMessageRendererCallback.mm in Sources */, C6CCC5C716FFE5190077A5FC /* MCORange.mm in Sources */, C63D316217C92D8300A4D993 /* MCOIMAPIdentity.mm in Sources */, C6F61F7B170169EE0073032E /* MCOIMAPFolderInfoOperation.mm in Sources */, C6F61F7E170169FB0073032E /* MCOIMAPAppendMessageOperation.mm in Sources */, C6F61F8117016A0D0073032E /* MCOIMAPCopyMessagesOperation.mm in Sources */, - DA0F1C7B177C07B300F0D3B4 /* MCIMAPMessageRenderingOperation.cc in Sources */, + DA0F1C7B177C07B300F0D3B4 /* MCIMAPMessageRenderingOperation.cpp in Sources */, C6F61F8417016A200073032E /* MCOIMAPFetchMessagesOperation.mm in Sources */, C6F61F8717016AD60073032E /* MCOIMAPFetchContentOperation.mm in Sources */, C6F61F8A17016AE60073032E /* MCOIMAPSearchOperation.mm in Sources */, @@ -3222,27 +3222,27 @@ C6F61F9F17016EA10073032E /* MCOIMAPFolderInfo.m in Sources */, C6D4FD3F19FB7534001F7E01 /* MCMessageParserMac.mm in Sources */, C6F61FB51702AB340073032E /* MCOIMAPBaseOperation.mm in Sources */, - C608167517759967001F1018 /* MCSMTPDisconnectOperation.cc in Sources */, + C608167517759967001F1018 /* MCSMTPDisconnectOperation.cpp in Sources */, C6A81BBF17068E5E00882C15 /* MCOSMTPSession.mm in Sources */, 8B0095CC1A00DDE700F84BC0 /* MCOSMTPLoginOperation.mm in Sources */, C6A81BC317068E9500882C15 /* MCOSMTPSendOperation.mm in Sources */, C6A81BC717068EB000882C15 /* MCOSMTPOperation.mm in Sources */, 8416A99D17F284F400B3C7DA /* MCOSMTPNoopOperation.mm in Sources */, C6A81BD61706903500882C15 /* MCOPOPSession.mm in Sources */, - C6EFFBC8182BBF5700CFF656 /* MCIMAPMultiDisconnectOperation.cc in Sources */, + C6EFFBC8182BBF5700CFF656 /* MCIMAPMultiDisconnectOperation.cpp in Sources */, C6A81BDA1706903E00882C15 /* MCOPOPFetchHeaderOperation.mm in Sources */, - C608167B177635D2001F1018 /* MCIMAPDisconnectOperation.cc in Sources */, + C608167B177635D2001F1018 /* MCIMAPDisconnectOperation.cpp in Sources */, C6A81BDE1706904800882C15 /* MCOPOPFetchMessageOperation.mm in Sources */, - 84D73730199BF704005124E5 /* MCNNTPOperation.cc in Sources */, + 84D73730199BF704005124E5 /* MCNNTPOperation.cpp in Sources */, C6A81BE21706905600882C15 /* MCOPOPOperation.mm in Sources */, C6A81BE61706906D00882C15 /* MCOPOPFetchMessagesOperation.mm in Sources */, C6A81C001707CEE600882C15 /* MCOPOPMessageInfo.mm in Sources */, - C6AC110017114DAF00B715B7 /* MCPOPCheckAccountOperation.cc in Sources */, - C6D6F7F9171E595D006F5B28 /* MCJSON.cc in Sources */, - C6D6F954171E5CB8006F5B28 /* MCMD5.cc in Sources */, - C6D6F956171E5CB8006F5B28 /* MCNull.cc in Sources */, - C6D6F967171FCF9F006F5B28 /* MCJSONParser.cc in Sources */, - 84CFA98719F7159700FE35D2 /* MCNNTPFetchOverviewOperation.cc in Sources */, + C6AC110017114DAF00B715B7 /* MCPOPCheckAccountOperation.cpp in Sources */, + C6D6F7F9171E595D006F5B28 /* MCJSON.cpp in Sources */, + C6D6F954171E5CB8006F5B28 /* MCMD5.cpp in Sources */, + C6D6F956171E5CB8006F5B28 /* MCNull.cpp in Sources */, + C6D6F967171FCF9F006F5B28 /* MCJSONParser.cpp in Sources */, + 84CFA98719F7159700FE35D2 /* MCNNTPFetchOverviewOperation.cpp in Sources */, 84D73768199BFFFC005124E5 /* MCONNTPOperation.mm in Sources */, C668E2C71735C8D500A2BB47 /* MCObjectMac.mm in Sources */, C668E2CC1735CB8900A2BB47 /* MCAutoreleasePoolMac.mm in Sources */, @@ -3251,20 +3251,20 @@ 84D7378F199C02A8005124E5 /* MCONNTPDisconnectOperation.mm in Sources */, C6CF62BD175324CE006398B9 /* MCONetService.mm in Sources */, C6EFFBCC1833334900CFF656 /* MCOIMAPMultiDisconnectOperation.mm in Sources */, - C6CF62C6175324F0006398B9 /* MCMailProvider.cc in Sources */, - C6CF62C8175324F0006398B9 /* MCMailProvidersManager.cc in Sources */, - C6CF62CA175324F0006398B9 /* MCNetService.cc in Sources */, + C6CF62C6175324F0006398B9 /* MCMailProvider.cpp in Sources */, + C6CF62C8175324F0006398B9 /* MCMailProvidersManager.cpp in Sources */, + C6CF62CA175324F0006398B9 /* MCNetService.cpp in Sources */, 9EF9AB09175F2EC60027FA3B /* MCOIMAPFolderStatus.mm in Sources */, - 9EF9AB11175F319A0027FA3B /* MCIMAPFolderStatusOperation.cc in Sources */, + 9EF9AB11175F319A0027FA3B /* MCIMAPFolderStatusOperation.cpp in Sources */, 9EF9AB19175F36600027FA3B /* MCOIMAPFolderStatusOperation.mm in Sources */, - 9E774D891767C7F60065EB9B /* MCIMAPFolderStatus.cc in Sources */, - DAD28C8B1783CFFC00F2BB8F /* MCHTMLBodyRendererTemplateCallback.cc in Sources */, - BD63713B177DFF080094121B /* MCLibetpan.cc in Sources */, - DAACAD5117886807000B4517 /* MCHTMLRendererIMAPDataCallback.cc in Sources */, + 9E774D891767C7F60065EB9B /* MCIMAPFolderStatus.cpp in Sources */, + DAD28C8B1783CFFC00F2BB8F /* MCHTMLBodyRendererTemplateCallback.cpp in Sources */, + BD63713B177DFF080094121B /* MCLibetpan.cpp in Sources */, + DAACAD5117886807000B4517 /* MCHTMLRendererIMAPDataCallback.cpp in Sources */, DA89896D178A47D200F6D90A /* MCOIMAPMessageRenderingOperation.mm in Sources */, 84D73771199C007E005124E5 /* MCONNTPFetchArticleOperation.mm in Sources */, 4B3C1BDE17ABF309008BBF4C /* MCOIMAPQuotaOperation.mm in Sources */, - 4B3C1BE117ABF4BC008BBF4C /* MCIMAPQuotaOperation.cc in Sources */, + 4B3C1BE117ABF4BC008BBF4C /* MCIMAPQuotaOperation.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3301,127 +3301,127 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 84D7373E199BF83B005124E5 /* MCNNTPFetchArticleOperation.cc in Sources */, - C6BA2B991705F4E6003F0E9E /* MCAbstractMessage.cc in Sources */, - C6BA2B9A1705F4E6003F0E9E /* MCAbstractMessagePart.cc in Sources */, - 84B639EE17F280F3003B5BA2 /* MCIMAPNoopOperation.cc in Sources */, - C6BA2B9B1705F4E6003F0E9E /* MCAbstractMultipart.cc in Sources */, - C6BA2B9C1705F4E6003F0E9E /* MCAbstractPart.cc in Sources */, - C6BA2B9D1705F4E6003F0E9E /* MCAddress.cc in Sources */, - C6BA2B9E1705F4E6003F0E9E /* MCMessageHeader.cc in Sources */, - C6BA2B9F1705F4E6003F0E9E /* MCAutoreleasePool.cc in Sources */, - C6BA2BA01705F4E6003F0E9E /* MCArray.cc in Sources */, - C6E665B61796500B0063F2CF /* MCZip.cc in Sources */, - 84B639E417F279BB003B5BA2 /* MCSMTPNoopOperation.cc in Sources */, + 84D7373E199BF83B005124E5 /* MCNNTPFetchArticleOperation.cpp in Sources */, + C6BA2B991705F4E6003F0E9E /* MCAbstractMessage.cpp in Sources */, + C6BA2B9A1705F4E6003F0E9E /* MCAbstractMessagePart.cpp in Sources */, + 84B639EE17F280F3003B5BA2 /* MCIMAPNoopOperation.cpp in Sources */, + C6BA2B9B1705F4E6003F0E9E /* MCAbstractMultipart.cpp in Sources */, + C6BA2B9C1705F4E6003F0E9E /* MCAbstractPart.cpp in Sources */, + C6BA2B9D1705F4E6003F0E9E /* MCAddress.cpp in Sources */, + C6BA2B9E1705F4E6003F0E9E /* MCMessageHeader.cpp in Sources */, + C6BA2B9F1705F4E6003F0E9E /* MCAutoreleasePool.cpp in Sources */, + C6BA2BA01705F4E6003F0E9E /* MCArray.cpp in Sources */, + C6E665B61796500B0063F2CF /* MCZip.cpp in Sources */, + 84B639E417F279BB003B5BA2 /* MCSMTPNoopOperation.cpp in Sources */, 84CFA98419F7153B00FE35D2 /* MCONNTPFetchOverviewOperation.mm in Sources */, 8199FBEC19FAEA440040BBC3 /* MCOIMAPFetchParsedContentOperation.mm in Sources */, C6BA2BA11705F4E6003F0E9E /* MCAssert.c in Sources */, 84D73794199C0511005124E5 /* MCONNTPGroupInfo.mm in Sources */, - C6BA2BA21705F4E6003F0E9E /* MCData.cc in Sources */, - C6BA2BA31705F4E6003F0E9E /* MCHash.cc in Sources */, - C6BA2BA41705F4E6003F0E9E /* MCHashMap.cc in Sources */, + C6BA2BA21705F4E6003F0E9E /* MCData.cpp in Sources */, + C6BA2BA31705F4E6003F0E9E /* MCHash.cpp in Sources */, + C6BA2BA41705F4E6003F0E9E /* MCHashMap.cpp in Sources */, C6BA2BA51705F4E6003F0E9E /* MCLog.cpp in Sources */, - C6BA2BA61705F4E6003F0E9E /* MCObject.cc in Sources */, - C6BA2BA71705F4E6003F0E9E /* MCRange.cc in Sources */, - C6BA2BA81705F4E6003F0E9E /* MCSet.cc in Sources */, - C6BA2BA91705F4E6003F0E9E /* MCString.cc in Sources */, - C6BA2BAA1705F4E6003F0E9E /* MCValue.cc in Sources */, + C6BA2BA61705F4E6003F0E9E /* MCObject.cpp in Sources */, + C6BA2BA71705F4E6003F0E9E /* MCRange.cpp in Sources */, + C6BA2BA81705F4E6003F0E9E /* MCSet.cpp in Sources */, + C6BA2BA91705F4E6003F0E9E /* MCString.cpp in Sources */, + C6BA2BAA1705F4E6003F0E9E /* MCValue.cpp in Sources */, C6BA2BAB1705F4E6003F0E9E /* MCMainThreadMac.mm in Sources */, - C6BA2BAC1705F4E6003F0E9E /* MCOperation.cc in Sources */, - C6BA2BAD1705F4E6003F0E9E /* MCOperationQueue.cc in Sources */, - C61CC25819765763004A28D3 /* MCLibetpan.cc in Sources */, - C6BA2BAE1705F4E6003F0E9E /* MCIMAPFolder.cc in Sources */, - C6BA2BAF1705F4E6003F0E9E /* MCIMAPMessage.cc in Sources */, - C6BA2BB01705F4E6003F0E9E /* MCIMAPMessagePart.cc in Sources */, + C6BA2BAC1705F4E6003F0E9E /* MCOperation.cpp in Sources */, + C6BA2BAD1705F4E6003F0E9E /* MCOperationQueue.cpp in Sources */, + C61CC25819765763004A28D3 /* MCLibetpan.cpp in Sources */, + C6BA2BAE1705F4E6003F0E9E /* MCIMAPFolder.cpp in Sources */, + C6BA2BAF1705F4E6003F0E9E /* MCIMAPMessage.cpp in Sources */, + C6BA2BB01705F4E6003F0E9E /* MCIMAPMessagePart.cpp in Sources */, 84D73776199C00AB005124E5 /* MCONNTPFetchAllArticlesOperation.mm in Sources */, 84CFA99619F725CB00FE35D2 /* MCONNTPFetchServerTimeOperation.mm in Sources */, - C6BA2BB11705F4E6003F0E9E /* MCIMAPMultipart.cc in Sources */, - C6BA2BB21705F4E6003F0E9E /* MCIMAPNamespace.cc in Sources */, - C6BA2BB31705F4E6003F0E9E /* MCIMAPNamespaceItem.cc in Sources */, - C6BA2BB41705F4E6003F0E9E /* MCIMAPPart.cc in Sources */, - C6BA2BB51705F4E6003F0E9E /* MCIMAPSearchExpression.cc in Sources */, - C6BA2BB61705F4E6003F0E9E /* MCIMAPSession.cc in Sources */, - C68B2AF817797389005E61EF /* MCConnectionLoggerUtils.cc in Sources */, - C6BA2BB71705F4E6003F0E9E /* MCPOPMessageInfo.cc in Sources */, - C6BA2BB81705F4E6003F0E9E /* MCPOPSession.cc in Sources */, - 84D7375D199BFDCA005124E5 /* MCNNTPListNewsgroupsOperation.cc in Sources */, - C6BA2BB91705F4E6003F0E9E /* MCAttachment.cc in Sources */, - C6BA2BBA1705F4E6003F0E9E /* MCMessageBuilder.cc in Sources */, - C6BA2BBB1705F4E6003F0E9E /* MCMessageParser.cc in Sources */, - C6BA2BBC1705F4E6003F0E9E /* MCMessagePart.cc in Sources */, + C6BA2BB11705F4E6003F0E9E /* MCIMAPMultipart.cpp in Sources */, + C6BA2BB21705F4E6003F0E9E /* MCIMAPNamespace.cpp in Sources */, + C6BA2BB31705F4E6003F0E9E /* MCIMAPNamespaceItem.cpp in Sources */, + C6BA2BB41705F4E6003F0E9E /* MCIMAPPart.cpp in Sources */, + C6BA2BB51705F4E6003F0E9E /* MCIMAPSearchExpression.cpp in Sources */, + C6BA2BB61705F4E6003F0E9E /* MCIMAPSession.cpp in Sources */, + C68B2AF817797389005E61EF /* MCConnectionLoggerUtils.cpp in Sources */, + C6BA2BB71705F4E6003F0E9E /* MCPOPMessageInfo.cpp in Sources */, + C6BA2BB81705F4E6003F0E9E /* MCPOPSession.cpp in Sources */, + 84D7375D199BFDCA005124E5 /* MCNNTPListNewsgroupsOperation.cpp in Sources */, + C6BA2BB91705F4E6003F0E9E /* MCAttachment.cpp in Sources */, + C6BA2BBA1705F4E6003F0E9E /* MCMessageBuilder.cpp in Sources */, + C6BA2BBB1705F4E6003F0E9E /* MCMessageParser.cpp in Sources */, + C6BA2BBC1705F4E6003F0E9E /* MCMessagePart.cpp in Sources */, 84D7378C199C0260005124E5 /* MCONNTPListNewsgroupsOperation.mm in Sources */, - C6BA2BBD1705F4E6003F0E9E /* MCMultipart.cc in Sources */, - C6BA2BBE1705F4E6003F0E9E /* MCSMTPSession.cc in Sources */, + C6BA2BBD1705F4E6003F0E9E /* MCMultipart.cpp in Sources */, + C6BA2BBE1705F4E6003F0E9E /* MCSMTPSession.cpp in Sources */, 8416A9A217F2871D00B3C7DA /* MCOIMAPNoopOperation.mm in Sources */, - C6BA2BBF1705F4E6003F0E9E /* MCSMTPAsyncSession.cc in Sources */, - C6F7B1A017A1C15200BE78BB /* MCCertificateUtils.cc in Sources */, - 8B0095CF1A00DE7700F84BC0 /* MCSMTPLoginOperation.cc in Sources */, - C6BA2BC01705F4E6003F0E9E /* MCSMTPSendWithDataOperation.cc in Sources */, - C6BA2BC11705F4E6003F0E9E /* MCSMTPOperation.cc in Sources */, - C6BA2BC21705F4E6003F0E9E /* MCSMTPCheckAccountOperation.cc in Sources */, - C6BA2BC31705F4E6003F0E9E /* MCIMAPOperation.cc in Sources */, - C6BA2BC41705F4E6003F0E9E /* MCIMAPCheckAccountOperation.cc in Sources */, - 943F1A9E17D96C5500F0C798 /* MCIMAPConnectOperation.cc in Sources */, - C6BA2BC51705F4E6003F0E9E /* MCIMAPFetchFoldersOperation.cc in Sources */, - C6BA2BC61705F4E6003F0E9E /* MCIMAPRenameFolderOperation.cc in Sources */, + C6BA2BBF1705F4E6003F0E9E /* MCSMTPAsyncSession.cpp in Sources */, + C6F7B1A017A1C15200BE78BB /* MCCertificateUtils.cpp in Sources */, + 8B0095CF1A00DE7700F84BC0 /* MCSMTPLoginOperation.cpp in Sources */, + C6BA2BC01705F4E6003F0E9E /* MCSMTPSendWithDataOperation.cpp in Sources */, + C6BA2BC11705F4E6003F0E9E /* MCSMTPOperation.cpp in Sources */, + C6BA2BC21705F4E6003F0E9E /* MCSMTPCheckAccountOperation.cpp in Sources */, + C6BA2BC31705F4E6003F0E9E /* MCIMAPOperation.cpp in Sources */, + C6BA2BC41705F4E6003F0E9E /* MCIMAPCheckAccountOperation.cpp in Sources */, + 943F1A9E17D96C5500F0C798 /* MCIMAPConnectOperation.cpp in Sources */, + C6BA2BC51705F4E6003F0E9E /* MCIMAPFetchFoldersOperation.cpp in Sources */, + C6BA2BC61705F4E6003F0E9E /* MCIMAPRenameFolderOperation.cpp in Sources */, BD49963819FEC6DD000945BC /* ConvertUTF.c in Sources */, - C6BA2BC71705F4E6003F0E9E /* MCIMAPDeleteFolderOperation.cc in Sources */, - C63D315D17C9155C00A4D993 /* MCIMAPIdentity.cc in Sources */, - 84D73743199BF963005124E5 /* MCNNTPFetchAllArticlesOperation.cc in Sources */, - C6BA2BC81705F4E6003F0E9E /* MCIMAPCreateFolderOperation.cc in Sources */, - C6BA2BC91705F4E6003F0E9E /* MCIMAPSubscribeFolderOperation.cc in Sources */, - 84D7372D199BF66C005124E5 /* MCNNTPAsyncSession.cc in Sources */, - C6BA2BCA1705F4E6003F0E9E /* MCIMAPAppendMessageOperation.cc in Sources */, - C6BA2BCB1705F4E6003F0E9E /* MCIMAPCopyMessagesOperation.cc in Sources */, - C6BA2BCC1705F4E6003F0E9E /* MCIMAPExpungeOperation.cc in Sources */, + C6BA2BC71705F4E6003F0E9E /* MCIMAPDeleteFolderOperation.cpp in Sources */, + C63D315D17C9155C00A4D993 /* MCIMAPIdentity.cpp in Sources */, + 84D73743199BF963005124E5 /* MCNNTPFetchAllArticlesOperation.cpp in Sources */, + C6BA2BC81705F4E6003F0E9E /* MCIMAPCreateFolderOperation.cpp in Sources */, + C6BA2BC91705F4E6003F0E9E /* MCIMAPSubscribeFolderOperation.cpp in Sources */, + 84D7372D199BF66C005124E5 /* MCNNTPAsyncSession.cpp in Sources */, + C6BA2BCA1705F4E6003F0E9E /* MCIMAPAppendMessageOperation.cpp in Sources */, + C6BA2BCB1705F4E6003F0E9E /* MCIMAPCopyMessagesOperation.cpp in Sources */, + C6BA2BCC1705F4E6003F0E9E /* MCIMAPExpungeOperation.cpp in Sources */, C69BA85C17DEFCCB00D601B7 /* NSIndexSet+MCO.m in Sources */, - C6BA2BCD1705F4E6003F0E9E /* MCIMAPFetchMessagesOperation.cc in Sources */, - C6BA2BCE1705F4E6003F0E9E /* MCIMAPFetchContentOperation.cc in Sources */, - 84D73747199BFA8C005124E5 /* MCNNTPCheckAccountOperation.cc in Sources */, - C6BA2BCF1705F4E6003F0E9E /* MCIMAPStoreFlagsOperation.cc in Sources */, - C6BA2BD01705F4E6003F0E9E /* MCIMAPStoreLabelsOperation.cc in Sources */, + C6BA2BCD1705F4E6003F0E9E /* MCIMAPFetchMessagesOperation.cpp in Sources */, + C6BA2BCE1705F4E6003F0E9E /* MCIMAPFetchContentOperation.cpp in Sources */, + 84D73747199BFA8C005124E5 /* MCNNTPCheckAccountOperation.cpp in Sources */, + C6BA2BCF1705F4E6003F0E9E /* MCIMAPStoreFlagsOperation.cpp in Sources */, + C6BA2BD01705F4E6003F0E9E /* MCIMAPStoreLabelsOperation.cpp in Sources */, C643F493189A3D59007EA2F7 /* NSSet+MCO.mm in Sources */, - C6BA2BD11705F4E6003F0E9E /* MCIMAPSearchOperation.cc in Sources */, + C6BA2BD11705F4E6003F0E9E /* MCIMAPSearchOperation.cpp in Sources */, C6E665BE1796500C0063F2CF /* zip.c in Sources */, - C6BA2BD21705F4E6003F0E9E /* MCIMAPIdleOperation.cc in Sources */, - C6BA2BD31705F4E6003F0E9E /* MCIMAPFetchNamespaceOperation.cc in Sources */, - 84D73759199BFC8A005124E5 /* MCNNTPDisconnectOperation.cc in Sources */, - 84B639E917F27EBD003B5BA2 /* MCPOPNoopOperation.cc in Sources */, - 849189A218C93FB7002063A3 /* MCNNTPSession.cc in Sources */, - C6BA2BD41705F4E6003F0E9E /* MCIMAPIdentityOperation.cc in Sources */, - C6BA2BD51705F4E6003F0E9E /* MCIMAPFolderInfoOperation.cc in Sources */, - C6BA2BD61705F4E6003F0E9E /* MCIMAPAsyncConnection.cc in Sources */, - C6BA2BD71705F4E6003F0E9E /* MCPOPAsyncSession.cc in Sources */, - C6BA2BD81705F4E6003F0E9E /* MCPOPFetchHeaderOperation.cc in Sources */, - C6BA2BD91705F4E6003F0E9E /* MCPOPFetchMessageOperation.cc in Sources */, - C6BA2BDA1705F4E6003F0E9E /* MCPOPDeleteMessagesOperation.cc in Sources */, - C6BA2BDB1705F4E6003F0E9E /* MCPOPOperation.cc in Sources */, - C6BA2BDC1705F4E6003F0E9E /* MCPOPFetchMessagesOperation.cc in Sources */, - C6BA2BDD1705F4E6003F0E9E /* MCIMAPAsyncSession.cc in Sources */, + C6BA2BD21705F4E6003F0E9E /* MCIMAPIdleOperation.cpp in Sources */, + C6BA2BD31705F4E6003F0E9E /* MCIMAPFetchNamespaceOperation.cpp in Sources */, + 84D73759199BFC8A005124E5 /* MCNNTPDisconnectOperation.cpp in Sources */, + 84B639E917F27EBD003B5BA2 /* MCPOPNoopOperation.cpp in Sources */, + 849189A218C93FB7002063A3 /* MCNNTPSession.cpp in Sources */, + C6BA2BD41705F4E6003F0E9E /* MCIMAPIdentityOperation.cpp in Sources */, + C6BA2BD51705F4E6003F0E9E /* MCIMAPFolderInfoOperation.cpp in Sources */, + C6BA2BD61705F4E6003F0E9E /* MCIMAPAsyncConnection.cpp in Sources */, + C6BA2BD71705F4E6003F0E9E /* MCPOPAsyncSession.cpp in Sources */, + C6BA2BD81705F4E6003F0E9E /* MCPOPFetchHeaderOperation.cpp in Sources */, + C6BA2BD91705F4E6003F0E9E /* MCPOPFetchMessageOperation.cpp in Sources */, + C6BA2BDA1705F4E6003F0E9E /* MCPOPDeleteMessagesOperation.cpp in Sources */, + C6BA2BDB1705F4E6003F0E9E /* MCPOPOperation.cpp in Sources */, + C6BA2BDC1705F4E6003F0E9E /* MCPOPFetchMessagesOperation.cpp in Sources */, + C6BA2BDD1705F4E6003F0E9E /* MCIMAPAsyncSession.cpp in Sources */, C6BA2BDE1705F4E6003F0E9E /* NSData+MCO.mm in Sources */, C6BA2BDF1705F4E6003F0E9E /* NSString+MCO.mm in Sources */, C6BA2BE01705F4E6003F0E9E /* MCOObjectWrapper.mm in Sources */, - 84D73738199BF7F2005124E5 /* MCNNTPFetchHeaderOperation.cc in Sources */, + 84D73738199BF7F2005124E5 /* MCNNTPFetchHeaderOperation.cpp in Sources */, 84D7376E199C005A005124E5 /* MCONNTPFetchHeaderOperation.mm in Sources */, C6E665B81796500B0063F2CF /* ioapi.c in Sources */, C6BA2BE11705F4E6003F0E9E /* MCOIMAPSession.mm in Sources */, C6BA2BE21705F4E6003F0E9E /* NSError+MCO.mm in Sources */, C6BA2BE31705F4E6003F0E9E /* MCOIMAPFetchFoldersOperation.mm in Sources */, 84B639F217F282B4003B5BA2 /* MCOPOPNoopOperation.mm in Sources */, - 8199FBF219FAF1270040BBC3 /* MCIMAPFetchParsedContentOperation.cc in Sources */, + 8199FBF219FAF1270040BBC3 /* MCIMAPFetchParsedContentOperation.cpp in Sources */, C6BA2BE41705F4E6003F0E9E /* NSDictionary+MCO.mm in Sources */, C6BA2BE51705F4E6003F0E9E /* NSArray+MCO.mm in Sources */, C6BA2BE61705F4E6003F0E9E /* NSObject+MCO.mm in Sources */, - C6BA2BE71705F4E6003F0E9E /* MCAddressDisplay.cc in Sources */, - C6BA2BE81705F4E6003F0E9E /* MCDateFormatter.cc in Sources */, - C6BA2BE91705F4E6003F0E9E /* MCHTMLRenderer.cc in Sources */, - C6BA2BEA1705F4E6003F0E9E /* MCSizeFormatter.cc in Sources */, - 84CFA99019F724E500FE35D2 /* MCNNTPFetchServerTimeOperation.cc in Sources */, - C6BA2BEB1705F4E6003F0E9E /* MCHTMLRendererCallback.cc in Sources */, - C6BA2BEC1705F4E6003F0E9E /* MCHTMLCleaner.cc in Sources */, - C6BA2BED1705F4E6003F0E9E /* MCIMAPSyncResult.cc in Sources */, - C6BA2BEE1705F4E6003F0E9E /* MCIMAPCapabilityOperation.cc in Sources */, - C6BA2BEF1705F4E6003F0E9E /* MCIndexSet.cc in Sources */, + C6BA2BE71705F4E6003F0E9E /* MCAddressDisplay.cpp in Sources */, + C6BA2BE81705F4E6003F0E9E /* MCDateFormatter.cpp in Sources */, + C6BA2BE91705F4E6003F0E9E /* MCHTMLRenderer.cpp in Sources */, + C6BA2BEA1705F4E6003F0E9E /* MCSizeFormatter.cpp in Sources */, + 84CFA99019F724E500FE35D2 /* MCNNTPFetchServerTimeOperation.cpp in Sources */, + C6BA2BEB1705F4E6003F0E9E /* MCHTMLRendererCallback.cpp in Sources */, + C6BA2BEC1705F4E6003F0E9E /* MCHTMLCleaner.cpp in Sources */, + C6BA2BED1705F4E6003F0E9E /* MCIMAPSyncResult.cpp in Sources */, + C6BA2BEE1705F4E6003F0E9E /* MCIMAPCapabilityOperation.cpp in Sources */, + C6BA2BEF1705F4E6003F0E9E /* MCIndexSet.cpp in Sources */, 84D73765199BFFC7005124E5 /* MCONNTPSession.mm in Sources */, C6BA2BF01705F4E6003F0E9E /* MCOAbstractMessage.mm in Sources */, C6BA2BF11705F4E6003F0E9E /* MCOAbstractMessagePart.mm in Sources */, @@ -3447,14 +3447,14 @@ C6BA2C031705F4E6003F0E9E /* MCOIMAPNamespaceItem.mm in Sources */, C6BA2C041705F4E6003F0E9E /* MCOIMAPPart.mm in Sources */, C6BA2C051705F4E6003F0E9E /* MCOIndexSet.mm in Sources */, - 849189AC18C94986002063A3 /* MCNNTPGroupInfo.cc in Sources */, + 849189AC18C94986002063A3 /* MCNNTPGroupInfo.cpp in Sources */, C6BA2C061705F4E6003F0E9E /* MCOAbstractMessageRendererCallback.mm in Sources */, C6BA2C071705F4E6003F0E9E /* MCORange.mm in Sources */, C63D316317C92D8300A4D993 /* MCOIMAPIdentity.mm in Sources */, C6BA2C081705F4E6003F0E9E /* MCOIMAPFolderInfoOperation.mm in Sources */, C6BA2C091705F4E6003F0E9E /* MCOIMAPAppendMessageOperation.mm in Sources */, C6BA2C0A1705F4E6003F0E9E /* MCOIMAPCopyMessagesOperation.mm in Sources */, - DA0F1C7C177C07B300F0D3B4 /* MCIMAPMessageRenderingOperation.cc in Sources */, + DA0F1C7C177C07B300F0D3B4 /* MCIMAPMessageRenderingOperation.cpp in Sources */, C6BA2C0B1705F4E6003F0E9E /* MCOIMAPFetchMessagesOperation.mm in Sources */, C6BA2C0C1705F4E6003F0E9E /* MCOIMAPFetchContentOperation.mm in Sources */, C6BA2C0D1705F4E6003F0E9E /* MCOIMAPSearchOperation.mm in Sources */, @@ -3467,27 +3467,27 @@ C6D4FD4019FB7786001F7E01 /* MCMessageParserMac.mm in Sources */, C6BA2C131705F4E6003F0E9E /* MCOIMAPFolderInfo.m in Sources */, C6BA2C141705F4E6003F0E9E /* MCOIMAPBaseOperation.mm in Sources */, - C608167617759968001F1018 /* MCSMTPDisconnectOperation.cc in Sources */, + C608167617759968001F1018 /* MCSMTPDisconnectOperation.cpp in Sources */, C6A81BC017068E5E00882C15 /* MCOSMTPSession.mm in Sources */, 8B0095CE1A00DE7700F84BC0 /* MCOSMTPLoginOperation.mm in Sources */, C6A81BC417068E9500882C15 /* MCOSMTPSendOperation.mm in Sources */, C6A81BC817068EB000882C15 /* MCOSMTPOperation.mm in Sources */, 8416A99E17F284F400B3C7DA /* MCOSMTPNoopOperation.mm in Sources */, C6A81BD71706903500882C15 /* MCOPOPSession.mm in Sources */, - C6EFFBC9182BBF5700CFF656 /* MCIMAPMultiDisconnectOperation.cc in Sources */, + C6EFFBC9182BBF5700CFF656 /* MCIMAPMultiDisconnectOperation.cpp in Sources */, C6A81BDB1706903E00882C15 /* MCOPOPFetchHeaderOperation.mm in Sources */, - C608167C177635D2001F1018 /* MCIMAPDisconnectOperation.cc in Sources */, + C608167C177635D2001F1018 /* MCIMAPDisconnectOperation.cpp in Sources */, C6A81BDF1706904800882C15 /* MCOPOPFetchMessageOperation.mm in Sources */, - 84D73731199BF704005124E5 /* MCNNTPOperation.cc in Sources */, + 84D73731199BF704005124E5 /* MCNNTPOperation.cpp in Sources */, C6A81BE31706905600882C15 /* MCOPOPOperation.mm in Sources */, C6A81BE71706906D00882C15 /* MCOPOPFetchMessagesOperation.mm in Sources */, C6A81C011707CEE600882C15 /* MCOPOPMessageInfo.mm in Sources */, - C6AC110117114DAF00B715B7 /* MCPOPCheckAccountOperation.cc in Sources */, - C6D6F7FA171E595D006F5B28 /* MCJSON.cc in Sources */, - C6D6F955171E5CB8006F5B28 /* MCMD5.cc in Sources */, - C6D6F957171E5CB8006F5B28 /* MCNull.cc in Sources */, - 84CFA98819F7159700FE35D2 /* MCNNTPFetchOverviewOperation.cc in Sources */, - C6D6F968171FCF9F006F5B28 /* MCJSONParser.cc in Sources */, + C6AC110117114DAF00B715B7 /* MCPOPCheckAccountOperation.cpp in Sources */, + C6D6F7FA171E595D006F5B28 /* MCJSON.cpp in Sources */, + C6D6F955171E5CB8006F5B28 /* MCMD5.cpp in Sources */, + C6D6F957171E5CB8006F5B28 /* MCNull.cpp in Sources */, + 84CFA98819F7159700FE35D2 /* MCNNTPFetchOverviewOperation.cpp in Sources */, + C6D6F968171FCF9F006F5B28 /* MCJSONParser.cpp in Sources */, 84D73769199BFFFC005124E5 /* MCONNTPOperation.mm in Sources */, C668E2C81735C8D500A2BB47 /* MCObjectMac.mm in Sources */, C668E2CD1735CB8900A2BB47 /* MCAutoreleasePoolMac.mm in Sources */, @@ -3496,19 +3496,19 @@ 84D73790199C02A8005124E5 /* MCONNTPDisconnectOperation.mm in Sources */, C6CF62BE175324CE006398B9 /* MCONetService.mm in Sources */, C6EFFBCD1833334900CFF656 /* MCOIMAPMultiDisconnectOperation.mm in Sources */, - C6CF62C7175324F0006398B9 /* MCMailProvider.cc in Sources */, - C6CF62C9175324F0006398B9 /* MCMailProvidersManager.cc in Sources */, - C6CF62CB175324F0006398B9 /* MCNetService.cc in Sources */, + C6CF62C7175324F0006398B9 /* MCMailProvider.cpp in Sources */, + C6CF62C9175324F0006398B9 /* MCMailProvidersManager.cpp in Sources */, + C6CF62CB175324F0006398B9 /* MCNetService.cpp in Sources */, 9EF9AB0A175F2EC60027FA3B /* MCOIMAPFolderStatus.mm in Sources */, - 9EF9AB12175F319A0027FA3B /* MCIMAPFolderStatusOperation.cc in Sources */, + 9EF9AB12175F319A0027FA3B /* MCIMAPFolderStatusOperation.cpp in Sources */, 9EF9AB1A175F36600027FA3B /* MCOIMAPFolderStatusOperation.mm in Sources */, - 9E774D8A1767C7F60065EB9B /* MCIMAPFolderStatus.cc in Sources */, - DAD28C8C1783CFFC00F2BB8F /* MCHTMLBodyRendererTemplateCallback.cc in Sources */, - DAACAD5217886807000B4517 /* MCHTMLRendererIMAPDataCallback.cc in Sources */, + 9E774D8A1767C7F60065EB9B /* MCIMAPFolderStatus.cpp in Sources */, + DAD28C8C1783CFFC00F2BB8F /* MCHTMLBodyRendererTemplateCallback.cpp in Sources */, + DAACAD5217886807000B4517 /* MCHTMLRendererIMAPDataCallback.cpp in Sources */, DA89896E178A47D200F6D90A /* MCOIMAPMessageRenderingOperation.mm in Sources */, 84D73772199C007E005124E5 /* MCONNTPFetchArticleOperation.mm in Sources */, 4B3C1BE317ABFF91008BBF4C /* MCOIMAPQuotaOperation.mm in Sources */, - 4B3C1BE517AC0176008BBF4C /* MCIMAPQuotaOperation.cc in Sources */, + 4B3C1BE517AC0176008BBF4C /* MCIMAPQuotaOperation.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/async/imap/MCIMAPAppendMessageOperation.cc b/src/async/imap/MCIMAPAppendMessageOperation.cc deleted file mode 100644 index 23eaaea0..00000000 --- a/src/async/imap/MCIMAPAppendMessageOperation.cc +++ /dev/null @@ -1,82 +0,0 @@ -// -// MCIMAPAppendMessageOperation.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/12/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPAppendMessageOperation.h" - -#include "MCIMAPSession.h" -#include "MCIMAPAsyncConnection.h" - -using namespace mailcore; - -IMAPAppendMessageOperation::IMAPAppendMessageOperation() -{ - mMessageData = NULL; - mFlags = MessageFlagNone; - mCustomFlags = NULL; - mDate = (time_t) -1; - mCreatedUID = 0; -} - -IMAPAppendMessageOperation::~IMAPAppendMessageOperation() -{ - MC_SAFE_RELEASE(mMessageData); - MC_SAFE_RELEASE(mCustomFlags); -} - -void IMAPAppendMessageOperation::setMessageData(Data * messageData) -{ - MC_SAFE_REPLACE_RETAIN(Data, mMessageData, messageData); -} - -Data * IMAPAppendMessageOperation::messageData() -{ - return mMessageData; -} - -void IMAPAppendMessageOperation::setFlags(MessageFlag flags) -{ - mFlags = flags; -} - -MessageFlag IMAPAppendMessageOperation::flags() -{ - return mFlags; -} - -void IMAPAppendMessageOperation::setCustomFlags(Array * customFlags) -{ - MC_SAFE_REPLACE_COPY(Array, mCustomFlags, customFlags); -} - -Array * IMAPAppendMessageOperation::customFlags() -{ - return customFlags(); -} - -void IMAPAppendMessageOperation::setDate(time_t date) -{ - mDate = date; -} - -time_t IMAPAppendMessageOperation::date() -{ - return mDate; -} - -uint32_t IMAPAppendMessageOperation::createdUID() -{ - return mCreatedUID; -} - -void IMAPAppendMessageOperation::main() -{ - ErrorCode error; - session()->session()->appendMessageWithCustomFlagsAndDate(folder(), mMessageData, mFlags, mCustomFlags, mDate, this, &mCreatedUID, &error); - setError(error); -} - diff --git a/src/async/imap/MCIMAPAppendMessageOperation.cpp b/src/async/imap/MCIMAPAppendMessageOperation.cpp new file mode 100644 index 00000000..23eaaea0 --- /dev/null +++ b/src/async/imap/MCIMAPAppendMessageOperation.cpp @@ -0,0 +1,82 @@ +// +// MCIMAPAppendMessageOperation.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPAppendMessageOperation.h" + +#include "MCIMAPSession.h" +#include "MCIMAPAsyncConnection.h" + +using namespace mailcore; + +IMAPAppendMessageOperation::IMAPAppendMessageOperation() +{ + mMessageData = NULL; + mFlags = MessageFlagNone; + mCustomFlags = NULL; + mDate = (time_t) -1; + mCreatedUID = 0; +} + +IMAPAppendMessageOperation::~IMAPAppendMessageOperation() +{ + MC_SAFE_RELEASE(mMessageData); + MC_SAFE_RELEASE(mCustomFlags); +} + +void IMAPAppendMessageOperation::setMessageData(Data * messageData) +{ + MC_SAFE_REPLACE_RETAIN(Data, mMessageData, messageData); +} + +Data * IMAPAppendMessageOperation::messageData() +{ + return mMessageData; +} + +void IMAPAppendMessageOperation::setFlags(MessageFlag flags) +{ + mFlags = flags; +} + +MessageFlag IMAPAppendMessageOperation::flags() +{ + return mFlags; +} + +void IMAPAppendMessageOperation::setCustomFlags(Array * customFlags) +{ + MC_SAFE_REPLACE_COPY(Array, mCustomFlags, customFlags); +} + +Array * IMAPAppendMessageOperation::customFlags() +{ + return customFlags(); +} + +void IMAPAppendMessageOperation::setDate(time_t date) +{ + mDate = date; +} + +time_t IMAPAppendMessageOperation::date() +{ + return mDate; +} + +uint32_t IMAPAppendMessageOperation::createdUID() +{ + return mCreatedUID; +} + +void IMAPAppendMessageOperation::main() +{ + ErrorCode error; + session()->session()->appendMessageWithCustomFlagsAndDate(folder(), mMessageData, mFlags, mCustomFlags, mDate, this, &mCreatedUID, &error); + setError(error); +} + diff --git a/src/async/imap/MCIMAPAsyncConnection.cc b/src/async/imap/MCIMAPAsyncConnection.cc deleted file mode 100755 index b2fc24c3..00000000 --- a/src/async/imap/MCIMAPAsyncConnection.cc +++ /dev/null @@ -1,424 +0,0 @@ -// -// IMAPAsyncConnection.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/12/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPAsyncConnection.h" - -#include "MCIMAP.h" -#include "MCIMAPFolderInfoOperation.h" -#include "MCIMAPFolderStatusOperation.h" -#include "MCIMAPFetchFoldersOperation.h" -#include "MCIMAPRenameFolderOperation.h" -#include "MCIMAPDeleteFolderOperation.h" -#include "MCIMAPCreateFolderOperation.h" -#include "MCIMAPSubscribeFolderOperation.h" -#include "MCIMAPExpungeOperation.h" -#include "MCIMAPAppendMessageOperation.h" -#include "MCIMAPCopyMessagesOperation.h" -#include "MCIMAPFetchMessagesOperation.h" -#include "MCIMAPFetchContentOperation.h" -#include "MCIMAPFetchParsedContentOperation.h" -#include "MCIMAPStoreFlagsOperation.h" -#include "MCIMAPStoreLabelsOperation.h" -#include "MCIMAPSearchOperation.h" -#include "MCIMAPConnectOperation.h" -#include "MCIMAPCheckAccountOperation.h" -#include "MCIMAPFetchNamespaceOperation.h" -#include "MCIMAPIdleOperation.h" -#include "MCIMAPIdentityOperation.h" -#include "MCIMAPCapabilityOperation.h" -#include "MCIMAPQuotaOperation.h" -#include "MCOperationQueueCallback.h" -#include "MCIMAPDisconnectOperation.h" -#include "MCIMAPNoopOperation.h" -#include "MCIMAPAsyncSession.h" -#include "MCConnectionLogger.h" -#include "MCIMAPMessageRenderingOperation.h" -#include "MCIMAPIdentity.h" - -using namespace mailcore; - -namespace mailcore { - - class IMAPOperationQueueCallback : public Object, public OperationQueueCallback { - public: - IMAPOperationQueueCallback(IMAPAsyncConnection * connection) { - mConnection = connection; - } - - virtual ~IMAPOperationQueueCallback() { - } - - virtual void queueStartRunning() { - mConnection->setQueueRunning(true); - mConnection->owner()->operationRunningStateChanged(); - mConnection->queueStartRunning(); - } - - virtual void queueStoppedRunning() { - mConnection->setQueueRunning(false); - mConnection->tryAutomaticDisconnect(); - mConnection->owner()->operationRunningStateChanged(); - mConnection->queueStoppedRunning(); - } - - private: - IMAPAsyncConnection * mConnection; - }; - - class IMAPConnectionLogger : public Object, public ConnectionLogger { - public: - IMAPConnectionLogger(IMAPAsyncConnection * connection) { - mConnection = connection; - } - - virtual ~IMAPConnectionLogger() { - } - - virtual void log(void * sender, ConnectionLogType logType, Data * buffer) - { - mConnection->logConnection(logType, buffer); - } - - private: - IMAPAsyncConnection * mConnection; - }; - -} - -IMAPAsyncConnection::IMAPAsyncConnection() -{ - mSession = new IMAPSession(); - mQueue = new OperationQueue(); - mDefaultNamespace = NULL; - mClientIdentity = new IMAPIdentity(); - mLastFolder = NULL; - mQueueCallback = new IMAPOperationQueueCallback(this); - mQueue->setCallback(mQueueCallback); - mOwner = NULL; - mConnectionLogger = NULL; - pthread_mutex_init(&mConnectionLoggerLock, NULL); - mInternalLogger = new IMAPConnectionLogger(this); - mAutomaticConfigurationEnabled = true; - mQueueRunning = false; - mScheduledAutomaticDisconnect = false; -} - -IMAPAsyncConnection::~IMAPAsyncConnection() -{ -#if __APPLE__ - cancelDelayedPerformMethodOnDispatchQueue((Object::Method) &IMAPAsyncConnection::tryAutomaticDisconnectAfterDelay, NULL, dispatchQueue()); -#else - cancelDelayedPerformMethod((Object::Method) &IMAPAsyncConnection::tryAutomaticDisconnectAfterDelay, NULL); -#endif - pthread_mutex_destroy(&mConnectionLoggerLock); - MC_SAFE_RELEASE(mInternalLogger); - MC_SAFE_RELEASE(mQueueCallback); - MC_SAFE_RELEASE(mLastFolder); - MC_SAFE_RELEASE(mClientIdentity); - MC_SAFE_RELEASE(mDefaultNamespace); - MC_SAFE_RELEASE(mQueue); - MC_SAFE_RELEASE(mSession); -} - -void IMAPAsyncConnection::setHostname(String * hostname) -{ - mSession->setHostname(hostname); -} - -String * IMAPAsyncConnection::hostname() -{ - return mSession->hostname(); -} - -void IMAPAsyncConnection::setPort(unsigned int port) -{ - mSession->setPort(port); -} - -unsigned int IMAPAsyncConnection::port() -{ - return mSession->port(); -} - -void IMAPAsyncConnection::setUsername(String * username) -{ - mSession->setUsername(username); -} - -String * IMAPAsyncConnection::username() -{ - return mSession->username(); -} - -void IMAPAsyncConnection::setPassword(String * password) -{ - mSession->setPassword(password); -} - -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); -} - -AuthType IMAPAsyncConnection::authType() -{ - return mSession->authType(); -} - -void IMAPAsyncConnection::setConnectionType(ConnectionType connectionType) -{ - mSession->setConnectionType(connectionType); -} - -ConnectionType IMAPAsyncConnection::connectionType() -{ - return mSession->connectionType(); -} - -void IMAPAsyncConnection::setTimeout(time_t timeout) -{ - mSession->setTimeout(timeout); -} - -time_t IMAPAsyncConnection::timeout() -{ - return mSession->timeout(); -} - -void IMAPAsyncConnection::setCheckCertificateEnabled(bool enabled) -{ - mSession->setCheckCertificateEnabled(enabled); -} - -bool IMAPAsyncConnection::isCheckCertificateEnabled() -{ - return mSession->isCheckCertificateEnabled(); -} - -void IMAPAsyncConnection::setVoIPEnabled(bool enabled) -{ - mSession->setVoIPEnabled(enabled); -} - -bool IMAPAsyncConnection::isVoIPEnabled() -{ - return mSession->isVoIPEnabled(); -} - -void IMAPAsyncConnection::setDefaultNamespace(IMAPNamespace * ns) -{ - mSession->setDefaultNamespace(ns); - MC_SAFE_REPLACE_RETAIN(IMAPNamespace, mDefaultNamespace, ns); -} - -IMAPNamespace * IMAPAsyncConnection::defaultNamespace() -{ - return mDefaultNamespace; -} - -void IMAPAsyncConnection::setClientIdentity(IMAPIdentity * identity) -{ - MC_SAFE_REPLACE_COPY(IMAPIdentity, mClientIdentity, identity); - mc_foreacharray(String, key, identity->allInfoKeys()) { - mSession->clientIdentity()->setInfoForKey(key, identity->infoForKey(key)); - } -} - -IMAPIdentity * IMAPAsyncConnection::clientIdentity() -{ - return mClientIdentity; -} - -IMAPOperation * IMAPAsyncConnection::disconnectOperation() -{ - IMAPDisconnectOperation * op = new IMAPDisconnectOperation(); - op->setSession(this); - op->autorelease(); - return op; -} - -IMAPSession * IMAPAsyncConnection::session() -{ - return mSession; -} - -unsigned int IMAPAsyncConnection::operationsCount() -{ - return mQueue->count(); -} - -void IMAPAsyncConnection::cancelAllOperations() -{ - mQueue->cancelAllOperations(); -} - -void IMAPAsyncConnection::runOperation(IMAPOperation * operation) -{ - if (mScheduledAutomaticDisconnect) { -#if __APPLE__ - cancelDelayedPerformMethodOnDispatchQueue((Object::Method) &IMAPAsyncConnection::tryAutomaticDisconnectAfterDelay, NULL, dispatchQueue()); -#else - cancelDelayedPerformMethod((Object::Method) &IMAPAsyncConnection::tryAutomaticDisconnectAfterDelay, NULL); -#endif - mOwner->release(); - mScheduledAutomaticDisconnect = false; - } - mQueue->addOperation(operation); -} - -void IMAPAsyncConnection::tryAutomaticDisconnect() -{ - // It's safe since no thread is running when this function is called. - if (mSession->isDisconnected()) { - return; - } - - bool scheduledAutomaticDisconnect = mScheduledAutomaticDisconnect; - if (scheduledAutomaticDisconnect) { -#if __APPLE__ - cancelDelayedPerformMethodOnDispatchQueue((Object::Method) &IMAPAsyncConnection::tryAutomaticDisconnectAfterDelay, NULL, dispatchQueue()); -#else - cancelDelayedPerformMethod((Object::Method) &IMAPAsyncConnection::tryAutomaticDisconnectAfterDelay, NULL); -#endif - } - - mOwner->retain(); - mScheduledAutomaticDisconnect = true; -#if __APPLE__ - performMethodOnDispatchQueueAfterDelay((Object::Method) &IMAPAsyncConnection::tryAutomaticDisconnectAfterDelay, NULL, dispatchQueue(), 30); -#else - performMethodAfterDelay((Object::Method) &IMAPAsyncConnection::tryAutomaticDisconnectAfterDelay, NULL, 30); -#endif - - if (scheduledAutomaticDisconnect) { - mOwner->release(); - } -} - -void IMAPAsyncConnection::tryAutomaticDisconnectAfterDelay(void * context) -{ - mScheduledAutomaticDisconnect = false; - - IMAPOperation * op = disconnectOperation(); - op->start(); - - mOwner->release(); -} - -void IMAPAsyncConnection::queueStartRunning() -{ - this->retain(); - mOwner->retain(); -} - -void IMAPAsyncConnection::queueStoppedRunning() -{ - mOwner->release(); - this->release(); -} - -void IMAPAsyncConnection::setLastFolder(String * folder) -{ - MC_SAFE_REPLACE_COPY(String, mLastFolder, folder); -} - -String * IMAPAsyncConnection::lastFolder() -{ - return mLastFolder; -} - -void IMAPAsyncConnection::setOwner(IMAPAsyncSession * owner) -{ - mOwner = owner; -} - -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); -} - -void IMAPAsyncConnection::setAutomaticConfigurationEnabled(bool enabled) -{ - mAutomaticConfigurationEnabled = enabled; - mSession->setAutomaticConfigurationEnabled(enabled); -} - -bool IMAPAsyncConnection::isAutomaticConfigurationEnabled() -{ - return mAutomaticConfigurationEnabled; -} - -bool IMAPAsyncConnection::isQueueRunning() -{ - return mQueueRunning; -} - -void IMAPAsyncConnection::setQueueRunning(bool running) -{ - mQueueRunning = running; -} - -#if __APPLE__ -void IMAPAsyncConnection::setDispatchQueue(dispatch_queue_t dispatchQueue) -{ - mQueue->setDispatchQueue(dispatchQueue); -} - -dispatch_queue_t IMAPAsyncConnection::dispatchQueue() -{ - return mQueue->dispatchQueue(); -} -#endif diff --git a/src/async/imap/MCIMAPAsyncConnection.cpp b/src/async/imap/MCIMAPAsyncConnection.cpp new file mode 100755 index 00000000..b2fc24c3 --- /dev/null +++ b/src/async/imap/MCIMAPAsyncConnection.cpp @@ -0,0 +1,424 @@ +// +// IMAPAsyncConnection.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPAsyncConnection.h" + +#include "MCIMAP.h" +#include "MCIMAPFolderInfoOperation.h" +#include "MCIMAPFolderStatusOperation.h" +#include "MCIMAPFetchFoldersOperation.h" +#include "MCIMAPRenameFolderOperation.h" +#include "MCIMAPDeleteFolderOperation.h" +#include "MCIMAPCreateFolderOperation.h" +#include "MCIMAPSubscribeFolderOperation.h" +#include "MCIMAPExpungeOperation.h" +#include "MCIMAPAppendMessageOperation.h" +#include "MCIMAPCopyMessagesOperation.h" +#include "MCIMAPFetchMessagesOperation.h" +#include "MCIMAPFetchContentOperation.h" +#include "MCIMAPFetchParsedContentOperation.h" +#include "MCIMAPStoreFlagsOperation.h" +#include "MCIMAPStoreLabelsOperation.h" +#include "MCIMAPSearchOperation.h" +#include "MCIMAPConnectOperation.h" +#include "MCIMAPCheckAccountOperation.h" +#include "MCIMAPFetchNamespaceOperation.h" +#include "MCIMAPIdleOperation.h" +#include "MCIMAPIdentityOperation.h" +#include "MCIMAPCapabilityOperation.h" +#include "MCIMAPQuotaOperation.h" +#include "MCOperationQueueCallback.h" +#include "MCIMAPDisconnectOperation.h" +#include "MCIMAPNoopOperation.h" +#include "MCIMAPAsyncSession.h" +#include "MCConnectionLogger.h" +#include "MCIMAPMessageRenderingOperation.h" +#include "MCIMAPIdentity.h" + +using namespace mailcore; + +namespace mailcore { + + class IMAPOperationQueueCallback : public Object, public OperationQueueCallback { + public: + IMAPOperationQueueCallback(IMAPAsyncConnection * connection) { + mConnection = connection; + } + + virtual ~IMAPOperationQueueCallback() { + } + + virtual void queueStartRunning() { + mConnection->setQueueRunning(true); + mConnection->owner()->operationRunningStateChanged(); + mConnection->queueStartRunning(); + } + + virtual void queueStoppedRunning() { + mConnection->setQueueRunning(false); + mConnection->tryAutomaticDisconnect(); + mConnection->owner()->operationRunningStateChanged(); + mConnection->queueStoppedRunning(); + } + + private: + IMAPAsyncConnection * mConnection; + }; + + class IMAPConnectionLogger : public Object, public ConnectionLogger { + public: + IMAPConnectionLogger(IMAPAsyncConnection * connection) { + mConnection = connection; + } + + virtual ~IMAPConnectionLogger() { + } + + virtual void log(void * sender, ConnectionLogType logType, Data * buffer) + { + mConnection->logConnection(logType, buffer); + } + + private: + IMAPAsyncConnection * mConnection; + }; + +} + +IMAPAsyncConnection::IMAPAsyncConnection() +{ + mSession = new IMAPSession(); + mQueue = new OperationQueue(); + mDefaultNamespace = NULL; + mClientIdentity = new IMAPIdentity(); + mLastFolder = NULL; + mQueueCallback = new IMAPOperationQueueCallback(this); + mQueue->setCallback(mQueueCallback); + mOwner = NULL; + mConnectionLogger = NULL; + pthread_mutex_init(&mConnectionLoggerLock, NULL); + mInternalLogger = new IMAPConnectionLogger(this); + mAutomaticConfigurationEnabled = true; + mQueueRunning = false; + mScheduledAutomaticDisconnect = false; +} + +IMAPAsyncConnection::~IMAPAsyncConnection() +{ +#if __APPLE__ + cancelDelayedPerformMethodOnDispatchQueue((Object::Method) &IMAPAsyncConnection::tryAutomaticDisconnectAfterDelay, NULL, dispatchQueue()); +#else + cancelDelayedPerformMethod((Object::Method) &IMAPAsyncConnection::tryAutomaticDisconnectAfterDelay, NULL); +#endif + pthread_mutex_destroy(&mConnectionLoggerLock); + MC_SAFE_RELEASE(mInternalLogger); + MC_SAFE_RELEASE(mQueueCallback); + MC_SAFE_RELEASE(mLastFolder); + MC_SAFE_RELEASE(mClientIdentity); + MC_SAFE_RELEASE(mDefaultNamespace); + MC_SAFE_RELEASE(mQueue); + MC_SAFE_RELEASE(mSession); +} + +void IMAPAsyncConnection::setHostname(String * hostname) +{ + mSession->setHostname(hostname); +} + +String * IMAPAsyncConnection::hostname() +{ + return mSession->hostname(); +} + +void IMAPAsyncConnection::setPort(unsigned int port) +{ + mSession->setPort(port); +} + +unsigned int IMAPAsyncConnection::port() +{ + return mSession->port(); +} + +void IMAPAsyncConnection::setUsername(String * username) +{ + mSession->setUsername(username); +} + +String * IMAPAsyncConnection::username() +{ + return mSession->username(); +} + +void IMAPAsyncConnection::setPassword(String * password) +{ + mSession->setPassword(password); +} + +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); +} + +AuthType IMAPAsyncConnection::authType() +{ + return mSession->authType(); +} + +void IMAPAsyncConnection::setConnectionType(ConnectionType connectionType) +{ + mSession->setConnectionType(connectionType); +} + +ConnectionType IMAPAsyncConnection::connectionType() +{ + return mSession->connectionType(); +} + +void IMAPAsyncConnection::setTimeout(time_t timeout) +{ + mSession->setTimeout(timeout); +} + +time_t IMAPAsyncConnection::timeout() +{ + return mSession->timeout(); +} + +void IMAPAsyncConnection::setCheckCertificateEnabled(bool enabled) +{ + mSession->setCheckCertificateEnabled(enabled); +} + +bool IMAPAsyncConnection::isCheckCertificateEnabled() +{ + return mSession->isCheckCertificateEnabled(); +} + +void IMAPAsyncConnection::setVoIPEnabled(bool enabled) +{ + mSession->setVoIPEnabled(enabled); +} + +bool IMAPAsyncConnection::isVoIPEnabled() +{ + return mSession->isVoIPEnabled(); +} + +void IMAPAsyncConnection::setDefaultNamespace(IMAPNamespace * ns) +{ + mSession->setDefaultNamespace(ns); + MC_SAFE_REPLACE_RETAIN(IMAPNamespace, mDefaultNamespace, ns); +} + +IMAPNamespace * IMAPAsyncConnection::defaultNamespace() +{ + return mDefaultNamespace; +} + +void IMAPAsyncConnection::setClientIdentity(IMAPIdentity * identity) +{ + MC_SAFE_REPLACE_COPY(IMAPIdentity, mClientIdentity, identity); + mc_foreacharray(String, key, identity->allInfoKeys()) { + mSession->clientIdentity()->setInfoForKey(key, identity->infoForKey(key)); + } +} + +IMAPIdentity * IMAPAsyncConnection::clientIdentity() +{ + return mClientIdentity; +} + +IMAPOperation * IMAPAsyncConnection::disconnectOperation() +{ + IMAPDisconnectOperation * op = new IMAPDisconnectOperation(); + op->setSession(this); + op->autorelease(); + return op; +} + +IMAPSession * IMAPAsyncConnection::session() +{ + return mSession; +} + +unsigned int IMAPAsyncConnection::operationsCount() +{ + return mQueue->count(); +} + +void IMAPAsyncConnection::cancelAllOperations() +{ + mQueue->cancelAllOperations(); +} + +void IMAPAsyncConnection::runOperation(IMAPOperation * operation) +{ + if (mScheduledAutomaticDisconnect) { +#if __APPLE__ + cancelDelayedPerformMethodOnDispatchQueue((Object::Method) &IMAPAsyncConnection::tryAutomaticDisconnectAfterDelay, NULL, dispatchQueue()); +#else + cancelDelayedPerformMethod((Object::Method) &IMAPAsyncConnection::tryAutomaticDisconnectAfterDelay, NULL); +#endif + mOwner->release(); + mScheduledAutomaticDisconnect = false; + } + mQueue->addOperation(operation); +} + +void IMAPAsyncConnection::tryAutomaticDisconnect() +{ + // It's safe since no thread is running when this function is called. + if (mSession->isDisconnected()) { + return; + } + + bool scheduledAutomaticDisconnect = mScheduledAutomaticDisconnect; + if (scheduledAutomaticDisconnect) { +#if __APPLE__ + cancelDelayedPerformMethodOnDispatchQueue((Object::Method) &IMAPAsyncConnection::tryAutomaticDisconnectAfterDelay, NULL, dispatchQueue()); +#else + cancelDelayedPerformMethod((Object::Method) &IMAPAsyncConnection::tryAutomaticDisconnectAfterDelay, NULL); +#endif + } + + mOwner->retain(); + mScheduledAutomaticDisconnect = true; +#if __APPLE__ + performMethodOnDispatchQueueAfterDelay((Object::Method) &IMAPAsyncConnection::tryAutomaticDisconnectAfterDelay, NULL, dispatchQueue(), 30); +#else + performMethodAfterDelay((Object::Method) &IMAPAsyncConnection::tryAutomaticDisconnectAfterDelay, NULL, 30); +#endif + + if (scheduledAutomaticDisconnect) { + mOwner->release(); + } +} + +void IMAPAsyncConnection::tryAutomaticDisconnectAfterDelay(void * context) +{ + mScheduledAutomaticDisconnect = false; + + IMAPOperation * op = disconnectOperation(); + op->start(); + + mOwner->release(); +} + +void IMAPAsyncConnection::queueStartRunning() +{ + this->retain(); + mOwner->retain(); +} + +void IMAPAsyncConnection::queueStoppedRunning() +{ + mOwner->release(); + this->release(); +} + +void IMAPAsyncConnection::setLastFolder(String * folder) +{ + MC_SAFE_REPLACE_COPY(String, mLastFolder, folder); +} + +String * IMAPAsyncConnection::lastFolder() +{ + return mLastFolder; +} + +void IMAPAsyncConnection::setOwner(IMAPAsyncSession * owner) +{ + mOwner = owner; +} + +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); +} + +void IMAPAsyncConnection::setAutomaticConfigurationEnabled(bool enabled) +{ + mAutomaticConfigurationEnabled = enabled; + mSession->setAutomaticConfigurationEnabled(enabled); +} + +bool IMAPAsyncConnection::isAutomaticConfigurationEnabled() +{ + return mAutomaticConfigurationEnabled; +} + +bool IMAPAsyncConnection::isQueueRunning() +{ + return mQueueRunning; +} + +void IMAPAsyncConnection::setQueueRunning(bool running) +{ + mQueueRunning = running; +} + +#if __APPLE__ +void IMAPAsyncConnection::setDispatchQueue(dispatch_queue_t dispatchQueue) +{ + mQueue->setDispatchQueue(dispatchQueue); +} + +dispatch_queue_t IMAPAsyncConnection::dispatchQueue() +{ + return mQueue->dispatchQueue(); +} +#endif diff --git a/src/async/imap/MCIMAPAsyncSession.cc b/src/async/imap/MCIMAPAsyncSession.cc deleted file mode 100755 index f3a55a5e..00000000 --- a/src/async/imap/MCIMAPAsyncSession.cc +++ /dev/null @@ -1,848 +0,0 @@ -// -// MCIMAPAsyncSession.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/17/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPAsyncSession.h" - -#include "MCIMAPAsyncConnection.h" -#include "MCIMAPNamespace.h" -#include "MCOperationQueueCallback.h" -#include "MCConnectionLogger.h" -#include "MCIMAPSession.h" -#include "MCIMAPIdentity.h" -#include "MCIMAPMultiDisconnectOperation.h" - -#include "MCIMAPFolderInfoOperation.h" -#include "MCIMAPFolderStatusOperation.h" -#include "MCIMAPFetchFoldersOperation.h" -#include "MCIMAPRenameFolderOperation.h" -#include "MCIMAPDeleteFolderOperation.h" -#include "MCIMAPCreateFolderOperation.h" -#include "MCIMAPSubscribeFolderOperation.h" -#include "MCIMAPExpungeOperation.h" -#include "MCIMAPAppendMessageOperation.h" -#include "MCIMAPCopyMessagesOperation.h" -#include "MCIMAPFetchMessagesOperation.h" -#include "MCIMAPFetchContentOperation.h" -#include "MCIMAPFetchParsedContentOperation.h" -#include "MCIMAPStoreFlagsOperation.h" -#include "MCIMAPStoreLabelsOperation.h" -#include "MCIMAPSearchOperation.h" -#include "MCIMAPConnectOperation.h" -#include "MCIMAPCheckAccountOperation.h" -#include "MCIMAPFetchNamespaceOperation.h" -#include "MCIMAPIdleOperation.h" -#include "MCIMAPIdentityOperation.h" -#include "MCIMAPCapabilityOperation.h" -#include "MCIMAPQuotaOperation.h" -#include "MCIMAPDisconnectOperation.h" -#include "MCIMAPNoopOperation.h" -#include "MCIMAPMessageRenderingOperation.h" - -#define DEFAULT_MAX_CONNECTIONS 3 - -using namespace mailcore; - -IMAPAsyncSession::IMAPAsyncSession() -{ - mSessions = new Array(); - mMaximumConnections = DEFAULT_MAX_CONNECTIONS; - mAllowsFolderConcurrentAccessEnabled = true; - - mHostname = NULL; - mPort = 0; - mUsername = NULL; - mPassword = NULL; - mOAuth2Token = NULL; - mAuthType = AuthTypeSASLNone; - mConnectionType = ConnectionTypeClear; - mCheckCertificateEnabled = true; - mVoIPEnabled = true; - mDefaultNamespace = NULL; - mTimeout = 30.; - mConnectionLogger = NULL; - mAutomaticConfigurationDone = false; - mServerIdentity = new IMAPIdentity(); - mClientIdentity = new IMAPIdentity(); - mOperationQueueCallback = NULL; -#if __APPLE__ - mDispatchQueue = dispatch_get_main_queue(); -#endif - mGmailUserDisplayName = NULL; -} - -IMAPAsyncSession::~IMAPAsyncSession() -{ -#if __APPLE__ - if (mDispatchQueue != NULL) { - dispatch_release(mDispatchQueue); - } -#endif - MC_SAFE_RELEASE(mGmailUserDisplayName); - MC_SAFE_RELEASE(mServerIdentity); - MC_SAFE_RELEASE(mClientIdentity); - 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) -{ - MC_SAFE_REPLACE_COPY(String, mHostname, hostname); -} - -String * IMAPAsyncSession::hostname() -{ - return mHostname; -} - -void IMAPAsyncSession::setPort(unsigned int port) -{ - mPort = port; -} - -unsigned int IMAPAsyncSession::port() -{ - return mPort; -} - -void IMAPAsyncSession::setUsername(String * username) -{ - MC_SAFE_REPLACE_COPY(String, mUsername, username); -} - -String * IMAPAsyncSession::username() -{ - return mUsername; -} - -void IMAPAsyncSession::setPassword(String * password) -{ - MC_SAFE_REPLACE_COPY(String, mPassword, password); -} - -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; -} - -AuthType IMAPAsyncSession::authType() -{ - return mAuthType; -} - -void IMAPAsyncSession::setConnectionType(ConnectionType connectionType) -{ - mConnectionType = connectionType; -} - -ConnectionType IMAPAsyncSession::connectionType() -{ - return mConnectionType; -} - -void IMAPAsyncSession::setTimeout(time_t timeout) -{ - mTimeout = timeout; -} - -time_t IMAPAsyncSession::timeout() -{ - return mTimeout; -} - -void IMAPAsyncSession::setCheckCertificateEnabled(bool enabled) -{ - mCheckCertificateEnabled = enabled; -} - -bool IMAPAsyncSession::isCheckCertificateEnabled() -{ - return mCheckCertificateEnabled; -} - -void IMAPAsyncSession::setVoIPEnabled(bool enabled) -{ - mVoIPEnabled = enabled; -} - -bool IMAPAsyncSession::isVoIPEnabled() -{ - return mVoIPEnabled; -} - -IMAPNamespace * IMAPAsyncSession::defaultNamespace() -{ - return mDefaultNamespace; -} - -void IMAPAsyncSession::setDefaultNamespace(IMAPNamespace * ns) -{ - MC_SAFE_REPLACE_RETAIN(IMAPNamespace, mDefaultNamespace, ns); -} - -void IMAPAsyncSession::setAllowsFolderConcurrentAccessEnabled(bool enabled) -{ - mAllowsFolderConcurrentAccessEnabled = enabled; -} - -bool IMAPAsyncSession::allowsFolderConcurrentAccessEnabled() -{ - return mAllowsFolderConcurrentAccessEnabled; -} - -void IMAPAsyncSession::setMaximumConnections(unsigned int maxConnections) -{ - mMaximumConnections = maxConnections; -} - -unsigned int IMAPAsyncSession::maximumConnections() -{ - return mMaximumConnections; -} - -IMAPIdentity * IMAPAsyncSession::serverIdentity() -{ - return mServerIdentity; -} - -IMAPIdentity * IMAPAsyncSession::clientIdentity() -{ - return mClientIdentity; -} - -String * IMAPAsyncSession::gmailUserDisplayName() -{ - return mGmailUserDisplayName; -} - -IMAPAsyncConnection * IMAPAsyncSession::session() -{ - IMAPAsyncConnection * session = new IMAPAsyncConnection(); - session->setConnectionLogger(mConnectionLogger); - session->setOwner(this); - session->autorelease(); - - session->setHostname(mHostname); - session->setPort(mPort); - session->setUsername(mUsername); - session->setPassword(mPassword); - session->setOAuth2Token(mOAuth2Token); - session->setAuthType(mAuthType); - session->setConnectionType(mConnectionType); - session->setTimeout(mTimeout); - session->setCheckCertificateEnabled(mCheckCertificateEnabled); - session->setVoIPEnabled(mVoIPEnabled); - session->setDefaultNamespace(mDefaultNamespace); - session->setClientIdentity(mClientIdentity); -#if __APPLE__ - session->setDispatchQueue(mDispatchQueue); -#endif -#if 0 // should be implemented properly - if (mAutomaticConfigurationDone) { - session->setAutomaticConfigurationEnabled(false); - } -#endif - - return session; -} - -IMAPAsyncConnection * IMAPAsyncSession::sessionForFolder(String * folder, bool urgent) -{ - if (folder == NULL) { - return availableSession(); - } - else { - IMAPAsyncConnection * s = NULL; - if (urgent && mAllowsFolderConcurrentAccessEnabled) { - s = availableSession(); - if (s->operationsCount() == 0) { - s->setLastFolder(folder); - return s; - } - } - - s = matchingSessionForFolder(folder); - s->setLastFolder(folder); - return s; - } -} - -IMAPAsyncConnection * IMAPAsyncSession::availableSession() -{ - if (mMaximumConnections == 0) { - for(unsigned int i = 0 ; i < mSessions->count() ; i ++) { - IMAPAsyncConnection * s = (IMAPAsyncConnection *) mSessions->objectAtIndex(i); - if (s->operationsCount() == 0) - return s; - } - IMAPAsyncConnection * chosenSession = session(); - mSessions->addObject(chosenSession); - return chosenSession; - } - else { - IMAPAsyncConnection * chosenSession = NULL; - unsigned int minOperationsCount = 0; - for(unsigned int i = 0 ; i < mSessions->count() ; i ++) { - IMAPAsyncConnection * s = (IMAPAsyncConnection *) mSessions->objectAtIndex(i); - if (chosenSession == NULL) { - chosenSession = s; - minOperationsCount = s->operationsCount(); - } - else if (s->operationsCount() < minOperationsCount) { - chosenSession = s; - minOperationsCount = s->operationsCount(); - } - } - if (mSessions->count() < mMaximumConnections) { - if ((chosenSession != NULL) && (minOperationsCount == 0)) { - return chosenSession; - } - chosenSession = session(); - mSessions->addObject(chosenSession); - return chosenSession; - } - else { - return chosenSession; - } - } -} - -IMAPAsyncConnection * IMAPAsyncSession::matchingSessionForFolder(String * folder) -{ - for(unsigned int i = 0 ; i < mSessions->count() ; i ++) { - IMAPAsyncConnection * currentSession = (IMAPAsyncConnection *) mSessions->objectAtIndex(i); - if (currentSession->lastFolder() != NULL) { - if (currentSession->lastFolder()->isEqual(folder)) { - return currentSession; - } - } - else { - return currentSession; - } - } - return availableSession(); -} - -IMAPFolderInfoOperation * IMAPAsyncSession::folderInfoOperation(String * folder) -{ - IMAPFolderInfoOperation * op = new IMAPFolderInfoOperation(); - op->setMainSession(this); - op->setFolder(folder); - op->autorelease(); - return op; -} - -IMAPFolderStatusOperation * IMAPAsyncSession::folderStatusOperation(String * folder) -{ - IMAPFolderStatusOperation * op = new IMAPFolderStatusOperation(); - op->setMainSession(this); - op->setFolder(folder); - op->autorelease(); - return op; -} - -IMAPFetchFoldersOperation * IMAPAsyncSession::fetchSubscribedFoldersOperation() -{ - IMAPFetchFoldersOperation * op = new IMAPFetchFoldersOperation(); - op->setMainSession(this); - op->setFetchSubscribedEnabled(true); - op->autorelease(); - return op; -} - -IMAPFetchFoldersOperation * IMAPAsyncSession::fetchAllFoldersOperation() -{ - IMAPFetchFoldersOperation * op = new IMAPFetchFoldersOperation(); - op->setMainSession(this); - op->autorelease(); - return op; -} - -IMAPOperation * IMAPAsyncSession::renameFolderOperation(String * folder, String * otherName) -{ - IMAPRenameFolderOperation * op = new IMAPRenameFolderOperation(); - op->setMainSession(this); - op->setFolder(folder); - op->setOtherName(otherName); - op->autorelease(); - return op; -} - -IMAPOperation * IMAPAsyncSession::deleteFolderOperation(String * folder) -{ - IMAPDeleteFolderOperation * op = new IMAPDeleteFolderOperation(); - op->setMainSession(this); - op->setFolder(folder); - op->autorelease(); - return op; -} - -IMAPOperation * IMAPAsyncSession::createFolderOperation(String * folder) -{ - IMAPCreateFolderOperation * op = new IMAPCreateFolderOperation(); - op->setMainSession(this); - op->setFolder(folder); - op->autorelease(); - return op; -} - -IMAPOperation * IMAPAsyncSession::subscribeFolderOperation(String * folder) -{ - IMAPSubscribeFolderOperation * op = new IMAPSubscribeFolderOperation(); - op->setMainSession(this); - op->setFolder(folder); - op->autorelease(); - return op; -} - -IMAPOperation * IMAPAsyncSession::unsubscribeFolderOperation(String * folder) -{ - IMAPSubscribeFolderOperation * op = new IMAPSubscribeFolderOperation(); - op->setMainSession(this); - op->setUnsubscribeEnabled(true); - op->setFolder(folder); - op->autorelease(); - return op; -} - -IMAPAppendMessageOperation * IMAPAsyncSession::appendMessageOperation(String * folder, Data * messageData, MessageFlag flags, Array * customFlags) -{ - IMAPAppendMessageOperation * op = new IMAPAppendMessageOperation(); - op->setMainSession(this); - op->setFolder(folder); - op->setMessageData(messageData); - op->setFlags(flags); - op->setCustomFlags(customFlags); - op->autorelease(); - return op; -} - -IMAPCopyMessagesOperation * IMAPAsyncSession::copyMessagesOperation(String * folder, IndexSet * uids, String * destFolder) -{ - IMAPCopyMessagesOperation * op = new IMAPCopyMessagesOperation(); - op->setMainSession(this); - op->setFolder(folder); - op->setUids(uids); - op->setDestFolder(destFolder); - op->autorelease(); - return op; -} - -IMAPOperation * IMAPAsyncSession::expungeOperation(String * folder) -{ - IMAPExpungeOperation * op = new IMAPExpungeOperation(); - op->setMainSession(this); - op->setFolder(folder); - op->autorelease(); - return op; -} - -IMAPFetchMessagesOperation * IMAPAsyncSession::fetchMessagesByUIDOperation(String * folder, IMAPMessagesRequestKind requestKind, - IndexSet * uids) -{ - IMAPFetchMessagesOperation * op = new IMAPFetchMessagesOperation(); - op->setMainSession(this); - op->setFolder(folder); - op->setKind(requestKind); - op->setFetchByUidEnabled(true); - op->setIndexes(uids); - op->autorelease(); - return op; -} - -IMAPFetchMessagesOperation * IMAPAsyncSession::fetchMessagesByNumberOperation(String * folder, IMAPMessagesRequestKind requestKind, - IndexSet * numbers) -{ - IMAPFetchMessagesOperation * op = new IMAPFetchMessagesOperation(); - op->setMainSession(this); - op->setFolder(folder); - op->setKind(requestKind); - op->setIndexes(numbers); - op->autorelease(); - return op; -} - -IMAPFetchMessagesOperation * IMAPAsyncSession::syncMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, - IndexSet * uids, uint64_t modSeq) -{ - IMAPFetchMessagesOperation * op = new IMAPFetchMessagesOperation(); - op->setMainSession(this); - op->setFolder(folder); - op->setKind(requestKind); - op->setFetchByUidEnabled(true); - op->setIndexes(uids); - op->setModSequenceValue(modSeq); - op->autorelease(); - return op; -} - -IMAPFetchContentOperation * IMAPAsyncSession::fetchMessageByUIDOperation(String * folder, uint32_t uid, bool urgent) -{ - IMAPFetchContentOperation * op = new IMAPFetchContentOperation(); - op->setMainSession(this); - op->setFolder(folder); - op->setUid(uid); - op->setUrgent(urgent); - op->autorelease(); - return op; -} - -IMAPFetchContentOperation * IMAPAsyncSession::fetchMessageAttachmentByUIDOperation(String * folder, uint32_t uid, String * partID, - Encoding encoding, bool urgent) -{ - IMAPFetchContentOperation * op = new IMAPFetchContentOperation(); - op->setMainSession(this); - op->setFolder(folder); - op->setUid(uid); - op->setPartID(partID); - op->setEncoding(encoding); - op->setUrgent(urgent); - op->autorelease(); - return op; -} - -IMAPFetchContentOperation * IMAPAsyncSession::fetchMessageByNumberOperation(String * folder, uint32_t number, bool urgent) -{ - IMAPFetchContentOperation * op = new IMAPFetchContentOperation(); - op->setMainSession(this); - op->setFolder(folder); - op->setNumber(number); - op->setUrgent(urgent); - op->autorelease(); - return op; -} - -IMAPFetchContentOperation * IMAPAsyncSession::fetchMessageAttachmentByNumberOperation(String * folder, uint32_t number, String * partID, - Encoding encoding, bool urgent) -{ - IMAPFetchContentOperation * op = new IMAPFetchContentOperation(); - op->setMainSession(this); - op->setFolder(folder); - op->setNumber(number); - op->setPartID(partID); - op->setEncoding(encoding); - op->setUrgent(urgent); - op->autorelease(); - return op; -} - -IMAPFetchParsedContentOperation * IMAPAsyncSession::fetchParsedMessageByUIDOperation(String * folder, uint32_t uid, bool urgent) -{ - IMAPFetchParsedContentOperation * op = new IMAPFetchParsedContentOperation(); - op->setMainSession(this); - op->setFolder(folder); - op->setUid(uid); - op->setUrgent(urgent); - op->autorelease(); - return op; -} - -IMAPFetchParsedContentOperation * IMAPAsyncSession::fetchParsedMessageByNumberOperation(String * folder, uint32_t number, bool urgent) -{ - IMAPFetchParsedContentOperation * op = new IMAPFetchParsedContentOperation(); - op->setMainSession(this); - op->setFolder(folder); - op->setNumber(number); - op->setUrgent(urgent); - op->autorelease(); - return op; -} - -IMAPOperation * IMAPAsyncSession::storeFlagsByUIDOperation(String * folder, IndexSet * uids, IMAPStoreFlagsRequestKind kind, MessageFlag flags, Array * customFlags) -{ - IMAPStoreFlagsOperation * op = new IMAPStoreFlagsOperation(); - op->setMainSession(this); - op->setFolder(folder); - op->setUids(uids); - op->setKind(kind); - op->setFlags(flags); - op->setCustomFlags(customFlags); - op->autorelease(); - return op; -} - -IMAPOperation * IMAPAsyncSession::storeFlagsByNumberOperation(String * folder, IndexSet * numbers, IMAPStoreFlagsRequestKind kind, MessageFlag flags, Array * customFlags) -{ - IMAPStoreFlagsOperation * op = new IMAPStoreFlagsOperation(); - op->setMainSession(this); - op->setFolder(folder); - op->setNumbers(numbers); - op->setKind(kind); - op->setFlags(flags); - op->setCustomFlags(customFlags); - op->autorelease(); - return op; -} - -IMAPOperation * IMAPAsyncSession::storeLabelsByUIDOperation(String * folder, IndexSet * uids, IMAPStoreFlagsRequestKind kind, Array * labels) -{ - IMAPStoreLabelsOperation * op = new IMAPStoreLabelsOperation(); - op->setMainSession(this); - op->setFolder(folder); - op->setUids(uids); - op->setKind(kind); - op->setLabels(labels); - op->autorelease(); - return op; -} - -IMAPOperation * IMAPAsyncSession::storeLabelsByNumberOperation(String * folder, IndexSet * numbers, IMAPStoreFlagsRequestKind kind, Array * labels) -{ - IMAPStoreLabelsOperation * op = new IMAPStoreLabelsOperation(); - op->setMainSession(this); - op->setFolder(folder); - op->setNumbers(numbers); - op->setKind(kind); - op->setLabels(labels); - op->autorelease(); - return op; -} - -IMAPSearchOperation * IMAPAsyncSession::searchOperation(String * folder, IMAPSearchKind kind, String * searchString) -{ - IMAPSearchOperation * op = new IMAPSearchOperation(); - op->setMainSession(this); - op->setFolder(folder); - op->setSearchKind(kind); - op->setSearchString(searchString); - op->autorelease(); - return op; -} - -IMAPSearchOperation * IMAPAsyncSession::searchOperation(String * folder, IMAPSearchExpression * expression) -{ - IMAPSearchOperation * op = new IMAPSearchOperation(); - op->setMainSession(this); - op->setFolder(folder); - op->setSearchExpression(expression); - op->autorelease(); - return op; -} - -IMAPIdleOperation * IMAPAsyncSession::idleOperation(String * folder, uint32_t lastKnownUID) -{ - IMAPIdleOperation * op = new IMAPIdleOperation(); - op->setMainSession(this); - op->setFolder(folder); - op->setLastKnownUID(lastKnownUID); - op->autorelease(); - return op; -} - -IMAPFetchNamespaceOperation * IMAPAsyncSession::fetchNamespaceOperation() -{ - IMAPFetchNamespaceOperation * op = new IMAPFetchNamespaceOperation(); - op->setMainSession(this); - op->autorelease(); - return op; -} - -IMAPIdentityOperation * IMAPAsyncSession::identityOperation(IMAPIdentity * identity) -{ - IMAPIdentityOperation * op = new IMAPIdentityOperation(); - op->setMainSession(this); - op->setClientIdentity(identity); - op->autorelease(); - return op; -} - -IMAPOperation * IMAPAsyncSession::connectOperation() -{ - IMAPConnectOperation * op = new IMAPConnectOperation(); - op->setMainSession(this); - op->autorelease(); - return op; -} - -IMAPOperation * IMAPAsyncSession::checkAccountOperation() -{ - IMAPCheckAccountOperation * op = new IMAPCheckAccountOperation(); - op->setMainSession(this); - op->autorelease(); - return op; -} - -IMAPCapabilityOperation * IMAPAsyncSession::capabilityOperation() -{ - IMAPCapabilityOperation * op = new IMAPCapabilityOperation(); - op->setMainSession(this); - op->autorelease(); - return op; -} - -IMAPQuotaOperation * IMAPAsyncSession::quotaOperation() -{ - IMAPQuotaOperation * op = new IMAPQuotaOperation(); - op->setMainSession(this); - op->autorelease(); - return op; -} - -IMAPOperation * IMAPAsyncSession::noopOperation() -{ - IMAPNoopOperation * op = new IMAPNoopOperation(); - op->setMainSession(this); - op->autorelease(); - return op; -} - -IMAPOperation * IMAPAsyncSession::disconnectOperation() -{ - IMAPMultiDisconnectOperation * op = new IMAPMultiDisconnectOperation(); - op->autorelease(); - for(unsigned int i = 0 ; i < mSessions->count() ; i ++) { - IMAPAsyncConnection * currentSession = (IMAPAsyncConnection *) mSessions->objectAtIndex(i); - op->addOperation(currentSession->disconnectOperation()); - } - return op; -} - -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; -} - -IMAPMessageRenderingOperation * IMAPAsyncSession::renderingOperation(IMAPMessage * message, - String * folder, - IMAPMessageRenderingType type) -{ - IMAPMessageRenderingOperation * op = new IMAPMessageRenderingOperation(); - op->setMainSession(this); - op->setMessage(message); - op->setFolder(folder); - op->setRenderingType(type); - op->autorelease(); - return op; -} - -IMAPMessageRenderingOperation * IMAPAsyncSession::htmlRenderingOperation(IMAPMessage * message, - String * folder) -{ - return renderingOperation(message, folder, IMAPMessageRenderingTypeHTML); -} - -IMAPMessageRenderingOperation * IMAPAsyncSession::htmlBodyRenderingOperation(IMAPMessage * message, - String * folder) -{ - return renderingOperation(message, folder, IMAPMessageRenderingTypeHTMLBody); -} - -IMAPMessageRenderingOperation * IMAPAsyncSession::plainTextRenderingOperation(IMAPMessage * message, - String * folder) -{ - return renderingOperation(message, folder, IMAPMessageRenderingTypePlainText); -} - -IMAPMessageRenderingOperation * IMAPAsyncSession::plainTextBodyRenderingOperation(IMAPMessage * message, - String * folder, - bool stripWhitespace) -{ - return renderingOperation(message, folder, - stripWhitespace ? IMAPMessageRenderingTypePlainTextBodyAndStripWhitespace : - IMAPMessageRenderingTypePlainTextBody); -} - -void IMAPAsyncSession::automaticConfigurationDone(IMAPSession * session) -{ - MC_SAFE_REPLACE_COPY(IMAPIdentity, mServerIdentity, session->serverIdentity()); - MC_SAFE_REPLACE_COPY(String, mGmailUserDisplayName, session->gmailUserDisplayName()); - setDefaultNamespace(session->defaultNamespace()); - mAutomaticConfigurationDone = true; -} - -void IMAPAsyncSession::setOperationQueueCallback(OperationQueueCallback * callback) -{ - mOperationQueueCallback = callback; -} - -OperationQueueCallback * IMAPAsyncSession::operationQueueCallback() -{ - return mOperationQueueCallback; -} - -bool IMAPAsyncSession::isOperationQueueRunning() -{ - return mQueueRunning; -} - -void IMAPAsyncSession::cancelAllOperations() -{ - for(unsigned int i = 0 ; i < mSessions->count() ; i ++) { - IMAPAsyncConnection * currentSession = (IMAPAsyncConnection *) mSessions->objectAtIndex(i); - currentSession->cancelAllOperations(); - } -} - -void IMAPAsyncSession::operationRunningStateChanged() -{ - bool isRunning = false; - for(unsigned int i = 0 ; i < mSessions->count() ; i ++) { - IMAPAsyncConnection * currentSession = (IMAPAsyncConnection *) mSessions->objectAtIndex(i); - if (currentSession->isQueueRunning()){ - isRunning = true; - break; - } - } - if (mQueueRunning == isRunning) { - return; - } - mQueueRunning = isRunning; - if (mOperationQueueCallback != NULL) { - if (isRunning) { - mOperationQueueCallback->queueStartRunning(); - } - else { - mOperationQueueCallback->queueStoppedRunning(); - } - } -} - -#if __APPLE__ -void IMAPAsyncSession::setDispatchQueue(dispatch_queue_t dispatchQueue) -{ - if (mDispatchQueue != NULL) { - dispatch_release(mDispatchQueue); - } - mDispatchQueue = dispatchQueue; - if (mDispatchQueue != NULL) { - dispatch_retain(mDispatchQueue); - } -} - -dispatch_queue_t IMAPAsyncSession::dispatchQueue() -{ - return mDispatchQueue; -} -#endif diff --git a/src/async/imap/MCIMAPAsyncSession.cpp b/src/async/imap/MCIMAPAsyncSession.cpp new file mode 100755 index 00000000..f3a55a5e --- /dev/null +++ b/src/async/imap/MCIMAPAsyncSession.cpp @@ -0,0 +1,848 @@ +// +// MCIMAPAsyncSession.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/17/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPAsyncSession.h" + +#include "MCIMAPAsyncConnection.h" +#include "MCIMAPNamespace.h" +#include "MCOperationQueueCallback.h" +#include "MCConnectionLogger.h" +#include "MCIMAPSession.h" +#include "MCIMAPIdentity.h" +#include "MCIMAPMultiDisconnectOperation.h" + +#include "MCIMAPFolderInfoOperation.h" +#include "MCIMAPFolderStatusOperation.h" +#include "MCIMAPFetchFoldersOperation.h" +#include "MCIMAPRenameFolderOperation.h" +#include "MCIMAPDeleteFolderOperation.h" +#include "MCIMAPCreateFolderOperation.h" +#include "MCIMAPSubscribeFolderOperation.h" +#include "MCIMAPExpungeOperation.h" +#include "MCIMAPAppendMessageOperation.h" +#include "MCIMAPCopyMessagesOperation.h" +#include "MCIMAPFetchMessagesOperation.h" +#include "MCIMAPFetchContentOperation.h" +#include "MCIMAPFetchParsedContentOperation.h" +#include "MCIMAPStoreFlagsOperation.h" +#include "MCIMAPStoreLabelsOperation.h" +#include "MCIMAPSearchOperation.h" +#include "MCIMAPConnectOperation.h" +#include "MCIMAPCheckAccountOperation.h" +#include "MCIMAPFetchNamespaceOperation.h" +#include "MCIMAPIdleOperation.h" +#include "MCIMAPIdentityOperation.h" +#include "MCIMAPCapabilityOperation.h" +#include "MCIMAPQuotaOperation.h" +#include "MCIMAPDisconnectOperation.h" +#include "MCIMAPNoopOperation.h" +#include "MCIMAPMessageRenderingOperation.h" + +#define DEFAULT_MAX_CONNECTIONS 3 + +using namespace mailcore; + +IMAPAsyncSession::IMAPAsyncSession() +{ + mSessions = new Array(); + mMaximumConnections = DEFAULT_MAX_CONNECTIONS; + mAllowsFolderConcurrentAccessEnabled = true; + + mHostname = NULL; + mPort = 0; + mUsername = NULL; + mPassword = NULL; + mOAuth2Token = NULL; + mAuthType = AuthTypeSASLNone; + mConnectionType = ConnectionTypeClear; + mCheckCertificateEnabled = true; + mVoIPEnabled = true; + mDefaultNamespace = NULL; + mTimeout = 30.; + mConnectionLogger = NULL; + mAutomaticConfigurationDone = false; + mServerIdentity = new IMAPIdentity(); + mClientIdentity = new IMAPIdentity(); + mOperationQueueCallback = NULL; +#if __APPLE__ + mDispatchQueue = dispatch_get_main_queue(); +#endif + mGmailUserDisplayName = NULL; +} + +IMAPAsyncSession::~IMAPAsyncSession() +{ +#if __APPLE__ + if (mDispatchQueue != NULL) { + dispatch_release(mDispatchQueue); + } +#endif + MC_SAFE_RELEASE(mGmailUserDisplayName); + MC_SAFE_RELEASE(mServerIdentity); + MC_SAFE_RELEASE(mClientIdentity); + 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) +{ + MC_SAFE_REPLACE_COPY(String, mHostname, hostname); +} + +String * IMAPAsyncSession::hostname() +{ + return mHostname; +} + +void IMAPAsyncSession::setPort(unsigned int port) +{ + mPort = port; +} + +unsigned int IMAPAsyncSession::port() +{ + return mPort; +} + +void IMAPAsyncSession::setUsername(String * username) +{ + MC_SAFE_REPLACE_COPY(String, mUsername, username); +} + +String * IMAPAsyncSession::username() +{ + return mUsername; +} + +void IMAPAsyncSession::setPassword(String * password) +{ + MC_SAFE_REPLACE_COPY(String, mPassword, password); +} + +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; +} + +AuthType IMAPAsyncSession::authType() +{ + return mAuthType; +} + +void IMAPAsyncSession::setConnectionType(ConnectionType connectionType) +{ + mConnectionType = connectionType; +} + +ConnectionType IMAPAsyncSession::connectionType() +{ + return mConnectionType; +} + +void IMAPAsyncSession::setTimeout(time_t timeout) +{ + mTimeout = timeout; +} + +time_t IMAPAsyncSession::timeout() +{ + return mTimeout; +} + +void IMAPAsyncSession::setCheckCertificateEnabled(bool enabled) +{ + mCheckCertificateEnabled = enabled; +} + +bool IMAPAsyncSession::isCheckCertificateEnabled() +{ + return mCheckCertificateEnabled; +} + +void IMAPAsyncSession::setVoIPEnabled(bool enabled) +{ + mVoIPEnabled = enabled; +} + +bool IMAPAsyncSession::isVoIPEnabled() +{ + return mVoIPEnabled; +} + +IMAPNamespace * IMAPAsyncSession::defaultNamespace() +{ + return mDefaultNamespace; +} + +void IMAPAsyncSession::setDefaultNamespace(IMAPNamespace * ns) +{ + MC_SAFE_REPLACE_RETAIN(IMAPNamespace, mDefaultNamespace, ns); +} + +void IMAPAsyncSession::setAllowsFolderConcurrentAccessEnabled(bool enabled) +{ + mAllowsFolderConcurrentAccessEnabled = enabled; +} + +bool IMAPAsyncSession::allowsFolderConcurrentAccessEnabled() +{ + return mAllowsFolderConcurrentAccessEnabled; +} + +void IMAPAsyncSession::setMaximumConnections(unsigned int maxConnections) +{ + mMaximumConnections = maxConnections; +} + +unsigned int IMAPAsyncSession::maximumConnections() +{ + return mMaximumConnections; +} + +IMAPIdentity * IMAPAsyncSession::serverIdentity() +{ + return mServerIdentity; +} + +IMAPIdentity * IMAPAsyncSession::clientIdentity() +{ + return mClientIdentity; +} + +String * IMAPAsyncSession::gmailUserDisplayName() +{ + return mGmailUserDisplayName; +} + +IMAPAsyncConnection * IMAPAsyncSession::session() +{ + IMAPAsyncConnection * session = new IMAPAsyncConnection(); + session->setConnectionLogger(mConnectionLogger); + session->setOwner(this); + session->autorelease(); + + session->setHostname(mHostname); + session->setPort(mPort); + session->setUsername(mUsername); + session->setPassword(mPassword); + session->setOAuth2Token(mOAuth2Token); + session->setAuthType(mAuthType); + session->setConnectionType(mConnectionType); + session->setTimeout(mTimeout); + session->setCheckCertificateEnabled(mCheckCertificateEnabled); + session->setVoIPEnabled(mVoIPEnabled); + session->setDefaultNamespace(mDefaultNamespace); + session->setClientIdentity(mClientIdentity); +#if __APPLE__ + session->setDispatchQueue(mDispatchQueue); +#endif +#if 0 // should be implemented properly + if (mAutomaticConfigurationDone) { + session->setAutomaticConfigurationEnabled(false); + } +#endif + + return session; +} + +IMAPAsyncConnection * IMAPAsyncSession::sessionForFolder(String * folder, bool urgent) +{ + if (folder == NULL) { + return availableSession(); + } + else { + IMAPAsyncConnection * s = NULL; + if (urgent && mAllowsFolderConcurrentAccessEnabled) { + s = availableSession(); + if (s->operationsCount() == 0) { + s->setLastFolder(folder); + return s; + } + } + + s = matchingSessionForFolder(folder); + s->setLastFolder(folder); + return s; + } +} + +IMAPAsyncConnection * IMAPAsyncSession::availableSession() +{ + if (mMaximumConnections == 0) { + for(unsigned int i = 0 ; i < mSessions->count() ; i ++) { + IMAPAsyncConnection * s = (IMAPAsyncConnection *) mSessions->objectAtIndex(i); + if (s->operationsCount() == 0) + return s; + } + IMAPAsyncConnection * chosenSession = session(); + mSessions->addObject(chosenSession); + return chosenSession; + } + else { + IMAPAsyncConnection * chosenSession = NULL; + unsigned int minOperationsCount = 0; + for(unsigned int i = 0 ; i < mSessions->count() ; i ++) { + IMAPAsyncConnection * s = (IMAPAsyncConnection *) mSessions->objectAtIndex(i); + if (chosenSession == NULL) { + chosenSession = s; + minOperationsCount = s->operationsCount(); + } + else if (s->operationsCount() < minOperationsCount) { + chosenSession = s; + minOperationsCount = s->operationsCount(); + } + } + if (mSessions->count() < mMaximumConnections) { + if ((chosenSession != NULL) && (minOperationsCount == 0)) { + return chosenSession; + } + chosenSession = session(); + mSessions->addObject(chosenSession); + return chosenSession; + } + else { + return chosenSession; + } + } +} + +IMAPAsyncConnection * IMAPAsyncSession::matchingSessionForFolder(String * folder) +{ + for(unsigned int i = 0 ; i < mSessions->count() ; i ++) { + IMAPAsyncConnection * currentSession = (IMAPAsyncConnection *) mSessions->objectAtIndex(i); + if (currentSession->lastFolder() != NULL) { + if (currentSession->lastFolder()->isEqual(folder)) { + return currentSession; + } + } + else { + return currentSession; + } + } + return availableSession(); +} + +IMAPFolderInfoOperation * IMAPAsyncSession::folderInfoOperation(String * folder) +{ + IMAPFolderInfoOperation * op = new IMAPFolderInfoOperation(); + op->setMainSession(this); + op->setFolder(folder); + op->autorelease(); + return op; +} + +IMAPFolderStatusOperation * IMAPAsyncSession::folderStatusOperation(String * folder) +{ + IMAPFolderStatusOperation * op = new IMAPFolderStatusOperation(); + op->setMainSession(this); + op->setFolder(folder); + op->autorelease(); + return op; +} + +IMAPFetchFoldersOperation * IMAPAsyncSession::fetchSubscribedFoldersOperation() +{ + IMAPFetchFoldersOperation * op = new IMAPFetchFoldersOperation(); + op->setMainSession(this); + op->setFetchSubscribedEnabled(true); + op->autorelease(); + return op; +} + +IMAPFetchFoldersOperation * IMAPAsyncSession::fetchAllFoldersOperation() +{ + IMAPFetchFoldersOperation * op = new IMAPFetchFoldersOperation(); + op->setMainSession(this); + op->autorelease(); + return op; +} + +IMAPOperation * IMAPAsyncSession::renameFolderOperation(String * folder, String * otherName) +{ + IMAPRenameFolderOperation * op = new IMAPRenameFolderOperation(); + op->setMainSession(this); + op->setFolder(folder); + op->setOtherName(otherName); + op->autorelease(); + return op; +} + +IMAPOperation * IMAPAsyncSession::deleteFolderOperation(String * folder) +{ + IMAPDeleteFolderOperation * op = new IMAPDeleteFolderOperation(); + op->setMainSession(this); + op->setFolder(folder); + op->autorelease(); + return op; +} + +IMAPOperation * IMAPAsyncSession::createFolderOperation(String * folder) +{ + IMAPCreateFolderOperation * op = new IMAPCreateFolderOperation(); + op->setMainSession(this); + op->setFolder(folder); + op->autorelease(); + return op; +} + +IMAPOperation * IMAPAsyncSession::subscribeFolderOperation(String * folder) +{ + IMAPSubscribeFolderOperation * op = new IMAPSubscribeFolderOperation(); + op->setMainSession(this); + op->setFolder(folder); + op->autorelease(); + return op; +} + +IMAPOperation * IMAPAsyncSession::unsubscribeFolderOperation(String * folder) +{ + IMAPSubscribeFolderOperation * op = new IMAPSubscribeFolderOperation(); + op->setMainSession(this); + op->setUnsubscribeEnabled(true); + op->setFolder(folder); + op->autorelease(); + return op; +} + +IMAPAppendMessageOperation * IMAPAsyncSession::appendMessageOperation(String * folder, Data * messageData, MessageFlag flags, Array * customFlags) +{ + IMAPAppendMessageOperation * op = new IMAPAppendMessageOperation(); + op->setMainSession(this); + op->setFolder(folder); + op->setMessageData(messageData); + op->setFlags(flags); + op->setCustomFlags(customFlags); + op->autorelease(); + return op; +} + +IMAPCopyMessagesOperation * IMAPAsyncSession::copyMessagesOperation(String * folder, IndexSet * uids, String * destFolder) +{ + IMAPCopyMessagesOperation * op = new IMAPCopyMessagesOperation(); + op->setMainSession(this); + op->setFolder(folder); + op->setUids(uids); + op->setDestFolder(destFolder); + op->autorelease(); + return op; +} + +IMAPOperation * IMAPAsyncSession::expungeOperation(String * folder) +{ + IMAPExpungeOperation * op = new IMAPExpungeOperation(); + op->setMainSession(this); + op->setFolder(folder); + op->autorelease(); + return op; +} + +IMAPFetchMessagesOperation * IMAPAsyncSession::fetchMessagesByUIDOperation(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * uids) +{ + IMAPFetchMessagesOperation * op = new IMAPFetchMessagesOperation(); + op->setMainSession(this); + op->setFolder(folder); + op->setKind(requestKind); + op->setFetchByUidEnabled(true); + op->setIndexes(uids); + op->autorelease(); + return op; +} + +IMAPFetchMessagesOperation * IMAPAsyncSession::fetchMessagesByNumberOperation(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * numbers) +{ + IMAPFetchMessagesOperation * op = new IMAPFetchMessagesOperation(); + op->setMainSession(this); + op->setFolder(folder); + op->setKind(requestKind); + op->setIndexes(numbers); + op->autorelease(); + return op; +} + +IMAPFetchMessagesOperation * IMAPAsyncSession::syncMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * uids, uint64_t modSeq) +{ + IMAPFetchMessagesOperation * op = new IMAPFetchMessagesOperation(); + op->setMainSession(this); + op->setFolder(folder); + op->setKind(requestKind); + op->setFetchByUidEnabled(true); + op->setIndexes(uids); + op->setModSequenceValue(modSeq); + op->autorelease(); + return op; +} + +IMAPFetchContentOperation * IMAPAsyncSession::fetchMessageByUIDOperation(String * folder, uint32_t uid, bool urgent) +{ + IMAPFetchContentOperation * op = new IMAPFetchContentOperation(); + op->setMainSession(this); + op->setFolder(folder); + op->setUid(uid); + op->setUrgent(urgent); + op->autorelease(); + return op; +} + +IMAPFetchContentOperation * IMAPAsyncSession::fetchMessageAttachmentByUIDOperation(String * folder, uint32_t uid, String * partID, + Encoding encoding, bool urgent) +{ + IMAPFetchContentOperation * op = new IMAPFetchContentOperation(); + op->setMainSession(this); + op->setFolder(folder); + op->setUid(uid); + op->setPartID(partID); + op->setEncoding(encoding); + op->setUrgent(urgent); + op->autorelease(); + return op; +} + +IMAPFetchContentOperation * IMAPAsyncSession::fetchMessageByNumberOperation(String * folder, uint32_t number, bool urgent) +{ + IMAPFetchContentOperation * op = new IMAPFetchContentOperation(); + op->setMainSession(this); + op->setFolder(folder); + op->setNumber(number); + op->setUrgent(urgent); + op->autorelease(); + return op; +} + +IMAPFetchContentOperation * IMAPAsyncSession::fetchMessageAttachmentByNumberOperation(String * folder, uint32_t number, String * partID, + Encoding encoding, bool urgent) +{ + IMAPFetchContentOperation * op = new IMAPFetchContentOperation(); + op->setMainSession(this); + op->setFolder(folder); + op->setNumber(number); + op->setPartID(partID); + op->setEncoding(encoding); + op->setUrgent(urgent); + op->autorelease(); + return op; +} + +IMAPFetchParsedContentOperation * IMAPAsyncSession::fetchParsedMessageByUIDOperation(String * folder, uint32_t uid, bool urgent) +{ + IMAPFetchParsedContentOperation * op = new IMAPFetchParsedContentOperation(); + op->setMainSession(this); + op->setFolder(folder); + op->setUid(uid); + op->setUrgent(urgent); + op->autorelease(); + return op; +} + +IMAPFetchParsedContentOperation * IMAPAsyncSession::fetchParsedMessageByNumberOperation(String * folder, uint32_t number, bool urgent) +{ + IMAPFetchParsedContentOperation * op = new IMAPFetchParsedContentOperation(); + op->setMainSession(this); + op->setFolder(folder); + op->setNumber(number); + op->setUrgent(urgent); + op->autorelease(); + return op; +} + +IMAPOperation * IMAPAsyncSession::storeFlagsByUIDOperation(String * folder, IndexSet * uids, IMAPStoreFlagsRequestKind kind, MessageFlag flags, Array * customFlags) +{ + IMAPStoreFlagsOperation * op = new IMAPStoreFlagsOperation(); + op->setMainSession(this); + op->setFolder(folder); + op->setUids(uids); + op->setKind(kind); + op->setFlags(flags); + op->setCustomFlags(customFlags); + op->autorelease(); + return op; +} + +IMAPOperation * IMAPAsyncSession::storeFlagsByNumberOperation(String * folder, IndexSet * numbers, IMAPStoreFlagsRequestKind kind, MessageFlag flags, Array * customFlags) +{ + IMAPStoreFlagsOperation * op = new IMAPStoreFlagsOperation(); + op->setMainSession(this); + op->setFolder(folder); + op->setNumbers(numbers); + op->setKind(kind); + op->setFlags(flags); + op->setCustomFlags(customFlags); + op->autorelease(); + return op; +} + +IMAPOperation * IMAPAsyncSession::storeLabelsByUIDOperation(String * folder, IndexSet * uids, IMAPStoreFlagsRequestKind kind, Array * labels) +{ + IMAPStoreLabelsOperation * op = new IMAPStoreLabelsOperation(); + op->setMainSession(this); + op->setFolder(folder); + op->setUids(uids); + op->setKind(kind); + op->setLabels(labels); + op->autorelease(); + return op; +} + +IMAPOperation * IMAPAsyncSession::storeLabelsByNumberOperation(String * folder, IndexSet * numbers, IMAPStoreFlagsRequestKind kind, Array * labels) +{ + IMAPStoreLabelsOperation * op = new IMAPStoreLabelsOperation(); + op->setMainSession(this); + op->setFolder(folder); + op->setNumbers(numbers); + op->setKind(kind); + op->setLabels(labels); + op->autorelease(); + return op; +} + +IMAPSearchOperation * IMAPAsyncSession::searchOperation(String * folder, IMAPSearchKind kind, String * searchString) +{ + IMAPSearchOperation * op = new IMAPSearchOperation(); + op->setMainSession(this); + op->setFolder(folder); + op->setSearchKind(kind); + op->setSearchString(searchString); + op->autorelease(); + return op; +} + +IMAPSearchOperation * IMAPAsyncSession::searchOperation(String * folder, IMAPSearchExpression * expression) +{ + IMAPSearchOperation * op = new IMAPSearchOperation(); + op->setMainSession(this); + op->setFolder(folder); + op->setSearchExpression(expression); + op->autorelease(); + return op; +} + +IMAPIdleOperation * IMAPAsyncSession::idleOperation(String * folder, uint32_t lastKnownUID) +{ + IMAPIdleOperation * op = new IMAPIdleOperation(); + op->setMainSession(this); + op->setFolder(folder); + op->setLastKnownUID(lastKnownUID); + op->autorelease(); + return op; +} + +IMAPFetchNamespaceOperation * IMAPAsyncSession::fetchNamespaceOperation() +{ + IMAPFetchNamespaceOperation * op = new IMAPFetchNamespaceOperation(); + op->setMainSession(this); + op->autorelease(); + return op; +} + +IMAPIdentityOperation * IMAPAsyncSession::identityOperation(IMAPIdentity * identity) +{ + IMAPIdentityOperation * op = new IMAPIdentityOperation(); + op->setMainSession(this); + op->setClientIdentity(identity); + op->autorelease(); + return op; +} + +IMAPOperation * IMAPAsyncSession::connectOperation() +{ + IMAPConnectOperation * op = new IMAPConnectOperation(); + op->setMainSession(this); + op->autorelease(); + return op; +} + +IMAPOperation * IMAPAsyncSession::checkAccountOperation() +{ + IMAPCheckAccountOperation * op = new IMAPCheckAccountOperation(); + op->setMainSession(this); + op->autorelease(); + return op; +} + +IMAPCapabilityOperation * IMAPAsyncSession::capabilityOperation() +{ + IMAPCapabilityOperation * op = new IMAPCapabilityOperation(); + op->setMainSession(this); + op->autorelease(); + return op; +} + +IMAPQuotaOperation * IMAPAsyncSession::quotaOperation() +{ + IMAPQuotaOperation * op = new IMAPQuotaOperation(); + op->setMainSession(this); + op->autorelease(); + return op; +} + +IMAPOperation * IMAPAsyncSession::noopOperation() +{ + IMAPNoopOperation * op = new IMAPNoopOperation(); + op->setMainSession(this); + op->autorelease(); + return op; +} + +IMAPOperation * IMAPAsyncSession::disconnectOperation() +{ + IMAPMultiDisconnectOperation * op = new IMAPMultiDisconnectOperation(); + op->autorelease(); + for(unsigned int i = 0 ; i < mSessions->count() ; i ++) { + IMAPAsyncConnection * currentSession = (IMAPAsyncConnection *) mSessions->objectAtIndex(i); + op->addOperation(currentSession->disconnectOperation()); + } + return op; +} + +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; +} + +IMAPMessageRenderingOperation * IMAPAsyncSession::renderingOperation(IMAPMessage * message, + String * folder, + IMAPMessageRenderingType type) +{ + IMAPMessageRenderingOperation * op = new IMAPMessageRenderingOperation(); + op->setMainSession(this); + op->setMessage(message); + op->setFolder(folder); + op->setRenderingType(type); + op->autorelease(); + return op; +} + +IMAPMessageRenderingOperation * IMAPAsyncSession::htmlRenderingOperation(IMAPMessage * message, + String * folder) +{ + return renderingOperation(message, folder, IMAPMessageRenderingTypeHTML); +} + +IMAPMessageRenderingOperation * IMAPAsyncSession::htmlBodyRenderingOperation(IMAPMessage * message, + String * folder) +{ + return renderingOperation(message, folder, IMAPMessageRenderingTypeHTMLBody); +} + +IMAPMessageRenderingOperation * IMAPAsyncSession::plainTextRenderingOperation(IMAPMessage * message, + String * folder) +{ + return renderingOperation(message, folder, IMAPMessageRenderingTypePlainText); +} + +IMAPMessageRenderingOperation * IMAPAsyncSession::plainTextBodyRenderingOperation(IMAPMessage * message, + String * folder, + bool stripWhitespace) +{ + return renderingOperation(message, folder, + stripWhitespace ? IMAPMessageRenderingTypePlainTextBodyAndStripWhitespace : + IMAPMessageRenderingTypePlainTextBody); +} + +void IMAPAsyncSession::automaticConfigurationDone(IMAPSession * session) +{ + MC_SAFE_REPLACE_COPY(IMAPIdentity, mServerIdentity, session->serverIdentity()); + MC_SAFE_REPLACE_COPY(String, mGmailUserDisplayName, session->gmailUserDisplayName()); + setDefaultNamespace(session->defaultNamespace()); + mAutomaticConfigurationDone = true; +} + +void IMAPAsyncSession::setOperationQueueCallback(OperationQueueCallback * callback) +{ + mOperationQueueCallback = callback; +} + +OperationQueueCallback * IMAPAsyncSession::operationQueueCallback() +{ + return mOperationQueueCallback; +} + +bool IMAPAsyncSession::isOperationQueueRunning() +{ + return mQueueRunning; +} + +void IMAPAsyncSession::cancelAllOperations() +{ + for(unsigned int i = 0 ; i < mSessions->count() ; i ++) { + IMAPAsyncConnection * currentSession = (IMAPAsyncConnection *) mSessions->objectAtIndex(i); + currentSession->cancelAllOperations(); + } +} + +void IMAPAsyncSession::operationRunningStateChanged() +{ + bool isRunning = false; + for(unsigned int i = 0 ; i < mSessions->count() ; i ++) { + IMAPAsyncConnection * currentSession = (IMAPAsyncConnection *) mSessions->objectAtIndex(i); + if (currentSession->isQueueRunning()){ + isRunning = true; + break; + } + } + if (mQueueRunning == isRunning) { + return; + } + mQueueRunning = isRunning; + if (mOperationQueueCallback != NULL) { + if (isRunning) { + mOperationQueueCallback->queueStartRunning(); + } + else { + mOperationQueueCallback->queueStoppedRunning(); + } + } +} + +#if __APPLE__ +void IMAPAsyncSession::setDispatchQueue(dispatch_queue_t dispatchQueue) +{ + if (mDispatchQueue != NULL) { + dispatch_release(mDispatchQueue); + } + mDispatchQueue = dispatchQueue; + if (mDispatchQueue != NULL) { + dispatch_retain(mDispatchQueue); + } +} + +dispatch_queue_t IMAPAsyncSession::dispatchQueue() +{ + return mDispatchQueue; +} +#endif diff --git a/src/async/imap/MCIMAPCapabilityOperation.cc b/src/async/imap/MCIMAPCapabilityOperation.cc deleted file mode 100644 index 9edb9b1c..00000000 --- a/src/async/imap/MCIMAPCapabilityOperation.cc +++ /dev/null @@ -1,43 +0,0 @@ -// -// MCIMAPCapabilityOperation.cpp -// mailcore2 -// -// Created by DINH Viêt Hoà on 3/4/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPCapabilityOperation.h" - -#include "MCIMAPSession.h" -#include "MCIMAPAsyncConnection.h" - -using namespace mailcore; - -IMAPCapabilityOperation::IMAPCapabilityOperation() -{ - mCapabilities = NULL; -} - -IMAPCapabilityOperation::~IMAPCapabilityOperation() -{ - MC_SAFE_RELEASE(mCapabilities); -} - -IndexSet * IMAPCapabilityOperation::capabilities() -{ - return mCapabilities; -} - -void IMAPCapabilityOperation::main() -{ - ErrorCode error; - session()->session()->loginIfNeeded(&error); - if (error != ErrorNone) { - setError(error); - return; - } - mCapabilities = session()->session()->capability(&error); - MC_SAFE_RETAIN(mCapabilities); - setError(error); -} - diff --git a/src/async/imap/MCIMAPCapabilityOperation.cpp b/src/async/imap/MCIMAPCapabilityOperation.cpp new file mode 100644 index 00000000..9edb9b1c --- /dev/null +++ b/src/async/imap/MCIMAPCapabilityOperation.cpp @@ -0,0 +1,43 @@ +// +// MCIMAPCapabilityOperation.cpp +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/4/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPCapabilityOperation.h" + +#include "MCIMAPSession.h" +#include "MCIMAPAsyncConnection.h" + +using namespace mailcore; + +IMAPCapabilityOperation::IMAPCapabilityOperation() +{ + mCapabilities = NULL; +} + +IMAPCapabilityOperation::~IMAPCapabilityOperation() +{ + MC_SAFE_RELEASE(mCapabilities); +} + +IndexSet * IMAPCapabilityOperation::capabilities() +{ + return mCapabilities; +} + +void IMAPCapabilityOperation::main() +{ + ErrorCode error; + session()->session()->loginIfNeeded(&error); + if (error != ErrorNone) { + setError(error); + return; + } + mCapabilities = session()->session()->capability(&error); + MC_SAFE_RETAIN(mCapabilities); + setError(error); +} + diff --git a/src/async/imap/MCIMAPCheckAccountOperation.cc b/src/async/imap/MCIMAPCheckAccountOperation.cc deleted file mode 100644 index 5baa89a9..00000000 --- a/src/async/imap/MCIMAPCheckAccountOperation.cc +++ /dev/null @@ -1,23 +0,0 @@ -// -// MCIMAPCheckAccountOperation.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/12/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPCheckAccountOperation.h" - -#include "MCIMAPAsyncConnection.h" -#include "MCIMAPSession.h" - -using namespace mailcore; - -void IMAPCheckAccountOperation::main() -{ - ErrorCode error; - session()->session()->connectIfNeeded(&error); - if (error == ErrorNone) - session()->session()->login(&error); - setError(error); -} diff --git a/src/async/imap/MCIMAPCheckAccountOperation.cpp b/src/async/imap/MCIMAPCheckAccountOperation.cpp new file mode 100644 index 00000000..5baa89a9 --- /dev/null +++ b/src/async/imap/MCIMAPCheckAccountOperation.cpp @@ -0,0 +1,23 @@ +// +// MCIMAPCheckAccountOperation.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPCheckAccountOperation.h" + +#include "MCIMAPAsyncConnection.h" +#include "MCIMAPSession.h" + +using namespace mailcore; + +void IMAPCheckAccountOperation::main() +{ + ErrorCode error; + session()->session()->connectIfNeeded(&error); + if (error == ErrorNone) + session()->session()->login(&error); + setError(error); +} diff --git a/src/async/imap/MCIMAPConnectOperation.cc b/src/async/imap/MCIMAPConnectOperation.cc deleted file mode 100644 index e4f71d03..00000000 --- a/src/async/imap/MCIMAPConnectOperation.cc +++ /dev/null @@ -1,21 +0,0 @@ -// -// MCIMAPConnectOperation.cc -// mailcore2 -// -// Created by Ryan Walklin on 6/09/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPConnectOperation.h" - -#include "MCIMAPAsyncConnection.h" -#include "MCIMAPSession.h" - -using namespace mailcore; - -void IMAPConnectOperation::main() -{ - ErrorCode error; - session()->session()->connectIfNeeded(&error); - setError(error); -} diff --git a/src/async/imap/MCIMAPConnectOperation.cpp b/src/async/imap/MCIMAPConnectOperation.cpp new file mode 100644 index 00000000..e4f71d03 --- /dev/null +++ b/src/async/imap/MCIMAPConnectOperation.cpp @@ -0,0 +1,21 @@ +// +// MCIMAPConnectOperation.cc +// mailcore2 +// +// Created by Ryan Walklin on 6/09/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPConnectOperation.h" + +#include "MCIMAPAsyncConnection.h" +#include "MCIMAPSession.h" + +using namespace mailcore; + +void IMAPConnectOperation::main() +{ + ErrorCode error; + session()->session()->connectIfNeeded(&error); + setError(error); +} diff --git a/src/async/imap/MCIMAPCopyMessagesOperation.cc b/src/async/imap/MCIMAPCopyMessagesOperation.cc deleted file mode 100644 index 87ef8e20..00000000 --- a/src/async/imap/MCIMAPCopyMessagesOperation.cc +++ /dev/null @@ -1,61 +0,0 @@ -// -// MCIMAPCopyMessagesOperation.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/12/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPCopyMessagesOperation.h" - -#include "MCIMAPSession.h" -#include "MCIMAPAsyncConnection.h" - -using namespace mailcore; - -IMAPCopyMessagesOperation::IMAPCopyMessagesOperation() -{ - mUids = NULL; - mDestFolder = NULL; - mUidMapping = NULL; -} - -IMAPCopyMessagesOperation::~IMAPCopyMessagesOperation() -{ - MC_SAFE_RELEASE(mUidMapping); - MC_SAFE_RELEASE(mUids); - MC_SAFE_RELEASE(mDestFolder); -} - -void IMAPCopyMessagesOperation::setUids(IndexSet * uids) -{ - MC_SAFE_REPLACE_RETAIN(IndexSet, mUids, uids); -} - -IndexSet * IMAPCopyMessagesOperation::uids() -{ - return mUids; -} - -HashMap * IMAPCopyMessagesOperation::uidMapping() -{ - return mUidMapping; -} - -void IMAPCopyMessagesOperation::setDestFolder(String * destFolder) -{ - MC_SAFE_REPLACE_COPY(String, mDestFolder, destFolder); -} - -String * IMAPCopyMessagesOperation::destFolder() -{ - return mDestFolder; -} - -void IMAPCopyMessagesOperation::main() -{ - ErrorCode error; - session()->session()->copyMessages(folder(), mUids, mDestFolder, &mUidMapping, &error); - MC_SAFE_RETAIN(mUidMapping); - setError(error); -} diff --git a/src/async/imap/MCIMAPCopyMessagesOperation.cpp b/src/async/imap/MCIMAPCopyMessagesOperation.cpp new file mode 100644 index 00000000..87ef8e20 --- /dev/null +++ b/src/async/imap/MCIMAPCopyMessagesOperation.cpp @@ -0,0 +1,61 @@ +// +// MCIMAPCopyMessagesOperation.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPCopyMessagesOperation.h" + +#include "MCIMAPSession.h" +#include "MCIMAPAsyncConnection.h" + +using namespace mailcore; + +IMAPCopyMessagesOperation::IMAPCopyMessagesOperation() +{ + mUids = NULL; + mDestFolder = NULL; + mUidMapping = NULL; +} + +IMAPCopyMessagesOperation::~IMAPCopyMessagesOperation() +{ + MC_SAFE_RELEASE(mUidMapping); + MC_SAFE_RELEASE(mUids); + MC_SAFE_RELEASE(mDestFolder); +} + +void IMAPCopyMessagesOperation::setUids(IndexSet * uids) +{ + MC_SAFE_REPLACE_RETAIN(IndexSet, mUids, uids); +} + +IndexSet * IMAPCopyMessagesOperation::uids() +{ + return mUids; +} + +HashMap * IMAPCopyMessagesOperation::uidMapping() +{ + return mUidMapping; +} + +void IMAPCopyMessagesOperation::setDestFolder(String * destFolder) +{ + MC_SAFE_REPLACE_COPY(String, mDestFolder, destFolder); +} + +String * IMAPCopyMessagesOperation::destFolder() +{ + return mDestFolder; +} + +void IMAPCopyMessagesOperation::main() +{ + ErrorCode error; + session()->session()->copyMessages(folder(), mUids, mDestFolder, &mUidMapping, &error); + MC_SAFE_RETAIN(mUidMapping); + setError(error); +} diff --git a/src/async/imap/MCIMAPCreateFolderOperation.cc b/src/async/imap/MCIMAPCreateFolderOperation.cc deleted file mode 100644 index d4e341fc..00000000 --- a/src/async/imap/MCIMAPCreateFolderOperation.cc +++ /dev/null @@ -1,29 +0,0 @@ -// -// MCIMAPCreateFolderOperation.cpp -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/12/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPCreateFolderOperation.h" - -#include "MCIMAPSession.h" -#include "MCIMAPAsyncConnection.h" - -using namespace mailcore; - -IMAPCreateFolderOperation::IMAPCreateFolderOperation() -{ -} - -IMAPCreateFolderOperation::~IMAPCreateFolderOperation() -{ -} - -void IMAPCreateFolderOperation::main() -{ - ErrorCode error; - session()->session()->createFolder(folder(), &error); - setError(error); -} diff --git a/src/async/imap/MCIMAPCreateFolderOperation.cpp b/src/async/imap/MCIMAPCreateFolderOperation.cpp new file mode 100644 index 00000000..d4e341fc --- /dev/null +++ b/src/async/imap/MCIMAPCreateFolderOperation.cpp @@ -0,0 +1,29 @@ +// +// MCIMAPCreateFolderOperation.cpp +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPCreateFolderOperation.h" + +#include "MCIMAPSession.h" +#include "MCIMAPAsyncConnection.h" + +using namespace mailcore; + +IMAPCreateFolderOperation::IMAPCreateFolderOperation() +{ +} + +IMAPCreateFolderOperation::~IMAPCreateFolderOperation() +{ +} + +void IMAPCreateFolderOperation::main() +{ + ErrorCode error; + session()->session()->createFolder(folder(), &error); + setError(error); +} diff --git a/src/async/imap/MCIMAPDeleteFolderOperation.cc b/src/async/imap/MCIMAPDeleteFolderOperation.cc deleted file mode 100644 index d03bfc88..00000000 --- a/src/async/imap/MCIMAPDeleteFolderOperation.cc +++ /dev/null @@ -1,29 +0,0 @@ -// -// MCIMAPDeleteFolderOperation.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/12/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPDeleteFolderOperation.h" - -#include "MCIMAPSession.h" -#include "MCIMAPAsyncConnection.h" - -using namespace mailcore; - -IMAPDeleteFolderOperation::IMAPDeleteFolderOperation() -{ -} - -IMAPDeleteFolderOperation::~IMAPDeleteFolderOperation() -{ -} - -void IMAPDeleteFolderOperation::main() -{ - ErrorCode error; - session()->session()->deleteFolder(folder(), &error); - setError(error); -} diff --git a/src/async/imap/MCIMAPDeleteFolderOperation.cpp b/src/async/imap/MCIMAPDeleteFolderOperation.cpp new file mode 100644 index 00000000..d03bfc88 --- /dev/null +++ b/src/async/imap/MCIMAPDeleteFolderOperation.cpp @@ -0,0 +1,29 @@ +// +// MCIMAPDeleteFolderOperation.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPDeleteFolderOperation.h" + +#include "MCIMAPSession.h" +#include "MCIMAPAsyncConnection.h" + +using namespace mailcore; + +IMAPDeleteFolderOperation::IMAPDeleteFolderOperation() +{ +} + +IMAPDeleteFolderOperation::~IMAPDeleteFolderOperation() +{ +} + +void IMAPDeleteFolderOperation::main() +{ + ErrorCode error; + session()->session()->deleteFolder(folder(), &error); + setError(error); +} diff --git a/src/async/imap/MCIMAPDisconnectOperation.cc b/src/async/imap/MCIMAPDisconnectOperation.cc deleted file mode 100644 index 4ee4ee9a..00000000 --- a/src/async/imap/MCIMAPDisconnectOperation.cc +++ /dev/null @@ -1,28 +0,0 @@ -// -// MCIMAPDisconnectOperation.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 6/22/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPDisconnectOperation.h" - -#include "MCIMAPAsyncConnection.h" -#include "MCIMAPSession.h" - -using namespace mailcore; - -IMAPDisconnectOperation::IMAPDisconnectOperation() -{ -} - -IMAPDisconnectOperation::~IMAPDisconnectOperation() -{ -} - -void IMAPDisconnectOperation::main() -{ - session()->session()->disconnect(); - setError(ErrorNone); -} diff --git a/src/async/imap/MCIMAPDisconnectOperation.cpp b/src/async/imap/MCIMAPDisconnectOperation.cpp new file mode 100644 index 00000000..4ee4ee9a --- /dev/null +++ b/src/async/imap/MCIMAPDisconnectOperation.cpp @@ -0,0 +1,28 @@ +// +// MCIMAPDisconnectOperation.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 6/22/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPDisconnectOperation.h" + +#include "MCIMAPAsyncConnection.h" +#include "MCIMAPSession.h" + +using namespace mailcore; + +IMAPDisconnectOperation::IMAPDisconnectOperation() +{ +} + +IMAPDisconnectOperation::~IMAPDisconnectOperation() +{ +} + +void IMAPDisconnectOperation::main() +{ + session()->session()->disconnect(); + setError(ErrorNone); +} diff --git a/src/async/imap/MCIMAPExpungeOperation.cc b/src/async/imap/MCIMAPExpungeOperation.cc deleted file mode 100644 index 141258b4..00000000 --- a/src/async/imap/MCIMAPExpungeOperation.cc +++ /dev/null @@ -1,29 +0,0 @@ -// -// MCIMAPExpungeOperation.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/12/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPExpungeOperation.h" - -#include "MCIMAPSession.h" -#include "MCIMAPAsyncConnection.h" - -using namespace mailcore; - -IMAPExpungeOperation::IMAPExpungeOperation() -{ -} - -IMAPExpungeOperation::~IMAPExpungeOperation() -{ -} - -void IMAPExpungeOperation::main() -{ - ErrorCode error; - session()->session()->expunge(folder(), &error); - setError(error); -} diff --git a/src/async/imap/MCIMAPExpungeOperation.cpp b/src/async/imap/MCIMAPExpungeOperation.cpp new file mode 100644 index 00000000..141258b4 --- /dev/null +++ b/src/async/imap/MCIMAPExpungeOperation.cpp @@ -0,0 +1,29 @@ +// +// MCIMAPExpungeOperation.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPExpungeOperation.h" + +#include "MCIMAPSession.h" +#include "MCIMAPAsyncConnection.h" + +using namespace mailcore; + +IMAPExpungeOperation::IMAPExpungeOperation() +{ +} + +IMAPExpungeOperation::~IMAPExpungeOperation() +{ +} + +void IMAPExpungeOperation::main() +{ + ErrorCode error; + session()->session()->expunge(folder(), &error); + setError(error); +} diff --git a/src/async/imap/MCIMAPFetchContentOperation.cc b/src/async/imap/MCIMAPFetchContentOperation.cc deleted file mode 100644 index 049ac8a7..00000000 --- a/src/async/imap/MCIMAPFetchContentOperation.cc +++ /dev/null @@ -1,98 +0,0 @@ -// -// IMAPFetchContentOperation.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/12/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPFetchContentOperation.h" - -#include "MCIMAPSession.h" -#include "MCIMAPAsyncConnection.h" - -using namespace mailcore; - -IMAPFetchContentOperation::IMAPFetchContentOperation() -{ - mUid = 0; - mNumber = 0; - mPartID = NULL; - mEncoding = Encoding7Bit; - mData = NULL; -} - -IMAPFetchContentOperation::~IMAPFetchContentOperation() -{ - MC_SAFE_RELEASE(mPartID); - MC_SAFE_RELEASE(mData); -} - -void IMAPFetchContentOperation::setUid(uint32_t uid) -{ - mUid = uid; -} - -uint32_t IMAPFetchContentOperation::uid() -{ - return mUid; -} - -void IMAPFetchContentOperation::setNumber(uint32_t value) -{ - mNumber = value; -} - -uint32_t IMAPFetchContentOperation::number() -{ - return mNumber; -} - -void IMAPFetchContentOperation::setPartID(String * partID) -{ - MC_SAFE_REPLACE_COPY(String, mPartID, partID); -} - -String * IMAPFetchContentOperation::partID() -{ - return mPartID; -} - -void IMAPFetchContentOperation::setEncoding(Encoding encoding) -{ - mEncoding = encoding; -} - -Encoding IMAPFetchContentOperation::encoding() -{ - return mEncoding; -} - -Data * IMAPFetchContentOperation::data() -{ - return mData; -} - -void IMAPFetchContentOperation::main() -{ - ErrorCode error; - if (mUid != 0) { - if (mPartID != NULL) { - mData = session()->session()->fetchMessageAttachmentByUID(folder(), mUid, mPartID, mEncoding, this, &error); - } - else { - mData = session()->session()->fetchMessageByUID(folder(), mUid, this, &error); - } - } - else { - if (mPartID != NULL) { - mData = session()->session()->fetchMessageAttachmentByNumber(folder(), mNumber, mPartID, mEncoding, this, &error); - } - else { - mData = session()->session()->fetchMessageByNumber(folder(), mNumber, this, &error); - } - } - MC_SAFE_RETAIN(mData); - setError(error); -} - diff --git a/src/async/imap/MCIMAPFetchContentOperation.cpp b/src/async/imap/MCIMAPFetchContentOperation.cpp new file mode 100644 index 00000000..049ac8a7 --- /dev/null +++ b/src/async/imap/MCIMAPFetchContentOperation.cpp @@ -0,0 +1,98 @@ +// +// IMAPFetchContentOperation.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPFetchContentOperation.h" + +#include "MCIMAPSession.h" +#include "MCIMAPAsyncConnection.h" + +using namespace mailcore; + +IMAPFetchContentOperation::IMAPFetchContentOperation() +{ + mUid = 0; + mNumber = 0; + mPartID = NULL; + mEncoding = Encoding7Bit; + mData = NULL; +} + +IMAPFetchContentOperation::~IMAPFetchContentOperation() +{ + MC_SAFE_RELEASE(mPartID); + MC_SAFE_RELEASE(mData); +} + +void IMAPFetchContentOperation::setUid(uint32_t uid) +{ + mUid = uid; +} + +uint32_t IMAPFetchContentOperation::uid() +{ + return mUid; +} + +void IMAPFetchContentOperation::setNumber(uint32_t value) +{ + mNumber = value; +} + +uint32_t IMAPFetchContentOperation::number() +{ + return mNumber; +} + +void IMAPFetchContentOperation::setPartID(String * partID) +{ + MC_SAFE_REPLACE_COPY(String, mPartID, partID); +} + +String * IMAPFetchContentOperation::partID() +{ + return mPartID; +} + +void IMAPFetchContentOperation::setEncoding(Encoding encoding) +{ + mEncoding = encoding; +} + +Encoding IMAPFetchContentOperation::encoding() +{ + return mEncoding; +} + +Data * IMAPFetchContentOperation::data() +{ + return mData; +} + +void IMAPFetchContentOperation::main() +{ + ErrorCode error; + if (mUid != 0) { + if (mPartID != NULL) { + mData = session()->session()->fetchMessageAttachmentByUID(folder(), mUid, mPartID, mEncoding, this, &error); + } + else { + mData = session()->session()->fetchMessageByUID(folder(), mUid, this, &error); + } + } + else { + if (mPartID != NULL) { + mData = session()->session()->fetchMessageAttachmentByNumber(folder(), mNumber, mPartID, mEncoding, this, &error); + } + else { + mData = session()->session()->fetchMessageByNumber(folder(), mNumber, this, &error); + } + } + MC_SAFE_RETAIN(mData); + setError(error); +} + diff --git a/src/async/imap/MCIMAPFetchFoldersOperation.cc b/src/async/imap/MCIMAPFetchFoldersOperation.cc deleted file mode 100644 index e1f121e8..00000000 --- a/src/async/imap/MCIMAPFetchFoldersOperation.cc +++ /dev/null @@ -1,55 +0,0 @@ -// -// MCIMAPFetchFoldersOperation.cpp -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/12/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPFetchFoldersOperation.h" - -#include - -#include "MCIMAPSession.h" -#include "MCIMAPAsyncConnection.h" - -using namespace mailcore; - -IMAPFetchFoldersOperation::IMAPFetchFoldersOperation() -{ - mFetchSubscribedEnabled = false; - mFolders = NULL; -} - -IMAPFetchFoldersOperation::~IMAPFetchFoldersOperation() -{ - MC_SAFE_RELEASE(mFolders); -} - -void IMAPFetchFoldersOperation::setFetchSubscribedEnabled(bool enabled) -{ - mFetchSubscribedEnabled = enabled; -} - -bool IMAPFetchFoldersOperation::isFetchSubscribedEnabled() -{ - return mFetchSubscribedEnabled; -} - -Array * IMAPFetchFoldersOperation::folders() -{ - return mFolders; -} - -void IMAPFetchFoldersOperation::main() -{ - ErrorCode error; - if (mFetchSubscribedEnabled) { - mFolders = session()->session()->fetchSubscribedFolders(&error); - } - else { - mFolders = session()->session()->fetchAllFolders(&error); - } - MC_SAFE_RETAIN(mFolders); - setError(error); -} diff --git a/src/async/imap/MCIMAPFetchFoldersOperation.cpp b/src/async/imap/MCIMAPFetchFoldersOperation.cpp new file mode 100644 index 00000000..e1f121e8 --- /dev/null +++ b/src/async/imap/MCIMAPFetchFoldersOperation.cpp @@ -0,0 +1,55 @@ +// +// MCIMAPFetchFoldersOperation.cpp +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPFetchFoldersOperation.h" + +#include + +#include "MCIMAPSession.h" +#include "MCIMAPAsyncConnection.h" + +using namespace mailcore; + +IMAPFetchFoldersOperation::IMAPFetchFoldersOperation() +{ + mFetchSubscribedEnabled = false; + mFolders = NULL; +} + +IMAPFetchFoldersOperation::~IMAPFetchFoldersOperation() +{ + MC_SAFE_RELEASE(mFolders); +} + +void IMAPFetchFoldersOperation::setFetchSubscribedEnabled(bool enabled) +{ + mFetchSubscribedEnabled = enabled; +} + +bool IMAPFetchFoldersOperation::isFetchSubscribedEnabled() +{ + return mFetchSubscribedEnabled; +} + +Array * IMAPFetchFoldersOperation::folders() +{ + return mFolders; +} + +void IMAPFetchFoldersOperation::main() +{ + ErrorCode error; + if (mFetchSubscribedEnabled) { + mFolders = session()->session()->fetchSubscribedFolders(&error); + } + else { + mFolders = session()->session()->fetchAllFolders(&error); + } + MC_SAFE_RETAIN(mFolders); + setError(error); +} diff --git a/src/async/imap/MCIMAPFetchMessagesOperation.cc b/src/async/imap/MCIMAPFetchMessagesOperation.cc deleted file mode 100644 index 480f2c1b..00000000 --- a/src/async/imap/MCIMAPFetchMessagesOperation.cc +++ /dev/null @@ -1,120 +0,0 @@ -// -// IMAPFetchMessagesOperation.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/12/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPFetchMessagesOperation.h" - -#include "MCIMAPSession.h" -#include "MCIMAPAsyncConnection.h" -#include "MCIMAPSyncResult.h" - -using namespace mailcore; - -IMAPFetchMessagesOperation::IMAPFetchMessagesOperation() -{ - mFetchByUidEnabled = false; - mIndexes = NULL; - mMessages = NULL; - mVanishedMessages = NULL; - mModSequenceValue = 0; - mExtraHeaders = NULL; -} - -IMAPFetchMessagesOperation::~IMAPFetchMessagesOperation() -{ - MC_SAFE_RELEASE(mIndexes); - MC_SAFE_RELEASE(mMessages); - MC_SAFE_RELEASE(mVanishedMessages); - MC_SAFE_RELEASE(mExtraHeaders); -} - -void IMAPFetchMessagesOperation::setFetchByUidEnabled(bool enabled) -{ - mFetchByUidEnabled = enabled; -} - -bool IMAPFetchMessagesOperation::isFetchByUidEnabled() -{ - return mFetchByUidEnabled; -} - -void IMAPFetchMessagesOperation::setIndexes(IndexSet * indexes) -{ - MC_SAFE_REPLACE_RETAIN(IndexSet, mIndexes, indexes); -} - -IndexSet * IMAPFetchMessagesOperation::indexes() -{ - return mIndexes; -} - -void IMAPFetchMessagesOperation::setModSequenceValue(uint64_t modseq) -{ - mModSequenceValue = modseq; -} - -uint64_t IMAPFetchMessagesOperation::modSequenceValue() -{ - return mModSequenceValue; -} - -void IMAPFetchMessagesOperation::setKind(IMAPMessagesRequestKind kind) -{ - mKind = kind; -} - -IMAPMessagesRequestKind IMAPFetchMessagesOperation::kind() -{ - return mKind; -} - -void IMAPFetchMessagesOperation::setExtraHeaders(Array * extraHeaders) { - MC_SAFE_REPLACE_COPY(Array, mExtraHeaders, extraHeaders); -} - -Array * IMAPFetchMessagesOperation::extraHeaders() { - return mExtraHeaders; -} - -Array * IMAPFetchMessagesOperation::messages() -{ - return mMessages; -} - -IndexSet * IMAPFetchMessagesOperation::vanishedMessages() -{ - return mVanishedMessages; -} - -void IMAPFetchMessagesOperation::main() -{ - ErrorCode error; - if (mFetchByUidEnabled) { - if (mModSequenceValue != 0) { - IMAPSyncResult * syncResult; - - syncResult = session()->session()->syncMessagesByUIDWithExtraHeaders(folder(), mKind, mIndexes, - mModSequenceValue, this, mExtraHeaders, - &error); - if (syncResult != NULL) { - mMessages = syncResult->modifiedOrAddedMessages(); - mVanishedMessages = syncResult->vanishedMessages(); - } - } - else { - mMessages = session()->session()->fetchMessagesByUIDWithExtraHeaders(folder(), mKind, mIndexes, this, - mExtraHeaders, &error); - } - } - else { - mMessages = session()->session()->fetchMessagesByNumberWithExtraHeaders(folder(), mKind, mIndexes, this, - mExtraHeaders, &error); - } - MC_SAFE_RETAIN(mMessages); - MC_SAFE_RETAIN(mVanishedMessages); - setError(error); -} diff --git a/src/async/imap/MCIMAPFetchMessagesOperation.cpp b/src/async/imap/MCIMAPFetchMessagesOperation.cpp new file mode 100644 index 00000000..480f2c1b --- /dev/null +++ b/src/async/imap/MCIMAPFetchMessagesOperation.cpp @@ -0,0 +1,120 @@ +// +// IMAPFetchMessagesOperation.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPFetchMessagesOperation.h" + +#include "MCIMAPSession.h" +#include "MCIMAPAsyncConnection.h" +#include "MCIMAPSyncResult.h" + +using namespace mailcore; + +IMAPFetchMessagesOperation::IMAPFetchMessagesOperation() +{ + mFetchByUidEnabled = false; + mIndexes = NULL; + mMessages = NULL; + mVanishedMessages = NULL; + mModSequenceValue = 0; + mExtraHeaders = NULL; +} + +IMAPFetchMessagesOperation::~IMAPFetchMessagesOperation() +{ + MC_SAFE_RELEASE(mIndexes); + MC_SAFE_RELEASE(mMessages); + MC_SAFE_RELEASE(mVanishedMessages); + MC_SAFE_RELEASE(mExtraHeaders); +} + +void IMAPFetchMessagesOperation::setFetchByUidEnabled(bool enabled) +{ + mFetchByUidEnabled = enabled; +} + +bool IMAPFetchMessagesOperation::isFetchByUidEnabled() +{ + return mFetchByUidEnabled; +} + +void IMAPFetchMessagesOperation::setIndexes(IndexSet * indexes) +{ + MC_SAFE_REPLACE_RETAIN(IndexSet, mIndexes, indexes); +} + +IndexSet * IMAPFetchMessagesOperation::indexes() +{ + return mIndexes; +} + +void IMAPFetchMessagesOperation::setModSequenceValue(uint64_t modseq) +{ + mModSequenceValue = modseq; +} + +uint64_t IMAPFetchMessagesOperation::modSequenceValue() +{ + return mModSequenceValue; +} + +void IMAPFetchMessagesOperation::setKind(IMAPMessagesRequestKind kind) +{ + mKind = kind; +} + +IMAPMessagesRequestKind IMAPFetchMessagesOperation::kind() +{ + return mKind; +} + +void IMAPFetchMessagesOperation::setExtraHeaders(Array * extraHeaders) { + MC_SAFE_REPLACE_COPY(Array, mExtraHeaders, extraHeaders); +} + +Array * IMAPFetchMessagesOperation::extraHeaders() { + return mExtraHeaders; +} + +Array * IMAPFetchMessagesOperation::messages() +{ + return mMessages; +} + +IndexSet * IMAPFetchMessagesOperation::vanishedMessages() +{ + return mVanishedMessages; +} + +void IMAPFetchMessagesOperation::main() +{ + ErrorCode error; + if (mFetchByUidEnabled) { + if (mModSequenceValue != 0) { + IMAPSyncResult * syncResult; + + syncResult = session()->session()->syncMessagesByUIDWithExtraHeaders(folder(), mKind, mIndexes, + mModSequenceValue, this, mExtraHeaders, + &error); + if (syncResult != NULL) { + mMessages = syncResult->modifiedOrAddedMessages(); + mVanishedMessages = syncResult->vanishedMessages(); + } + } + else { + mMessages = session()->session()->fetchMessagesByUIDWithExtraHeaders(folder(), mKind, mIndexes, this, + mExtraHeaders, &error); + } + } + else { + mMessages = session()->session()->fetchMessagesByNumberWithExtraHeaders(folder(), mKind, mIndexes, this, + mExtraHeaders, &error); + } + MC_SAFE_RETAIN(mMessages); + MC_SAFE_RETAIN(mVanishedMessages); + setError(error); +} diff --git a/src/async/imap/MCIMAPFetchNamespaceOperation.cc b/src/async/imap/MCIMAPFetchNamespaceOperation.cc deleted file mode 100644 index 6851130d..00000000 --- a/src/async/imap/MCIMAPFetchNamespaceOperation.cc +++ /dev/null @@ -1,38 +0,0 @@ -// -// IMAPFetchNamespaceOperation.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/12/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPFetchNamespaceOperation.h" - -#include "MCIMAPSession.h" -#include "MCIMAPAsyncConnection.h" - -using namespace mailcore; - -IMAPFetchNamespaceOperation::IMAPFetchNamespaceOperation() -{ - mNamespaces = NULL; -} - -IMAPFetchNamespaceOperation::~IMAPFetchNamespaceOperation() -{ - MC_SAFE_RELEASE(mNamespaces); -} - -void IMAPFetchNamespaceOperation::main() -{ - ErrorCode error; - mNamespaces = session()->session()->fetchNamespace(&error); - setError(error); - MC_SAFE_RETAIN(mNamespaces); -} - -HashMap * IMAPFetchNamespaceOperation::namespaces() -{ - return mNamespaces; -} - diff --git a/src/async/imap/MCIMAPFetchNamespaceOperation.cpp b/src/async/imap/MCIMAPFetchNamespaceOperation.cpp new file mode 100644 index 00000000..6851130d --- /dev/null +++ b/src/async/imap/MCIMAPFetchNamespaceOperation.cpp @@ -0,0 +1,38 @@ +// +// IMAPFetchNamespaceOperation.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPFetchNamespaceOperation.h" + +#include "MCIMAPSession.h" +#include "MCIMAPAsyncConnection.h" + +using namespace mailcore; + +IMAPFetchNamespaceOperation::IMAPFetchNamespaceOperation() +{ + mNamespaces = NULL; +} + +IMAPFetchNamespaceOperation::~IMAPFetchNamespaceOperation() +{ + MC_SAFE_RELEASE(mNamespaces); +} + +void IMAPFetchNamespaceOperation::main() +{ + ErrorCode error; + mNamespaces = session()->session()->fetchNamespace(&error); + setError(error); + MC_SAFE_RETAIN(mNamespaces); +} + +HashMap * IMAPFetchNamespaceOperation::namespaces() +{ + return mNamespaces; +} + diff --git a/src/async/imap/MCIMAPFetchParsedContentOperation.cc b/src/async/imap/MCIMAPFetchParsedContentOperation.cc deleted file mode 100644 index e32112e6..00000000 --- a/src/async/imap/MCIMAPFetchParsedContentOperation.cc +++ /dev/null @@ -1,79 +0,0 @@ -// -// IMAPFetchParsedContentOperation.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/12/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPFetchParsedContentOperation.h" - -#include "MCIMAPSession.h" -#include "MCIMAPAsyncConnection.h" - -using namespace mailcore; - -IMAPFetchParsedContentOperation::IMAPFetchParsedContentOperation() -{ - mUid = 0; - mNumber = 0; - mEncoding = Encoding7Bit; - mParser = NULL; -} - -IMAPFetchParsedContentOperation::~IMAPFetchParsedContentOperation() -{ - MC_SAFE_RELEASE(mParser); -} - -void IMAPFetchParsedContentOperation::setUid(uint32_t uid) -{ - mUid = uid; -} - -uint32_t IMAPFetchParsedContentOperation::uid() -{ - return mUid; -} - -void IMAPFetchParsedContentOperation::setNumber(uint32_t value) -{ - mNumber = value; -} - -uint32_t IMAPFetchParsedContentOperation::number() -{ - return mNumber; -} - -void IMAPFetchParsedContentOperation::setEncoding(Encoding encoding) -{ - mEncoding = encoding; -} - -Encoding IMAPFetchParsedContentOperation::encoding() -{ - return mEncoding; -} - -MessageParser * IMAPFetchParsedContentOperation::parser() -{ - return mParser; -} - -void IMAPFetchParsedContentOperation::main() -{ - ErrorCode error; - Data * data; - if (mUid != 0) { - data = session()->session()->fetchMessageByUID(folder(), mUid, this, &error); - } - else { - data = session()->session()->fetchMessageByNumber(folder(), mNumber, this, &error); - } - if (data) { - mParser = new mailcore::MessageParser(data); - } - setError(error); -} - diff --git a/src/async/imap/MCIMAPFetchParsedContentOperation.cpp b/src/async/imap/MCIMAPFetchParsedContentOperation.cpp new file mode 100644 index 00000000..e32112e6 --- /dev/null +++ b/src/async/imap/MCIMAPFetchParsedContentOperation.cpp @@ -0,0 +1,79 @@ +// +// IMAPFetchParsedContentOperation.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPFetchParsedContentOperation.h" + +#include "MCIMAPSession.h" +#include "MCIMAPAsyncConnection.h" + +using namespace mailcore; + +IMAPFetchParsedContentOperation::IMAPFetchParsedContentOperation() +{ + mUid = 0; + mNumber = 0; + mEncoding = Encoding7Bit; + mParser = NULL; +} + +IMAPFetchParsedContentOperation::~IMAPFetchParsedContentOperation() +{ + MC_SAFE_RELEASE(mParser); +} + +void IMAPFetchParsedContentOperation::setUid(uint32_t uid) +{ + mUid = uid; +} + +uint32_t IMAPFetchParsedContentOperation::uid() +{ + return mUid; +} + +void IMAPFetchParsedContentOperation::setNumber(uint32_t value) +{ + mNumber = value; +} + +uint32_t IMAPFetchParsedContentOperation::number() +{ + return mNumber; +} + +void IMAPFetchParsedContentOperation::setEncoding(Encoding encoding) +{ + mEncoding = encoding; +} + +Encoding IMAPFetchParsedContentOperation::encoding() +{ + return mEncoding; +} + +MessageParser * IMAPFetchParsedContentOperation::parser() +{ + return mParser; +} + +void IMAPFetchParsedContentOperation::main() +{ + ErrorCode error; + Data * data; + if (mUid != 0) { + data = session()->session()->fetchMessageByUID(folder(), mUid, this, &error); + } + else { + data = session()->session()->fetchMessageByNumber(folder(), mNumber, this, &error); + } + if (data) { + mParser = new mailcore::MessageParser(data); + } + setError(error); +} + diff --git a/src/async/imap/MCIMAPFolderInfoOperation.cc b/src/async/imap/MCIMAPFolderInfoOperation.cc deleted file mode 100644 index 0ea0d005..00000000 --- a/src/async/imap/MCIMAPFolderInfoOperation.cc +++ /dev/null @@ -1,86 +0,0 @@ -// -// MCIMAPFolderInfoOperation.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/13/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPFolderInfoOperation.h" - -#include "MCIMAPSession.h" -#include "MCIMAPAsyncConnection.h" - -using namespace mailcore; - -IMAPFolderInfoOperation::IMAPFolderInfoOperation() -{ - mUidNext = 0; - mUidValidity = 0; - mMessageCount = 0; - mModSequenceValue = 0; - mFirstUnseenUid = 0; - mAllowsNewPermanentFlags = false; -} - -IMAPFolderInfoOperation::~IMAPFolderInfoOperation() -{ -} - -uint32_t IMAPFolderInfoOperation::uidNext() -{ - return mUidNext; -} - -uint32_t IMAPFolderInfoOperation::uidValidity() -{ - return mUidValidity; -} - -uint64_t IMAPFolderInfoOperation::modSequenceValue() -{ - return mModSequenceValue; -} - -int IMAPFolderInfoOperation::messageCount() -{ - return mMessageCount; -} - -uint32_t IMAPFolderInfoOperation::firstUnseenUid() -{ - return mFirstUnseenUid; -} - -bool IMAPFolderInfoOperation::allowsNewPermanentFlags() -{ - return mAllowsNewPermanentFlags; -} - -void IMAPFolderInfoOperation::main() -{ - ErrorCode error; - - session()->session()->loginIfNeeded(&error); - if (error != ErrorNone) { - setError(error); - return; - } - - session()->session()->select(folder(), &error); - if (error != ErrorNone) { - setError(error); - return; - } - - - mUidNext = session()->session()->uidNext(); - mUidValidity = session()->session()->uidValidity(); - mModSequenceValue = session()->session()->modSequenceValue(); - mMessageCount = session()->session()->lastFolderMessageCount(); - mFirstUnseenUid = session()->session()->firstUnseenUid(); - mAllowsNewPermanentFlags = session()->session()->allowsNewPermanentFlags(); - - setError(error); -} - diff --git a/src/async/imap/MCIMAPFolderInfoOperation.cpp b/src/async/imap/MCIMAPFolderInfoOperation.cpp new file mode 100644 index 00000000..0ea0d005 --- /dev/null +++ b/src/async/imap/MCIMAPFolderInfoOperation.cpp @@ -0,0 +1,86 @@ +// +// MCIMAPFolderInfoOperation.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/13/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPFolderInfoOperation.h" + +#include "MCIMAPSession.h" +#include "MCIMAPAsyncConnection.h" + +using namespace mailcore; + +IMAPFolderInfoOperation::IMAPFolderInfoOperation() +{ + mUidNext = 0; + mUidValidity = 0; + mMessageCount = 0; + mModSequenceValue = 0; + mFirstUnseenUid = 0; + mAllowsNewPermanentFlags = false; +} + +IMAPFolderInfoOperation::~IMAPFolderInfoOperation() +{ +} + +uint32_t IMAPFolderInfoOperation::uidNext() +{ + return mUidNext; +} + +uint32_t IMAPFolderInfoOperation::uidValidity() +{ + return mUidValidity; +} + +uint64_t IMAPFolderInfoOperation::modSequenceValue() +{ + return mModSequenceValue; +} + +int IMAPFolderInfoOperation::messageCount() +{ + return mMessageCount; +} + +uint32_t IMAPFolderInfoOperation::firstUnseenUid() +{ + return mFirstUnseenUid; +} + +bool IMAPFolderInfoOperation::allowsNewPermanentFlags() +{ + return mAllowsNewPermanentFlags; +} + +void IMAPFolderInfoOperation::main() +{ + ErrorCode error; + + session()->session()->loginIfNeeded(&error); + if (error != ErrorNone) { + setError(error); + return; + } + + session()->session()->select(folder(), &error); + if (error != ErrorNone) { + setError(error); + return; + } + + + mUidNext = session()->session()->uidNext(); + mUidValidity = session()->session()->uidValidity(); + mModSequenceValue = session()->session()->modSequenceValue(); + mMessageCount = session()->session()->lastFolderMessageCount(); + mFirstUnseenUid = session()->session()->firstUnseenUid(); + mAllowsNewPermanentFlags = session()->session()->allowsNewPermanentFlags(); + + setError(error); +} + diff --git a/src/async/imap/MCIMAPFolderStatusOperation.cc b/src/async/imap/MCIMAPFolderStatusOperation.cc deleted file mode 100644 index 22f2797b..00000000 --- a/src/async/imap/MCIMAPFolderStatusOperation.cc +++ /dev/null @@ -1,51 +0,0 @@ -// -// MCIMAPFolderStatusOperation.cc -// mailcore2 -// -// Created by Sebastian on 6/5/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPFolderStatusOperation.h" - -#include "MCIMAPSession.h" -#include "MCIMAPAsyncConnection.h" -#include "MCIMAPFolderStatus.h" - -using namespace mailcore; - -IMAPFolderStatusOperation::IMAPFolderStatusOperation() -{ - mStatus = NULL; -} - -IMAPFolderStatusOperation::~IMAPFolderStatusOperation() -{ - MC_SAFE_RELEASE(mStatus); -} - -void IMAPFolderStatusOperation::main() -{ - ErrorCode error; - - session()->session()->loginIfNeeded(&error); - if (error != ErrorNone) { - setError(error); - return; - } - - IMAPFolderStatus *status = session()->session()->folderStatus(folder(), &error); - if (error != ErrorNone) { - setError(error); - return; - } - - MC_SAFE_REPLACE_RETAIN(IMAPFolderStatus, mStatus, status); - setError(error); -} - -IMAPFolderStatus * IMAPFolderStatusOperation::status() -{ - return mStatus; -} - diff --git a/src/async/imap/MCIMAPFolderStatusOperation.cpp b/src/async/imap/MCIMAPFolderStatusOperation.cpp new file mode 100644 index 00000000..22f2797b --- /dev/null +++ b/src/async/imap/MCIMAPFolderStatusOperation.cpp @@ -0,0 +1,51 @@ +// +// MCIMAPFolderStatusOperation.cc +// mailcore2 +// +// Created by Sebastian on 6/5/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPFolderStatusOperation.h" + +#include "MCIMAPSession.h" +#include "MCIMAPAsyncConnection.h" +#include "MCIMAPFolderStatus.h" + +using namespace mailcore; + +IMAPFolderStatusOperation::IMAPFolderStatusOperation() +{ + mStatus = NULL; +} + +IMAPFolderStatusOperation::~IMAPFolderStatusOperation() +{ + MC_SAFE_RELEASE(mStatus); +} + +void IMAPFolderStatusOperation::main() +{ + ErrorCode error; + + session()->session()->loginIfNeeded(&error); + if (error != ErrorNone) { + setError(error); + return; + } + + IMAPFolderStatus *status = session()->session()->folderStatus(folder(), &error); + if (error != ErrorNone) { + setError(error); + return; + } + + MC_SAFE_REPLACE_RETAIN(IMAPFolderStatus, mStatus, status); + setError(error); +} + +IMAPFolderStatus * IMAPFolderStatusOperation::status() +{ + return mStatus; +} + diff --git a/src/async/imap/MCIMAPIdentityOperation.cc b/src/async/imap/MCIMAPIdentityOperation.cc deleted file mode 100644 index 0dc035e5..00000000 --- a/src/async/imap/MCIMAPIdentityOperation.cc +++ /dev/null @@ -1,51 +0,0 @@ -// -// IMAPIdentityOperation.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/12/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPIdentityOperation.h" - -#include "MCIMAPSession.h" -#include "MCIMAPAsyncConnection.h" -#include "MCIMAPIdentity.h" - -using namespace mailcore; - -IMAPIdentityOperation::IMAPIdentityOperation() -{ - mClientIdentity = NULL; - mServerIdentity = NULL; -} - -IMAPIdentityOperation::~IMAPIdentityOperation() -{ - MC_SAFE_RELEASE(mClientIdentity); - MC_SAFE_RELEASE(mServerIdentity); -} - -void IMAPIdentityOperation::setClientIdentity(IMAPIdentity * identity) -{ - MC_SAFE_REPLACE_COPY(IMAPIdentity, mClientIdentity, identity); -} - -IMAPIdentity * IMAPIdentityOperation::clientIdentity() -{ - return mClientIdentity; -} - -IMAPIdentity * IMAPIdentityOperation::serverIdentity() -{ - return mServerIdentity; -} - -void IMAPIdentityOperation::main() -{ - ErrorCode error; - mServerIdentity = session()->session()->identity(mClientIdentity, &error); - MC_SAFE_RETAIN(mServerIdentity); - setError(error); -} - diff --git a/src/async/imap/MCIMAPIdentityOperation.cpp b/src/async/imap/MCIMAPIdentityOperation.cpp new file mode 100644 index 00000000..0dc035e5 --- /dev/null +++ b/src/async/imap/MCIMAPIdentityOperation.cpp @@ -0,0 +1,51 @@ +// +// IMAPIdentityOperation.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPIdentityOperation.h" + +#include "MCIMAPSession.h" +#include "MCIMAPAsyncConnection.h" +#include "MCIMAPIdentity.h" + +using namespace mailcore; + +IMAPIdentityOperation::IMAPIdentityOperation() +{ + mClientIdentity = NULL; + mServerIdentity = NULL; +} + +IMAPIdentityOperation::~IMAPIdentityOperation() +{ + MC_SAFE_RELEASE(mClientIdentity); + MC_SAFE_RELEASE(mServerIdentity); +} + +void IMAPIdentityOperation::setClientIdentity(IMAPIdentity * identity) +{ + MC_SAFE_REPLACE_COPY(IMAPIdentity, mClientIdentity, identity); +} + +IMAPIdentity * IMAPIdentityOperation::clientIdentity() +{ + return mClientIdentity; +} + +IMAPIdentity * IMAPIdentityOperation::serverIdentity() +{ + return mServerIdentity; +} + +void IMAPIdentityOperation::main() +{ + ErrorCode error; + mServerIdentity = session()->session()->identity(mClientIdentity, &error); + MC_SAFE_RETAIN(mServerIdentity); + setError(error); +} + diff --git a/src/async/imap/MCIMAPIdleOperation.cc b/src/async/imap/MCIMAPIdleOperation.cc deleted file mode 100644 index 7154a9f0..00000000 --- a/src/async/imap/MCIMAPIdleOperation.cc +++ /dev/null @@ -1,98 +0,0 @@ -// -// IMAPIdleOperation.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/12/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPIdleOperation.h" - -#include "MCIMAPSession.h" -#include "MCIMAPAsyncConnection.h" - -using namespace mailcore; - -IMAPIdleOperation::IMAPIdleOperation() -{ - mLastKnownUid = 0; - mSetupSuccess = false; - mInterrupted = false; - pthread_mutex_init(&mLock, NULL); -} - -IMAPIdleOperation::~IMAPIdleOperation() -{ - pthread_mutex_destroy(&mLock); -} - -void IMAPIdleOperation::setLastKnownUID(uint32_t uid) -{ - mLastKnownUid = uid; -} - -uint32_t IMAPIdleOperation::lastKnownUID() -{ - return mLastKnownUid; -} - -void IMAPIdleOperation::prepare(void * data) -{ - if (isInterrupted()) { - mSetupSuccess = false; - return; - } - - mSetupSuccess = session()->session()->setupIdle(); -} - -void IMAPIdleOperation::unprepare(void * data) -{ - if (mSetupSuccess) { - session()->session()->unsetupIdle(); - } -} - -bool IMAPIdleOperation::isInterrupted() { - pthread_mutex_lock(&mLock); - bool interrupted = mInterrupted; - pthread_mutex_unlock(&mLock); - - return interrupted; -} - -void IMAPIdleOperation::main() -{ - if (isInterrupted()) { - return; - } - - ErrorCode error; - session()->session()->selectIfNeeded(folder(), &error); - if (error != ErrorNone) { - setError(error); - return; - } - - performMethodOnCallbackThread((Object::Method) &IMAPIdleOperation::prepare, NULL, true); - - if (!mSetupSuccess) { - return; - } - - session()->session()->idle(folder(), mLastKnownUid, &error); - setError(error); - - performMethodOnCallbackThread((Object::Method) &IMAPIdleOperation::unprepare, NULL, true); -} - -void IMAPIdleOperation::interruptIdle() -{ - pthread_mutex_lock(&mLock); - mInterrupted = true; - pthread_mutex_unlock(&mLock); - if (mSetupSuccess) { - session()->session()->interruptIdle(); - } -} - diff --git a/src/async/imap/MCIMAPIdleOperation.cpp b/src/async/imap/MCIMAPIdleOperation.cpp new file mode 100644 index 00000000..7154a9f0 --- /dev/null +++ b/src/async/imap/MCIMAPIdleOperation.cpp @@ -0,0 +1,98 @@ +// +// IMAPIdleOperation.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPIdleOperation.h" + +#include "MCIMAPSession.h" +#include "MCIMAPAsyncConnection.h" + +using namespace mailcore; + +IMAPIdleOperation::IMAPIdleOperation() +{ + mLastKnownUid = 0; + mSetupSuccess = false; + mInterrupted = false; + pthread_mutex_init(&mLock, NULL); +} + +IMAPIdleOperation::~IMAPIdleOperation() +{ + pthread_mutex_destroy(&mLock); +} + +void IMAPIdleOperation::setLastKnownUID(uint32_t uid) +{ + mLastKnownUid = uid; +} + +uint32_t IMAPIdleOperation::lastKnownUID() +{ + return mLastKnownUid; +} + +void IMAPIdleOperation::prepare(void * data) +{ + if (isInterrupted()) { + mSetupSuccess = false; + return; + } + + mSetupSuccess = session()->session()->setupIdle(); +} + +void IMAPIdleOperation::unprepare(void * data) +{ + if (mSetupSuccess) { + session()->session()->unsetupIdle(); + } +} + +bool IMAPIdleOperation::isInterrupted() { + pthread_mutex_lock(&mLock); + bool interrupted = mInterrupted; + pthread_mutex_unlock(&mLock); + + return interrupted; +} + +void IMAPIdleOperation::main() +{ + if (isInterrupted()) { + return; + } + + ErrorCode error; + session()->session()->selectIfNeeded(folder(), &error); + if (error != ErrorNone) { + setError(error); + return; + } + + performMethodOnCallbackThread((Object::Method) &IMAPIdleOperation::prepare, NULL, true); + + if (!mSetupSuccess) { + return; + } + + session()->session()->idle(folder(), mLastKnownUid, &error); + setError(error); + + performMethodOnCallbackThread((Object::Method) &IMAPIdleOperation::unprepare, NULL, true); +} + +void IMAPIdleOperation::interruptIdle() +{ + pthread_mutex_lock(&mLock); + mInterrupted = true; + pthread_mutex_unlock(&mLock); + if (mSetupSuccess) { + session()->session()->interruptIdle(); + } +} + diff --git a/src/async/imap/MCIMAPMessageRenderingOperation.cc b/src/async/imap/MCIMAPMessageRenderingOperation.cc deleted file mode 100644 index e30bcd67..00000000 --- a/src/async/imap/MCIMAPMessageRenderingOperation.cc +++ /dev/null @@ -1,76 +0,0 @@ -// -// MCIMAPMessageRenderingOperation.cc -// mailcore2 -// -// Created by Paul Young on 27/06/2013. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPMessageRenderingOperation.h" - -#include "MCIMAPSession.h" -#include "MCIMAPAsyncConnection.h" - -using namespace mailcore; - -IMAPMessageRenderingOperation::IMAPMessageRenderingOperation() -{ - mMessage = NULL; - mRenderingType = IMAPMessageRenderingTypePlainTextBody; - mResult = NULL; -} - -IMAPMessageRenderingOperation::~IMAPMessageRenderingOperation() -{ - MC_SAFE_RELEASE(mMessage); - MC_SAFE_RELEASE(mResult); -} - -void IMAPMessageRenderingOperation::setRenderingType(IMAPMessageRenderingType type) -{ - mRenderingType = type; -} - -IMAPMessageRenderingType IMAPMessageRenderingOperation::renderingType() -{ - return mRenderingType; -} - -void IMAPMessageRenderingOperation::setMessage(IMAPMessage * message) -{ - MC_SAFE_REPLACE_COPY(IMAPMessage, mMessage, message); -} - -IMAPMessage * IMAPMessageRenderingOperation::message() -{ - return mMessage; -} - -String * IMAPMessageRenderingOperation::result() -{ - return mResult; -} - -void IMAPMessageRenderingOperation::main() -{ - ErrorCode error = ErrorNone; - - if (mRenderingType == IMAPMessageRenderingTypeHTML) { - mResult = session()->session()->htmlRendering(mMessage, folder(), &error); - } - else if (mRenderingType == IMAPMessageRenderingTypeHTMLBody) { - mResult = session()->session()->htmlBodyRendering(mMessage, folder(), &error); - } - else if (mRenderingType == IMAPMessageRenderingTypePlainText) { - mResult = session()->session()->plainTextRendering(mMessage, folder(), &error); - } - else if (mRenderingType == IMAPMessageRenderingTypePlainTextBody) { - mResult = session()->session()->plainTextBodyRendering(mMessage, folder(), false, &error); - } - else if (mRenderingType == IMAPMessageRenderingTypePlainTextBodyAndStripWhitespace) { - mResult = session()->session()->plainTextBodyRendering(mMessage, folder(), true, &error); - } - - MC_SAFE_RETAIN(mResult); - setError(error); -} diff --git a/src/async/imap/MCIMAPMessageRenderingOperation.cpp b/src/async/imap/MCIMAPMessageRenderingOperation.cpp new file mode 100644 index 00000000..e30bcd67 --- /dev/null +++ b/src/async/imap/MCIMAPMessageRenderingOperation.cpp @@ -0,0 +1,76 @@ +// +// MCIMAPMessageRenderingOperation.cc +// mailcore2 +// +// Created by Paul Young on 27/06/2013. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPMessageRenderingOperation.h" + +#include "MCIMAPSession.h" +#include "MCIMAPAsyncConnection.h" + +using namespace mailcore; + +IMAPMessageRenderingOperation::IMAPMessageRenderingOperation() +{ + mMessage = NULL; + mRenderingType = IMAPMessageRenderingTypePlainTextBody; + mResult = NULL; +} + +IMAPMessageRenderingOperation::~IMAPMessageRenderingOperation() +{ + MC_SAFE_RELEASE(mMessage); + MC_SAFE_RELEASE(mResult); +} + +void IMAPMessageRenderingOperation::setRenderingType(IMAPMessageRenderingType type) +{ + mRenderingType = type; +} + +IMAPMessageRenderingType IMAPMessageRenderingOperation::renderingType() +{ + return mRenderingType; +} + +void IMAPMessageRenderingOperation::setMessage(IMAPMessage * message) +{ + MC_SAFE_REPLACE_COPY(IMAPMessage, mMessage, message); +} + +IMAPMessage * IMAPMessageRenderingOperation::message() +{ + return mMessage; +} + +String * IMAPMessageRenderingOperation::result() +{ + return mResult; +} + +void IMAPMessageRenderingOperation::main() +{ + ErrorCode error = ErrorNone; + + if (mRenderingType == IMAPMessageRenderingTypeHTML) { + mResult = session()->session()->htmlRendering(mMessage, folder(), &error); + } + else if (mRenderingType == IMAPMessageRenderingTypeHTMLBody) { + mResult = session()->session()->htmlBodyRendering(mMessage, folder(), &error); + } + else if (mRenderingType == IMAPMessageRenderingTypePlainText) { + mResult = session()->session()->plainTextRendering(mMessage, folder(), &error); + } + else if (mRenderingType == IMAPMessageRenderingTypePlainTextBody) { + mResult = session()->session()->plainTextBodyRendering(mMessage, folder(), false, &error); + } + else if (mRenderingType == IMAPMessageRenderingTypePlainTextBodyAndStripWhitespace) { + mResult = session()->session()->plainTextBodyRendering(mMessage, folder(), true, &error); + } + + MC_SAFE_RETAIN(mResult); + setError(error); +} diff --git a/src/async/imap/MCIMAPMultiDisconnectOperation.cc b/src/async/imap/MCIMAPMultiDisconnectOperation.cc deleted file mode 100644 index f6d0b180..00000000 --- a/src/async/imap/MCIMAPMultiDisconnectOperation.cc +++ /dev/null @@ -1,58 +0,0 @@ -// -// MCIMAPMultiDisconnectOperation.cc -// mailcore2 -// -// Created by Hoa V. DINH on 11/7/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPMultiDisconnectOperation.h" - -using namespace mailcore; - -IMAPMultiDisconnectOperation::IMAPMultiDisconnectOperation() -{ - _count = 0; - _operations = new Array(); -} - -IMAPMultiDisconnectOperation::~IMAPMultiDisconnectOperation() -{ - MC_SAFE_RELEASE(_operations); -} - -void IMAPMultiDisconnectOperation::addOperation(IMAPOperation * op) -{ - _operations->addObject(op); -} - -void IMAPMultiDisconnectOperation::start() -{ - if (_operations->count() == 0) { - if (callback() != NULL) { - callback()->operationFinished(this); - } - return; - } - - retain(); - mc_foreacharray(IMAPOperation, op, _operations) { -#if __APPLE__ - op->setCallbackDispatchQueue(this->callbackDispatchQueue()); -#endif - op->setCallback(this); - op->start(); - } -} - -void IMAPMultiDisconnectOperation::operationFinished(Operation * op) -{ - _count ++; - if (_count == _operations->count()) { - if (callback() != NULL) { - callback()->operationFinished(this); - } - release(); - } -} - diff --git a/src/async/imap/MCIMAPMultiDisconnectOperation.cpp b/src/async/imap/MCIMAPMultiDisconnectOperation.cpp new file mode 100644 index 00000000..f6d0b180 --- /dev/null +++ b/src/async/imap/MCIMAPMultiDisconnectOperation.cpp @@ -0,0 +1,58 @@ +// +// MCIMAPMultiDisconnectOperation.cc +// mailcore2 +// +// Created by Hoa V. DINH on 11/7/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPMultiDisconnectOperation.h" + +using namespace mailcore; + +IMAPMultiDisconnectOperation::IMAPMultiDisconnectOperation() +{ + _count = 0; + _operations = new Array(); +} + +IMAPMultiDisconnectOperation::~IMAPMultiDisconnectOperation() +{ + MC_SAFE_RELEASE(_operations); +} + +void IMAPMultiDisconnectOperation::addOperation(IMAPOperation * op) +{ + _operations->addObject(op); +} + +void IMAPMultiDisconnectOperation::start() +{ + if (_operations->count() == 0) { + if (callback() != NULL) { + callback()->operationFinished(this); + } + return; + } + + retain(); + mc_foreacharray(IMAPOperation, op, _operations) { +#if __APPLE__ + op->setCallbackDispatchQueue(this->callbackDispatchQueue()); +#endif + op->setCallback(this); + op->start(); + } +} + +void IMAPMultiDisconnectOperation::operationFinished(Operation * op) +{ + _count ++; + if (_count == _operations->count()) { + if (callback() != NULL) { + callback()->operationFinished(this); + } + release(); + } +} + diff --git a/src/async/imap/MCIMAPNoopOperation.cc b/src/async/imap/MCIMAPNoopOperation.cc deleted file mode 100644 index 19a82883..00000000 --- a/src/async/imap/MCIMAPNoopOperation.cc +++ /dev/null @@ -1,29 +0,0 @@ -// -// MCIMAPNoopOperation.cpp -// mailcore2 -// -// Created by Robert Widmann on 9/24/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPNoopOperation.h" - -#include "MCIMAPSession.h" -#include "MCIMAPAsyncConnection.h" - -using namespace mailcore; - -IMAPNoopOperation::IMAPNoopOperation() -{ -} - -IMAPNoopOperation::~IMAPNoopOperation() -{ -} - -void IMAPNoopOperation::main() -{ - ErrorCode error; - session()->session()->noop(&error); - setError(error); -} diff --git a/src/async/imap/MCIMAPNoopOperation.cpp b/src/async/imap/MCIMAPNoopOperation.cpp new file mode 100644 index 00000000..19a82883 --- /dev/null +++ b/src/async/imap/MCIMAPNoopOperation.cpp @@ -0,0 +1,29 @@ +// +// MCIMAPNoopOperation.cpp +// mailcore2 +// +// Created by Robert Widmann on 9/24/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPNoopOperation.h" + +#include "MCIMAPSession.h" +#include "MCIMAPAsyncConnection.h" + +using namespace mailcore; + +IMAPNoopOperation::IMAPNoopOperation() +{ +} + +IMAPNoopOperation::~IMAPNoopOperation() +{ +} + +void IMAPNoopOperation::main() +{ + ErrorCode error; + session()->session()->noop(&error); + setError(error); +} diff --git a/src/async/imap/MCIMAPOperation.cc b/src/async/imap/MCIMAPOperation.cc deleted file mode 100644 index 9ab30ab0..00000000 --- a/src/async/imap/MCIMAPOperation.cc +++ /dev/null @@ -1,185 +0,0 @@ -// -// MCIMAPOperation.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/12/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPOperation.h" - -#include - -#include "MCIMAPAsyncSession.h" -#include "MCIMAPSession.h" -#include "MCIMAPAsyncConnection.h" -#include "MCIMAPOperationCallback.h" - -using namespace mailcore; - -IMAPOperation::IMAPOperation() -{ - mSession = NULL; - mMainSession = NULL; - mImapCallback = NULL; - mError = ErrorNone; - mFolder = NULL; - mUrgent = false; -} - -IMAPOperation::~IMAPOperation() -{ - MC_SAFE_RELEASE(mMainSession); - MC_SAFE_RELEASE(mFolder); - MC_SAFE_RELEASE(mSession); -} - -void IMAPOperation::setSession(IMAPAsyncConnection * session) -{ - MC_SAFE_REPLACE_RETAIN(IMAPAsyncConnection, mSession, session); -#if __APPLE__ - dispatch_queue_t queue; - if (session != NULL) { - queue = session->dispatchQueue(); - } - else { - queue = dispatch_get_main_queue(); - } - setCallbackDispatchQueue(queue); -#endif -} - -IMAPAsyncConnection * IMAPOperation::session() -{ - return mSession; -} - -void IMAPOperation::setMainSession(IMAPAsyncSession * session) -{ - MC_SAFE_REPLACE_RETAIN(IMAPAsyncSession, mMainSession, session); -} - -IMAPAsyncSession * IMAPOperation::mainSession() -{ - return mMainSession; -} - -void IMAPOperation::setFolder(String * folder) -{ - MC_SAFE_REPLACE_COPY(String, mFolder, folder); -} - -String * IMAPOperation::folder() -{ - return mFolder; -} - -void IMAPOperation::setUrgent(bool urgent) -{ - mUrgent = urgent; -} - -bool IMAPOperation::isUrgent() -{ - return mUrgent; -} - -void IMAPOperation::setImapCallback(IMAPOperationCallback * callback) -{ - mImapCallback = callback; -} - -IMAPOperationCallback * IMAPOperation::imapCallback() -{ - return mImapCallback; -} - -void IMAPOperation::setError(ErrorCode error) -{ - mError = error; -} - -ErrorCode IMAPOperation::error() -{ - return mError; -} - -void IMAPOperation::start() -{ - if (session() == NULL) { - IMAPAsyncConnection * connection = mMainSession->sessionForFolder(mFolder, mUrgent); - setSession(connection); - } - mSession->runOperation(this); -} - -struct progressContext { - unsigned int current; - unsigned int maximum; -}; - -void IMAPOperation::bodyProgress(IMAPSession * session, unsigned int current, unsigned int maximum) -{ - if (isCancelled()) - return; - - struct progressContext * context = (struct progressContext *) calloc(sizeof(* context), 1); - context->current = current; - context->maximum = maximum; - retain(); - performMethodOnCallbackThread((Object::Method) &IMAPOperation::bodyProgressOnMainThread, context, true); -} - -void IMAPOperation::bodyProgressOnMainThread(void * ctx) -{ - if (isCancelled()) { - release(); - return; - } - - struct progressContext * context = (struct progressContext *) ctx; - if (mImapCallback != NULL) { - mImapCallback->bodyProgress(this, context->current, context->maximum); - } - free(context); - release(); -} - -void IMAPOperation::itemsProgress(IMAPSession * session, unsigned int current, unsigned int maximum) -{ - if (isCancelled()) - return; - - struct progressContext * context = (struct progressContext *) calloc(sizeof(* context), 1); - context->current = current; - context->maximum = maximum; - retain(); - performMethodOnCallbackThread((Object::Method) &IMAPOperation::itemsProgressOnMainThread, context, true); -} - -void IMAPOperation::itemsProgressOnMainThread(void * ctx) -{ - if (isCancelled()) { - release(); - return; - } - - struct progressContext * context = (struct progressContext *) ctx; - if (mImapCallback != NULL) { - mImapCallback->itemProgress(this, context->current, context->maximum); - } - free(context); - release(); -} - -void IMAPOperation::beforeMain() -{ -} - -void IMAPOperation::afterMain() -{ - if (mSession->session()->isAutomaticConfigurationDone()) { - mSession->owner()->automaticConfigurationDone(mSession->session()); - mSession->session()->resetAutomaticConfigurationDone(); - } -} diff --git a/src/async/imap/MCIMAPOperation.cpp b/src/async/imap/MCIMAPOperation.cpp new file mode 100644 index 00000000..9ab30ab0 --- /dev/null +++ b/src/async/imap/MCIMAPOperation.cpp @@ -0,0 +1,185 @@ +// +// MCIMAPOperation.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPOperation.h" + +#include + +#include "MCIMAPAsyncSession.h" +#include "MCIMAPSession.h" +#include "MCIMAPAsyncConnection.h" +#include "MCIMAPOperationCallback.h" + +using namespace mailcore; + +IMAPOperation::IMAPOperation() +{ + mSession = NULL; + mMainSession = NULL; + mImapCallback = NULL; + mError = ErrorNone; + mFolder = NULL; + mUrgent = false; +} + +IMAPOperation::~IMAPOperation() +{ + MC_SAFE_RELEASE(mMainSession); + MC_SAFE_RELEASE(mFolder); + MC_SAFE_RELEASE(mSession); +} + +void IMAPOperation::setSession(IMAPAsyncConnection * session) +{ + MC_SAFE_REPLACE_RETAIN(IMAPAsyncConnection, mSession, session); +#if __APPLE__ + dispatch_queue_t queue; + if (session != NULL) { + queue = session->dispatchQueue(); + } + else { + queue = dispatch_get_main_queue(); + } + setCallbackDispatchQueue(queue); +#endif +} + +IMAPAsyncConnection * IMAPOperation::session() +{ + return mSession; +} + +void IMAPOperation::setMainSession(IMAPAsyncSession * session) +{ + MC_SAFE_REPLACE_RETAIN(IMAPAsyncSession, mMainSession, session); +} + +IMAPAsyncSession * IMAPOperation::mainSession() +{ + return mMainSession; +} + +void IMAPOperation::setFolder(String * folder) +{ + MC_SAFE_REPLACE_COPY(String, mFolder, folder); +} + +String * IMAPOperation::folder() +{ + return mFolder; +} + +void IMAPOperation::setUrgent(bool urgent) +{ + mUrgent = urgent; +} + +bool IMAPOperation::isUrgent() +{ + return mUrgent; +} + +void IMAPOperation::setImapCallback(IMAPOperationCallback * callback) +{ + mImapCallback = callback; +} + +IMAPOperationCallback * IMAPOperation::imapCallback() +{ + return mImapCallback; +} + +void IMAPOperation::setError(ErrorCode error) +{ + mError = error; +} + +ErrorCode IMAPOperation::error() +{ + return mError; +} + +void IMAPOperation::start() +{ + if (session() == NULL) { + IMAPAsyncConnection * connection = mMainSession->sessionForFolder(mFolder, mUrgent); + setSession(connection); + } + mSession->runOperation(this); +} + +struct progressContext { + unsigned int current; + unsigned int maximum; +}; + +void IMAPOperation::bodyProgress(IMAPSession * session, unsigned int current, unsigned int maximum) +{ + if (isCancelled()) + return; + + struct progressContext * context = (struct progressContext *) calloc(sizeof(* context), 1); + context->current = current; + context->maximum = maximum; + retain(); + performMethodOnCallbackThread((Object::Method) &IMAPOperation::bodyProgressOnMainThread, context, true); +} + +void IMAPOperation::bodyProgressOnMainThread(void * ctx) +{ + if (isCancelled()) { + release(); + return; + } + + struct progressContext * context = (struct progressContext *) ctx; + if (mImapCallback != NULL) { + mImapCallback->bodyProgress(this, context->current, context->maximum); + } + free(context); + release(); +} + +void IMAPOperation::itemsProgress(IMAPSession * session, unsigned int current, unsigned int maximum) +{ + if (isCancelled()) + return; + + struct progressContext * context = (struct progressContext *) calloc(sizeof(* context), 1); + context->current = current; + context->maximum = maximum; + retain(); + performMethodOnCallbackThread((Object::Method) &IMAPOperation::itemsProgressOnMainThread, context, true); +} + +void IMAPOperation::itemsProgressOnMainThread(void * ctx) +{ + if (isCancelled()) { + release(); + return; + } + + struct progressContext * context = (struct progressContext *) ctx; + if (mImapCallback != NULL) { + mImapCallback->itemProgress(this, context->current, context->maximum); + } + free(context); + release(); +} + +void IMAPOperation::beforeMain() +{ +} + +void IMAPOperation::afterMain() +{ + if (mSession->session()->isAutomaticConfigurationDone()) { + mSession->owner()->automaticConfigurationDone(mSession->session()); + mSession->session()->resetAutomaticConfigurationDone(); + } +} diff --git a/src/async/imap/MCIMAPQuotaOperation.cc b/src/async/imap/MCIMAPQuotaOperation.cc deleted file mode 100644 index 2268a384..00000000 --- a/src/async/imap/MCIMAPQuotaOperation.cc +++ /dev/null @@ -1,47 +0,0 @@ -// -// MCIMAPQuotaOperation.cc -// mailcore2 -// -// Created by Petro Korenev on 8/2/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPQuotaOperation.h" - -#include "MCIMAPSession.h" -#include "MCIMAPAsyncConnection.h" - -using namespace mailcore; - -IMAPQuotaOperation::IMAPQuotaOperation() -{ - mLimit = 0; - mUsage = 0; -} - -IMAPQuotaOperation::~IMAPQuotaOperation() -{ -} - -uint32_t IMAPQuotaOperation::limit() -{ - return mLimit; -} - -uint32_t IMAPQuotaOperation::usage() -{ - return mUsage; -} - -void IMAPQuotaOperation::main() -{ - ErrorCode error; - session()->session()->loginIfNeeded(&error); - if (error != ErrorNone) { - setError(error); - return; - } - - session()->session()->getQuota(&mUsage, &mLimit, &error); - setError(error); -} diff --git a/src/async/imap/MCIMAPQuotaOperation.cpp b/src/async/imap/MCIMAPQuotaOperation.cpp new file mode 100644 index 00000000..2268a384 --- /dev/null +++ b/src/async/imap/MCIMAPQuotaOperation.cpp @@ -0,0 +1,47 @@ +// +// MCIMAPQuotaOperation.cc +// mailcore2 +// +// Created by Petro Korenev on 8/2/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPQuotaOperation.h" + +#include "MCIMAPSession.h" +#include "MCIMAPAsyncConnection.h" + +using namespace mailcore; + +IMAPQuotaOperation::IMAPQuotaOperation() +{ + mLimit = 0; + mUsage = 0; +} + +IMAPQuotaOperation::~IMAPQuotaOperation() +{ +} + +uint32_t IMAPQuotaOperation::limit() +{ + return mLimit; +} + +uint32_t IMAPQuotaOperation::usage() +{ + return mUsage; +} + +void IMAPQuotaOperation::main() +{ + ErrorCode error; + session()->session()->loginIfNeeded(&error); + if (error != ErrorNone) { + setError(error); + return; + } + + session()->session()->getQuota(&mUsage, &mLimit, &error); + setError(error); +} diff --git a/src/async/imap/MCIMAPRenameFolderOperation.cc b/src/async/imap/MCIMAPRenameFolderOperation.cc deleted file mode 100644 index 338e02a5..00000000 --- a/src/async/imap/MCIMAPRenameFolderOperation.cc +++ /dev/null @@ -1,42 +0,0 @@ -// -// MCIMAPRenameFolderOperation.cpp -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/12/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPRenameFolderOperation.h" - -#include "MCIMAPSession.h" -#include "MCIMAPAsyncConnection.h" - -using namespace mailcore; - -IMAPRenameFolderOperation::IMAPRenameFolderOperation() -{ - mOtherName = NULL; -} - -IMAPRenameFolderOperation::~IMAPRenameFolderOperation() -{ - MC_SAFE_RELEASE(mOtherName); -} - -void IMAPRenameFolderOperation::setOtherName(String * otherName) -{ - MC_SAFE_REPLACE_COPY(String, mOtherName, otherName); -} - -String * IMAPRenameFolderOperation::otherName() -{ - return mOtherName; -} - -void IMAPRenameFolderOperation::main() -{ - ErrorCode error; - session()->session()->renameFolder(folder(), mOtherName, &error); - setError(error); -} - diff --git a/src/async/imap/MCIMAPRenameFolderOperation.cpp b/src/async/imap/MCIMAPRenameFolderOperation.cpp new file mode 100644 index 00000000..338e02a5 --- /dev/null +++ b/src/async/imap/MCIMAPRenameFolderOperation.cpp @@ -0,0 +1,42 @@ +// +// MCIMAPRenameFolderOperation.cpp +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPRenameFolderOperation.h" + +#include "MCIMAPSession.h" +#include "MCIMAPAsyncConnection.h" + +using namespace mailcore; + +IMAPRenameFolderOperation::IMAPRenameFolderOperation() +{ + mOtherName = NULL; +} + +IMAPRenameFolderOperation::~IMAPRenameFolderOperation() +{ + MC_SAFE_RELEASE(mOtherName); +} + +void IMAPRenameFolderOperation::setOtherName(String * otherName) +{ + MC_SAFE_REPLACE_COPY(String, mOtherName, otherName); +} + +String * IMAPRenameFolderOperation::otherName() +{ + return mOtherName; +} + +void IMAPRenameFolderOperation::main() +{ + ErrorCode error; + session()->session()->renameFolder(folder(), mOtherName, &error); + setError(error); +} + diff --git a/src/async/imap/MCIMAPSearchOperation.cc b/src/async/imap/MCIMAPSearchOperation.cc deleted file mode 100644 index 6db73f8c..00000000 --- a/src/async/imap/MCIMAPSearchOperation.cc +++ /dev/null @@ -1,79 +0,0 @@ -// -// IMAPSearchOperation.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/12/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPSearchOperation.h" - -#include "MCIMAPSession.h" -#include "MCIMAPAsyncConnection.h" -#include "MCIMAPSearchExpression.h" - -using namespace mailcore; - -IMAPSearchOperation::IMAPSearchOperation() -{ - mKind = IMAPSearchKindNone; - mSearchString = NULL; - mExpression = NULL; - mUids = NULL; -} - -IMAPSearchOperation::~IMAPSearchOperation() -{ - MC_SAFE_RELEASE(mSearchString); - MC_SAFE_RELEASE(mExpression); - MC_SAFE_RELEASE(mUids); -} - -void IMAPSearchOperation::setSearchKind(IMAPSearchKind kind) -{ - mKind = kind; -} - -IMAPSearchKind IMAPSearchOperation::searchKind() -{ - return mKind; -} - -void IMAPSearchOperation::setSearchString(String * searchString) -{ - MC_SAFE_REPLACE_COPY(String, mSearchString, searchString); -} - -String * IMAPSearchOperation::searchString() -{ - return mSearchString; -} - -void IMAPSearchOperation::setSearchExpression(IMAPSearchExpression * expression) -{ - MC_SAFE_REPLACE_RETAIN(IMAPSearchExpression, mExpression, expression); -} - -IMAPSearchExpression * IMAPSearchOperation::searchExpression() -{ - return mExpression; -} - -IndexSet * IMAPSearchOperation::uids() -{ - return mUids; -} - -void IMAPSearchOperation::main() -{ - ErrorCode error; - if (mExpression != NULL) { - mUids = session()->session()->search(folder(), mExpression, &error); - } - else { - mUids = session()->session()->search(folder(), mKind, mSearchString, &error); - } - MC_SAFE_RETAIN(mUids); - setError(error); -} - diff --git a/src/async/imap/MCIMAPSearchOperation.cpp b/src/async/imap/MCIMAPSearchOperation.cpp new file mode 100644 index 00000000..6db73f8c --- /dev/null +++ b/src/async/imap/MCIMAPSearchOperation.cpp @@ -0,0 +1,79 @@ +// +// IMAPSearchOperation.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPSearchOperation.h" + +#include "MCIMAPSession.h" +#include "MCIMAPAsyncConnection.h" +#include "MCIMAPSearchExpression.h" + +using namespace mailcore; + +IMAPSearchOperation::IMAPSearchOperation() +{ + mKind = IMAPSearchKindNone; + mSearchString = NULL; + mExpression = NULL; + mUids = NULL; +} + +IMAPSearchOperation::~IMAPSearchOperation() +{ + MC_SAFE_RELEASE(mSearchString); + MC_SAFE_RELEASE(mExpression); + MC_SAFE_RELEASE(mUids); +} + +void IMAPSearchOperation::setSearchKind(IMAPSearchKind kind) +{ + mKind = kind; +} + +IMAPSearchKind IMAPSearchOperation::searchKind() +{ + return mKind; +} + +void IMAPSearchOperation::setSearchString(String * searchString) +{ + MC_SAFE_REPLACE_COPY(String, mSearchString, searchString); +} + +String * IMAPSearchOperation::searchString() +{ + return mSearchString; +} + +void IMAPSearchOperation::setSearchExpression(IMAPSearchExpression * expression) +{ + MC_SAFE_REPLACE_RETAIN(IMAPSearchExpression, mExpression, expression); +} + +IMAPSearchExpression * IMAPSearchOperation::searchExpression() +{ + return mExpression; +} + +IndexSet * IMAPSearchOperation::uids() +{ + return mUids; +} + +void IMAPSearchOperation::main() +{ + ErrorCode error; + if (mExpression != NULL) { + mUids = session()->session()->search(folder(), mExpression, &error); + } + else { + mUids = session()->session()->search(folder(), mKind, mSearchString, &error); + } + MC_SAFE_RETAIN(mUids); + setError(error); +} + diff --git a/src/async/imap/MCIMAPStoreFlagsOperation.cc b/src/async/imap/MCIMAPStoreFlagsOperation.cc deleted file mode 100644 index a049333e..00000000 --- a/src/async/imap/MCIMAPStoreFlagsOperation.cc +++ /dev/null @@ -1,92 +0,0 @@ -// -// MCIMAPStoreFlagsOperation.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/12/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPStoreFlagsOperation.h" - -#include "MCIMAPSession.h" -#include "MCIMAPAsyncConnection.h" - -using namespace mailcore; - -IMAPStoreFlagsOperation::IMAPStoreFlagsOperation() -{ - mUids = NULL; - mNumbers = NULL; - mKind = IMAPStoreFlagsRequestKindAdd; - mFlags = MessageFlagNone; - mCustomFlags = NULL; -} - -IMAPStoreFlagsOperation::~IMAPStoreFlagsOperation() -{ - MC_SAFE_RELEASE(mNumbers); - MC_SAFE_RELEASE(mUids); - MC_SAFE_RELEASE(mCustomFlags); -} - -void IMAPStoreFlagsOperation::setUids(IndexSet * uids) -{ - MC_SAFE_REPLACE_RETAIN(IndexSet, mUids, uids); -} - -IndexSet * IMAPStoreFlagsOperation::uids() -{ - return mUids; -} - -void IMAPStoreFlagsOperation::setNumbers(IndexSet * numbers) -{ - MC_SAFE_REPLACE_RETAIN(IndexSet, mNumbers, numbers); -} - -IndexSet * IMAPStoreFlagsOperation::numbers() -{ - return mNumbers; -} - -void IMAPStoreFlagsOperation::setKind(IMAPStoreFlagsRequestKind kind) -{ - mKind = kind; -} - -IMAPStoreFlagsRequestKind IMAPStoreFlagsOperation::kind() -{ - return mKind; -} - -void IMAPStoreFlagsOperation::setFlags(MessageFlag flags) -{ - mFlags = flags; -} - -MessageFlag IMAPStoreFlagsOperation::flags() -{ - return mFlags; -} - -void IMAPStoreFlagsOperation::setCustomFlags(Array * customFlags) -{ - MC_SAFE_REPLACE_RETAIN(Array, mCustomFlags, customFlags); -} - -Array * IMAPStoreFlagsOperation::customFlags() -{ - return mCustomFlags; -} - -void IMAPStoreFlagsOperation::main() -{ - ErrorCode error; - if (mUids != NULL) { - session()->session()->storeFlagsAndCustomFlagsByUID(folder(), mUids, mKind, mFlags, mCustomFlags, &error); - } - else { - session()->session()->storeFlagsAndCustomFlagsByNumber(folder(), mNumbers, mKind, mFlags, mCustomFlags, &error); - } - setError(error); -} diff --git a/src/async/imap/MCIMAPStoreFlagsOperation.cpp b/src/async/imap/MCIMAPStoreFlagsOperation.cpp new file mode 100644 index 00000000..a049333e --- /dev/null +++ b/src/async/imap/MCIMAPStoreFlagsOperation.cpp @@ -0,0 +1,92 @@ +// +// MCIMAPStoreFlagsOperation.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPStoreFlagsOperation.h" + +#include "MCIMAPSession.h" +#include "MCIMAPAsyncConnection.h" + +using namespace mailcore; + +IMAPStoreFlagsOperation::IMAPStoreFlagsOperation() +{ + mUids = NULL; + mNumbers = NULL; + mKind = IMAPStoreFlagsRequestKindAdd; + mFlags = MessageFlagNone; + mCustomFlags = NULL; +} + +IMAPStoreFlagsOperation::~IMAPStoreFlagsOperation() +{ + MC_SAFE_RELEASE(mNumbers); + MC_SAFE_RELEASE(mUids); + MC_SAFE_RELEASE(mCustomFlags); +} + +void IMAPStoreFlagsOperation::setUids(IndexSet * uids) +{ + MC_SAFE_REPLACE_RETAIN(IndexSet, mUids, uids); +} + +IndexSet * IMAPStoreFlagsOperation::uids() +{ + return mUids; +} + +void IMAPStoreFlagsOperation::setNumbers(IndexSet * numbers) +{ + MC_SAFE_REPLACE_RETAIN(IndexSet, mNumbers, numbers); +} + +IndexSet * IMAPStoreFlagsOperation::numbers() +{ + return mNumbers; +} + +void IMAPStoreFlagsOperation::setKind(IMAPStoreFlagsRequestKind kind) +{ + mKind = kind; +} + +IMAPStoreFlagsRequestKind IMAPStoreFlagsOperation::kind() +{ + return mKind; +} + +void IMAPStoreFlagsOperation::setFlags(MessageFlag flags) +{ + mFlags = flags; +} + +MessageFlag IMAPStoreFlagsOperation::flags() +{ + return mFlags; +} + +void IMAPStoreFlagsOperation::setCustomFlags(Array * customFlags) +{ + MC_SAFE_REPLACE_RETAIN(Array, mCustomFlags, customFlags); +} + +Array * IMAPStoreFlagsOperation::customFlags() +{ + return mCustomFlags; +} + +void IMAPStoreFlagsOperation::main() +{ + ErrorCode error; + if (mUids != NULL) { + session()->session()->storeFlagsAndCustomFlagsByUID(folder(), mUids, mKind, mFlags, mCustomFlags, &error); + } + else { + session()->session()->storeFlagsAndCustomFlagsByNumber(folder(), mNumbers, mKind, mFlags, mCustomFlags, &error); + } + setError(error); +} diff --git a/src/async/imap/MCIMAPStoreLabelsOperation.cc b/src/async/imap/MCIMAPStoreLabelsOperation.cc deleted file mode 100644 index 3ad2212a..00000000 --- a/src/async/imap/MCIMAPStoreLabelsOperation.cc +++ /dev/null @@ -1,82 +0,0 @@ -// -// MCIMAPStoreLabelsOperation.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/12/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPStoreLabelsOperation.h" - -#include "MCIMAPSession.h" -#include "MCIMAPAsyncConnection.h" - -using namespace mailcore; - -IMAPStoreLabelsOperation::IMAPStoreLabelsOperation() -{ - mUids = NULL; - mNumbers = NULL; - mKind = IMAPStoreFlagsRequestKindAdd; - mLabels = NULL; -} - -IMAPStoreLabelsOperation::~IMAPStoreLabelsOperation() -{ - MC_SAFE_RELEASE(mNumbers); - MC_SAFE_RELEASE(mUids); - MC_SAFE_RELEASE(mLabels); -} - -void IMAPStoreLabelsOperation::setUids(IndexSet * uids) -{ - MC_SAFE_REPLACE_RETAIN(IndexSet, mUids, uids); -} - -IndexSet * IMAPStoreLabelsOperation::uids() -{ - return mUids; -} - -void IMAPStoreLabelsOperation::setNumbers(IndexSet * numbers) -{ - MC_SAFE_REPLACE_RETAIN(IndexSet, mNumbers, numbers); -} - -IndexSet * IMAPStoreLabelsOperation::numbers() -{ - return mNumbers; -} - -void IMAPStoreLabelsOperation::setKind(IMAPStoreFlagsRequestKind kind) -{ - mKind = kind; -} - -IMAPStoreFlagsRequestKind IMAPStoreLabelsOperation::kind() -{ - return mKind; -} - -void IMAPStoreLabelsOperation::setLabels(Array * labels) -{ - MC_SAFE_REPLACE_RETAIN(Array, mLabels, labels); -} - -Array * IMAPStoreLabelsOperation::labels() -{ - return mLabels; -} - -void IMAPStoreLabelsOperation::main() -{ - ErrorCode error; - if (mUids != NULL) { - session()->session()->storeLabelsByUID(folder(), mUids, mKind, mLabels, &error); - } - else { - session()->session()->storeLabelsByNumber(folder(), mUids, mKind, mLabels, &error); - } - setError(error); -} - diff --git a/src/async/imap/MCIMAPStoreLabelsOperation.cpp b/src/async/imap/MCIMAPStoreLabelsOperation.cpp new file mode 100644 index 00000000..3ad2212a --- /dev/null +++ b/src/async/imap/MCIMAPStoreLabelsOperation.cpp @@ -0,0 +1,82 @@ +// +// MCIMAPStoreLabelsOperation.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPStoreLabelsOperation.h" + +#include "MCIMAPSession.h" +#include "MCIMAPAsyncConnection.h" + +using namespace mailcore; + +IMAPStoreLabelsOperation::IMAPStoreLabelsOperation() +{ + mUids = NULL; + mNumbers = NULL; + mKind = IMAPStoreFlagsRequestKindAdd; + mLabels = NULL; +} + +IMAPStoreLabelsOperation::~IMAPStoreLabelsOperation() +{ + MC_SAFE_RELEASE(mNumbers); + MC_SAFE_RELEASE(mUids); + MC_SAFE_RELEASE(mLabels); +} + +void IMAPStoreLabelsOperation::setUids(IndexSet * uids) +{ + MC_SAFE_REPLACE_RETAIN(IndexSet, mUids, uids); +} + +IndexSet * IMAPStoreLabelsOperation::uids() +{ + return mUids; +} + +void IMAPStoreLabelsOperation::setNumbers(IndexSet * numbers) +{ + MC_SAFE_REPLACE_RETAIN(IndexSet, mNumbers, numbers); +} + +IndexSet * IMAPStoreLabelsOperation::numbers() +{ + return mNumbers; +} + +void IMAPStoreLabelsOperation::setKind(IMAPStoreFlagsRequestKind kind) +{ + mKind = kind; +} + +IMAPStoreFlagsRequestKind IMAPStoreLabelsOperation::kind() +{ + return mKind; +} + +void IMAPStoreLabelsOperation::setLabels(Array * labels) +{ + MC_SAFE_REPLACE_RETAIN(Array, mLabels, labels); +} + +Array * IMAPStoreLabelsOperation::labels() +{ + return mLabels; +} + +void IMAPStoreLabelsOperation::main() +{ + ErrorCode error; + if (mUids != NULL) { + session()->session()->storeLabelsByUID(folder(), mUids, mKind, mLabels, &error); + } + else { + session()->session()->storeLabelsByNumber(folder(), mUids, mKind, mLabels, &error); + } + setError(error); +} + diff --git a/src/async/imap/MCIMAPSubscribeFolderOperation.cc b/src/async/imap/MCIMAPSubscribeFolderOperation.cc deleted file mode 100644 index 1eedad29..00000000 --- a/src/async/imap/MCIMAPSubscribeFolderOperation.cc +++ /dev/null @@ -1,45 +0,0 @@ -// -// MCIMAPSubscribeFolderOperation.cpp -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/12/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPSubscribeFolderOperation.h" - -#include "MCIMAPSession.h" -#include "MCIMAPAsyncConnection.h" - -using namespace mailcore; - -IMAPSubscribeFolderOperation::IMAPSubscribeFolderOperation() -{ - mUnsubscribeEnabled = false; -} - -IMAPSubscribeFolderOperation::~IMAPSubscribeFolderOperation() -{ -} - -void IMAPSubscribeFolderOperation::setUnsubscribeEnabled(bool enabled) -{ - mUnsubscribeEnabled = enabled; -} - -bool IMAPSubscribeFolderOperation::isUnsubscribeEnabled() -{ - return mUnsubscribeEnabled; -} - -void IMAPSubscribeFolderOperation::main() -{ - ErrorCode error; - if (mUnsubscribeEnabled) { - session()->session()->unsubscribeFolder(folder(), &error); - } - else { - session()->session()->subscribeFolder(folder(), &error); - } - setError(error); -} diff --git a/src/async/imap/MCIMAPSubscribeFolderOperation.cpp b/src/async/imap/MCIMAPSubscribeFolderOperation.cpp new file mode 100644 index 00000000..1eedad29 --- /dev/null +++ b/src/async/imap/MCIMAPSubscribeFolderOperation.cpp @@ -0,0 +1,45 @@ +// +// MCIMAPSubscribeFolderOperation.cpp +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPSubscribeFolderOperation.h" + +#include "MCIMAPSession.h" +#include "MCIMAPAsyncConnection.h" + +using namespace mailcore; + +IMAPSubscribeFolderOperation::IMAPSubscribeFolderOperation() +{ + mUnsubscribeEnabled = false; +} + +IMAPSubscribeFolderOperation::~IMAPSubscribeFolderOperation() +{ +} + +void IMAPSubscribeFolderOperation::setUnsubscribeEnabled(bool enabled) +{ + mUnsubscribeEnabled = enabled; +} + +bool IMAPSubscribeFolderOperation::isUnsubscribeEnabled() +{ + return mUnsubscribeEnabled; +} + +void IMAPSubscribeFolderOperation::main() +{ + ErrorCode error; + if (mUnsubscribeEnabled) { + session()->session()->unsubscribeFolder(folder(), &error); + } + else { + session()->session()->subscribeFolder(folder(), &error); + } + setError(error); +} diff --git a/src/async/nntp/MCNNTPAsyncSession.cc b/src/async/nntp/MCNNTPAsyncSession.cc deleted file mode 100644 index a78a70b4..00000000 --- a/src/async/nntp/MCNNTPAsyncSession.cc +++ /dev/null @@ -1,302 +0,0 @@ -// -// MCNNTPAsyncSession.cpp -// mailcore2 -// -// Created by Robert Widmann on 8/13/14. -// Copyright (c) 2014 MailCore. All rights reserved. -// - -#include "MCNNTPAsyncSession.h" - -#include "MCNNTP.h" -#include "MCNNTPFetchHeaderOperation.h" -#include "MCNNTPFetchArticleOperation.h" -#include "MCNNTPFetchAllArticlesOperation.h" -#include "MCNNTPListNewsgroupsOperation.h" -#include "MCNNTPFetchOverviewOperation.h" -#include "MCNNTPCheckAccountOperation.h" -#include "MCNNTPFetchServerTimeOperation.h" -#include "MCNNTPDisconnectOperation.h" -#include "MCOperationQueueCallback.h" -#include "MCConnectionLogger.h" - -using namespace mailcore; - -namespace mailcore { - class NNTPOperationQueueCallback : public Object, public OperationQueueCallback { - public: - NNTPOperationQueueCallback(NNTPAsyncSession * session) { - mSession = session; - } - - virtual ~NNTPOperationQueueCallback() { - } - - virtual void queueStartRunning() { - mSession->retain(); - } - - virtual void queueStoppedRunning() { - mSession->release(); - } - - private: - NNTPAsyncSession * mSession; - }; - - class NNTPConnectionLogger : public Object, public ConnectionLogger { - public: - NNTPConnectionLogger(NNTPAsyncSession * session) { - mSession = session; - } - - virtual ~NNTPConnectionLogger() { - } - - virtual void log(void * sender, ConnectionLogType logType, Data * buffer) - { - mSession->logConnection(logType, buffer); - } - - private: - NNTPAsyncSession * mSession; - }; - -} - -NNTPAsyncSession::NNTPAsyncSession() -{ - mSession = new NNTPSession(); - mQueue = new OperationQueue(); - mQueueCallback = new NNTPOperationQueueCallback(this); - mQueue->setCallback(mQueueCallback); - mConnectionLogger = NULL; - pthread_mutex_init(&mConnectionLoggerLock, NULL); - mInternalLogger = new NNTPConnectionLogger(this); - mSession->setConnectionLogger(mInternalLogger); -} - -NNTPAsyncSession::~NNTPAsyncSession() -{ - MC_SAFE_RELEASE(mInternalLogger); - pthread_mutex_destroy(&mConnectionLoggerLock); - MC_SAFE_RELEASE(mQueueCallback); - MC_SAFE_RELEASE(mSession); - MC_SAFE_RELEASE(mQueue); -} - -void NNTPAsyncSession::setHostname(String * hostname) -{ - mSession->setHostname(hostname); -} - -String * NNTPAsyncSession::hostname() -{ - return mSession->hostname(); -} - -void NNTPAsyncSession::setPort(unsigned int port) -{ - mSession->setPort(port); -} - -unsigned int NNTPAsyncSession::port() -{ - return mSession->port(); -} - -void NNTPAsyncSession::setUsername(String * username) -{ - mSession->setUsername(username); -} - -String * NNTPAsyncSession::username() -{ - return mSession->username(); -} - -void NNTPAsyncSession::setPassword(String * password) -{ - mSession->setPassword(password); -} - -String * NNTPAsyncSession::password() -{ - return mSession->password(); -} - -void NNTPAsyncSession::setConnectionType(ConnectionType connectionType) -{ - mSession->setConnectionType(connectionType); -} - -ConnectionType NNTPAsyncSession::connectionType() -{ - return mSession->connectionType(); -} - -void NNTPAsyncSession::setTimeout(time_t timeout) -{ - mSession->setTimeout(timeout); -} - -time_t NNTPAsyncSession::timeout() -{ - return mSession->timeout(); -} - -void NNTPAsyncSession::setCheckCertificateEnabled(bool enabled) -{ - mSession->setCheckCertificateEnabled(enabled); -} - -bool NNTPAsyncSession::isCheckCertificateEnabled() -{ - return mSession->isCheckCertificateEnabled(); -} - -NNTPFetchAllArticlesOperation * NNTPAsyncSession::fetchAllArticlesOperation(String * group) -{ - NNTPFetchAllArticlesOperation * op = new NNTPFetchAllArticlesOperation(); - op->setSession(this); - op->setGroupName(group); - op->autorelease(); - return op; -} - -NNTPFetchHeaderOperation * NNTPAsyncSession::fetchHeaderOperation(String * groupName, unsigned int index) -{ - NNTPFetchHeaderOperation * op = new NNTPFetchHeaderOperation(); - op->setSession(this); - op->setGroupName(groupName); - op->setMessageIndex(index); - op->autorelease(); - return op; -} - -NNTPFetchArticleOperation * NNTPAsyncSession::fetchArticleOperation(String * groupName, unsigned int index) -{ - NNTPFetchArticleOperation * op = new NNTPFetchArticleOperation(); - op->setSession(this); - op->setGroupName(groupName); - op->setMessageIndex(index); - op->autorelease(); - return op; -} - -NNTPFetchArticleOperation * NNTPAsyncSession::fetchArticleByMessageIDOperation(String *groupName, String *messageID) -{ - NNTPFetchArticleOperation * op = new NNTPFetchArticleOperation(); - op->setSession(this); - op->setGroupName(groupName); - op->setMessageID(messageID); - op->autorelease(); - return op; -} - -NNTPFetchOverviewOperation * NNTPAsyncSession::fetchOverviewOperationWithIndexes(String * groupName, IndexSet * indexes) -{ - NNTPFetchOverviewOperation * op = new NNTPFetchOverviewOperation(); - op->setSession(this); - op->setGroupName(groupName); - op->setIndexes(indexes); - op->autorelease(); - return op; -} - -NNTPFetchServerTimeOperation * NNTPAsyncSession::fetchServerDateOperation() -{ - NNTPFetchServerTimeOperation * op = new NNTPFetchServerTimeOperation(); - op->setSession(this); - op->autorelease(); - return op; -} - -NNTPListNewsgroupsOperation * NNTPAsyncSession::listAllNewsgroupsOperation() -{ - NNTPListNewsgroupsOperation * op = new NNTPListNewsgroupsOperation(); - op->setSession(this); - op->setListsSubscribed(false); - op->autorelease(); - return op; -} - -NNTPListNewsgroupsOperation * NNTPAsyncSession::listDefaultNewsgroupsOperation() -{ - NNTPListNewsgroupsOperation * op = new NNTPListNewsgroupsOperation(); - op->setSession(this); - op->setListsSubscribed(true); - op->autorelease(); - return op; -} - -NNTPOperation * NNTPAsyncSession::disconnectOperation() -{ - NNTPDisconnectOperation * op = new NNTPDisconnectOperation(); - op->setSession(this); - op->autorelease(); - return op; -} - -NNTPOperation * NNTPAsyncSession::checkAccountOperation() -{ - NNTPCheckAccountOperation * op = new NNTPCheckAccountOperation(); - op->setSession(this); - op->autorelease(); - return op; -} - -NNTPSession * NNTPAsyncSession::session() -{ - return mSession; -} - -void NNTPAsyncSession::runOperation(NNTPOperation * operation) -{ - mQueue->addOperation(operation); -} - -void NNTPAsyncSession::setConnectionLogger(ConnectionLogger * logger) -{ - pthread_mutex_lock(&mConnectionLoggerLock); - mConnectionLogger = logger; - if (mConnectionLogger != NULL) { - mSession->setConnectionLogger(mInternalLogger); - } - else { - mSession->setConnectionLogger(NULL); - } - pthread_mutex_unlock(&mConnectionLoggerLock); -} - -ConnectionLogger * NNTPAsyncSession::connectionLogger() -{ - ConnectionLogger * result; - - pthread_mutex_lock(&mConnectionLoggerLock); - result = mConnectionLogger; - pthread_mutex_unlock(&mConnectionLoggerLock); - - return result; -} - -void NNTPAsyncSession::logConnection(ConnectionLogType logType, Data * buffer) -{ - pthread_mutex_lock(&mConnectionLoggerLock); - if (mConnectionLogger != NULL) { - mConnectionLogger->log(this, logType, buffer); - } - pthread_mutex_unlock(&mConnectionLoggerLock); -} - -#if __APPLE__ -void NNTPAsyncSession::setDispatchQueue(dispatch_queue_t dispatchQueue) -{ - mQueue->setDispatchQueue(dispatchQueue); -} - -dispatch_queue_t NNTPAsyncSession::dispatchQueue() -{ - return mQueue->dispatchQueue(); -} -#endif diff --git a/src/async/nntp/MCNNTPAsyncSession.cpp b/src/async/nntp/MCNNTPAsyncSession.cpp new file mode 100644 index 00000000..a78a70b4 --- /dev/null +++ b/src/async/nntp/MCNNTPAsyncSession.cpp @@ -0,0 +1,302 @@ +// +// MCNNTPAsyncSession.cpp +// mailcore2 +// +// Created by Robert Widmann on 8/13/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#include "MCNNTPAsyncSession.h" + +#include "MCNNTP.h" +#include "MCNNTPFetchHeaderOperation.h" +#include "MCNNTPFetchArticleOperation.h" +#include "MCNNTPFetchAllArticlesOperation.h" +#include "MCNNTPListNewsgroupsOperation.h" +#include "MCNNTPFetchOverviewOperation.h" +#include "MCNNTPCheckAccountOperation.h" +#include "MCNNTPFetchServerTimeOperation.h" +#include "MCNNTPDisconnectOperation.h" +#include "MCOperationQueueCallback.h" +#include "MCConnectionLogger.h" + +using namespace mailcore; + +namespace mailcore { + class NNTPOperationQueueCallback : public Object, public OperationQueueCallback { + public: + NNTPOperationQueueCallback(NNTPAsyncSession * session) { + mSession = session; + } + + virtual ~NNTPOperationQueueCallback() { + } + + virtual void queueStartRunning() { + mSession->retain(); + } + + virtual void queueStoppedRunning() { + mSession->release(); + } + + private: + NNTPAsyncSession * mSession; + }; + + class NNTPConnectionLogger : public Object, public ConnectionLogger { + public: + NNTPConnectionLogger(NNTPAsyncSession * session) { + mSession = session; + } + + virtual ~NNTPConnectionLogger() { + } + + virtual void log(void * sender, ConnectionLogType logType, Data * buffer) + { + mSession->logConnection(logType, buffer); + } + + private: + NNTPAsyncSession * mSession; + }; + +} + +NNTPAsyncSession::NNTPAsyncSession() +{ + mSession = new NNTPSession(); + mQueue = new OperationQueue(); + mQueueCallback = new NNTPOperationQueueCallback(this); + mQueue->setCallback(mQueueCallback); + mConnectionLogger = NULL; + pthread_mutex_init(&mConnectionLoggerLock, NULL); + mInternalLogger = new NNTPConnectionLogger(this); + mSession->setConnectionLogger(mInternalLogger); +} + +NNTPAsyncSession::~NNTPAsyncSession() +{ + MC_SAFE_RELEASE(mInternalLogger); + pthread_mutex_destroy(&mConnectionLoggerLock); + MC_SAFE_RELEASE(mQueueCallback); + MC_SAFE_RELEASE(mSession); + MC_SAFE_RELEASE(mQueue); +} + +void NNTPAsyncSession::setHostname(String * hostname) +{ + mSession->setHostname(hostname); +} + +String * NNTPAsyncSession::hostname() +{ + return mSession->hostname(); +} + +void NNTPAsyncSession::setPort(unsigned int port) +{ + mSession->setPort(port); +} + +unsigned int NNTPAsyncSession::port() +{ + return mSession->port(); +} + +void NNTPAsyncSession::setUsername(String * username) +{ + mSession->setUsername(username); +} + +String * NNTPAsyncSession::username() +{ + return mSession->username(); +} + +void NNTPAsyncSession::setPassword(String * password) +{ + mSession->setPassword(password); +} + +String * NNTPAsyncSession::password() +{ + return mSession->password(); +} + +void NNTPAsyncSession::setConnectionType(ConnectionType connectionType) +{ + mSession->setConnectionType(connectionType); +} + +ConnectionType NNTPAsyncSession::connectionType() +{ + return mSession->connectionType(); +} + +void NNTPAsyncSession::setTimeout(time_t timeout) +{ + mSession->setTimeout(timeout); +} + +time_t NNTPAsyncSession::timeout() +{ + return mSession->timeout(); +} + +void NNTPAsyncSession::setCheckCertificateEnabled(bool enabled) +{ + mSession->setCheckCertificateEnabled(enabled); +} + +bool NNTPAsyncSession::isCheckCertificateEnabled() +{ + return mSession->isCheckCertificateEnabled(); +} + +NNTPFetchAllArticlesOperation * NNTPAsyncSession::fetchAllArticlesOperation(String * group) +{ + NNTPFetchAllArticlesOperation * op = new NNTPFetchAllArticlesOperation(); + op->setSession(this); + op->setGroupName(group); + op->autorelease(); + return op; +} + +NNTPFetchHeaderOperation * NNTPAsyncSession::fetchHeaderOperation(String * groupName, unsigned int index) +{ + NNTPFetchHeaderOperation * op = new NNTPFetchHeaderOperation(); + op->setSession(this); + op->setGroupName(groupName); + op->setMessageIndex(index); + op->autorelease(); + return op; +} + +NNTPFetchArticleOperation * NNTPAsyncSession::fetchArticleOperation(String * groupName, unsigned int index) +{ + NNTPFetchArticleOperation * op = new NNTPFetchArticleOperation(); + op->setSession(this); + op->setGroupName(groupName); + op->setMessageIndex(index); + op->autorelease(); + return op; +} + +NNTPFetchArticleOperation * NNTPAsyncSession::fetchArticleByMessageIDOperation(String *groupName, String *messageID) +{ + NNTPFetchArticleOperation * op = new NNTPFetchArticleOperation(); + op->setSession(this); + op->setGroupName(groupName); + op->setMessageID(messageID); + op->autorelease(); + return op; +} + +NNTPFetchOverviewOperation * NNTPAsyncSession::fetchOverviewOperationWithIndexes(String * groupName, IndexSet * indexes) +{ + NNTPFetchOverviewOperation * op = new NNTPFetchOverviewOperation(); + op->setSession(this); + op->setGroupName(groupName); + op->setIndexes(indexes); + op->autorelease(); + return op; +} + +NNTPFetchServerTimeOperation * NNTPAsyncSession::fetchServerDateOperation() +{ + NNTPFetchServerTimeOperation * op = new NNTPFetchServerTimeOperation(); + op->setSession(this); + op->autorelease(); + return op; +} + +NNTPListNewsgroupsOperation * NNTPAsyncSession::listAllNewsgroupsOperation() +{ + NNTPListNewsgroupsOperation * op = new NNTPListNewsgroupsOperation(); + op->setSession(this); + op->setListsSubscribed(false); + op->autorelease(); + return op; +} + +NNTPListNewsgroupsOperation * NNTPAsyncSession::listDefaultNewsgroupsOperation() +{ + NNTPListNewsgroupsOperation * op = new NNTPListNewsgroupsOperation(); + op->setSession(this); + op->setListsSubscribed(true); + op->autorelease(); + return op; +} + +NNTPOperation * NNTPAsyncSession::disconnectOperation() +{ + NNTPDisconnectOperation * op = new NNTPDisconnectOperation(); + op->setSession(this); + op->autorelease(); + return op; +} + +NNTPOperation * NNTPAsyncSession::checkAccountOperation() +{ + NNTPCheckAccountOperation * op = new NNTPCheckAccountOperation(); + op->setSession(this); + op->autorelease(); + return op; +} + +NNTPSession * NNTPAsyncSession::session() +{ + return mSession; +} + +void NNTPAsyncSession::runOperation(NNTPOperation * operation) +{ + mQueue->addOperation(operation); +} + +void NNTPAsyncSession::setConnectionLogger(ConnectionLogger * logger) +{ + pthread_mutex_lock(&mConnectionLoggerLock); + mConnectionLogger = logger; + if (mConnectionLogger != NULL) { + mSession->setConnectionLogger(mInternalLogger); + } + else { + mSession->setConnectionLogger(NULL); + } + pthread_mutex_unlock(&mConnectionLoggerLock); +} + +ConnectionLogger * NNTPAsyncSession::connectionLogger() +{ + ConnectionLogger * result; + + pthread_mutex_lock(&mConnectionLoggerLock); + result = mConnectionLogger; + pthread_mutex_unlock(&mConnectionLoggerLock); + + return result; +} + +void NNTPAsyncSession::logConnection(ConnectionLogType logType, Data * buffer) +{ + pthread_mutex_lock(&mConnectionLoggerLock); + if (mConnectionLogger != NULL) { + mConnectionLogger->log(this, logType, buffer); + } + pthread_mutex_unlock(&mConnectionLoggerLock); +} + +#if __APPLE__ +void NNTPAsyncSession::setDispatchQueue(dispatch_queue_t dispatchQueue) +{ + mQueue->setDispatchQueue(dispatchQueue); +} + +dispatch_queue_t NNTPAsyncSession::dispatchQueue() +{ + return mQueue->dispatchQueue(); +} +#endif diff --git a/src/async/nntp/MCNNTPCheckAccountOperation.cc b/src/async/nntp/MCNNTPCheckAccountOperation.cc deleted file mode 100644 index 29b050f0..00000000 --- a/src/async/nntp/MCNNTPCheckAccountOperation.cc +++ /dev/null @@ -1,30 +0,0 @@ -// -// MCNNTPCheckAccountOperation.cpp -// mailcore2 -// -// Created by Robert Widmann on 8/13/14. -// Copyright (c) 2014 MailCore. All rights reserved. -// - -#include "MCNNTPCheckAccountOperation.h" - -#include "MCNNTPAsyncSession.h" -#include "MCNNTPSession.h" - -using namespace mailcore; - -NNTPCheckAccountOperation::NNTPCheckAccountOperation() -{ -} - -NNTPCheckAccountOperation::~NNTPCheckAccountOperation() -{ -} - -void NNTPCheckAccountOperation::main() -{ - ErrorCode error; - - session()->session()->checkAccount(&error); - setError(error); -} diff --git a/src/async/nntp/MCNNTPCheckAccountOperation.cpp b/src/async/nntp/MCNNTPCheckAccountOperation.cpp new file mode 100644 index 00000000..29b050f0 --- /dev/null +++ b/src/async/nntp/MCNNTPCheckAccountOperation.cpp @@ -0,0 +1,30 @@ +// +// MCNNTPCheckAccountOperation.cpp +// mailcore2 +// +// Created by Robert Widmann on 8/13/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#include "MCNNTPCheckAccountOperation.h" + +#include "MCNNTPAsyncSession.h" +#include "MCNNTPSession.h" + +using namespace mailcore; + +NNTPCheckAccountOperation::NNTPCheckAccountOperation() +{ +} + +NNTPCheckAccountOperation::~NNTPCheckAccountOperation() +{ +} + +void NNTPCheckAccountOperation::main() +{ + ErrorCode error; + + session()->session()->checkAccount(&error); + setError(error); +} diff --git a/src/async/nntp/MCNNTPDisconnectOperation.cc b/src/async/nntp/MCNNTPDisconnectOperation.cc deleted file mode 100644 index d269904a..00000000 --- a/src/async/nntp/MCNNTPDisconnectOperation.cc +++ /dev/null @@ -1,30 +0,0 @@ -// -// MCNNTPDisconnectOperation.cpp -// mailcore2 -// -// Created by Robert Widmann on 8/13/14. -// Copyright (c) 2014 MailCore. All rights reserved. -// - -#include "MCNNTPDisconnectOperation.h" - -#include "MCNNTPAsyncSession.h" -#include "MCNNTPSession.h" - -using namespace mailcore; - -NNTPDisconnectOperation::NNTPDisconnectOperation() -{ -} - -NNTPDisconnectOperation::~NNTPDisconnectOperation() -{ -} - -void NNTPDisconnectOperation::main() -{ - ErrorCode error; - - session()->session()->checkAccount(&error); - setError(error); -} diff --git a/src/async/nntp/MCNNTPDisconnectOperation.cpp b/src/async/nntp/MCNNTPDisconnectOperation.cpp new file mode 100644 index 00000000..d269904a --- /dev/null +++ b/src/async/nntp/MCNNTPDisconnectOperation.cpp @@ -0,0 +1,30 @@ +// +// MCNNTPDisconnectOperation.cpp +// mailcore2 +// +// Created by Robert Widmann on 8/13/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#include "MCNNTPDisconnectOperation.h" + +#include "MCNNTPAsyncSession.h" +#include "MCNNTPSession.h" + +using namespace mailcore; + +NNTPDisconnectOperation::NNTPDisconnectOperation() +{ +} + +NNTPDisconnectOperation::~NNTPDisconnectOperation() +{ +} + +void NNTPDisconnectOperation::main() +{ + ErrorCode error; + + session()->session()->checkAccount(&error); + setError(error); +} diff --git a/src/async/nntp/MCNNTPFetchAllArticlesOperation.cc b/src/async/nntp/MCNNTPFetchAllArticlesOperation.cc deleted file mode 100644 index 044e9e5e..00000000 --- a/src/async/nntp/MCNNTPFetchAllArticlesOperation.cc +++ /dev/null @@ -1,49 +0,0 @@ -// -// MCNNTPFetchAllArticlesOperation.cpp -// mailcore2 -// -// Created by Robert Widmann on 8/13/14. -// Copyright (c) 2014 MailCore. All rights reserved. -// - -#include "MCNNTPFetchAllArticlesOperation.h" - -#include "MCNNTPAsyncSession.h" -#include "MCNNTPSession.h" - -using namespace mailcore; - -NNTPFetchAllArticlesOperation::NNTPFetchAllArticlesOperation() -{ - mGroupName = NULL; - mArticles = NULL; -} - -NNTPFetchAllArticlesOperation::~NNTPFetchAllArticlesOperation() -{ - MC_SAFE_RELEASE(mGroupName); - MC_SAFE_RELEASE(mArticles); -} - -void NNTPFetchAllArticlesOperation::setGroupName(String * groupname) -{ - MC_SAFE_REPLACE_COPY(String, mGroupName, groupname); -} - -String * NNTPFetchAllArticlesOperation::groupName() -{ - return mGroupName; -} - -IndexSet * NNTPFetchAllArticlesOperation::articles() -{ - return mArticles; -} - -void NNTPFetchAllArticlesOperation::main() -{ - ErrorCode error; - mArticles = session()->session()->fetchAllArticles(mGroupName, &error); - setError(error); - MC_SAFE_RETAIN(mArticles); -} diff --git a/src/async/nntp/MCNNTPFetchAllArticlesOperation.cpp b/src/async/nntp/MCNNTPFetchAllArticlesOperation.cpp new file mode 100644 index 00000000..044e9e5e --- /dev/null +++ b/src/async/nntp/MCNNTPFetchAllArticlesOperation.cpp @@ -0,0 +1,49 @@ +// +// MCNNTPFetchAllArticlesOperation.cpp +// mailcore2 +// +// Created by Robert Widmann on 8/13/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#include "MCNNTPFetchAllArticlesOperation.h" + +#include "MCNNTPAsyncSession.h" +#include "MCNNTPSession.h" + +using namespace mailcore; + +NNTPFetchAllArticlesOperation::NNTPFetchAllArticlesOperation() +{ + mGroupName = NULL; + mArticles = NULL; +} + +NNTPFetchAllArticlesOperation::~NNTPFetchAllArticlesOperation() +{ + MC_SAFE_RELEASE(mGroupName); + MC_SAFE_RELEASE(mArticles); +} + +void NNTPFetchAllArticlesOperation::setGroupName(String * groupname) +{ + MC_SAFE_REPLACE_COPY(String, mGroupName, groupname); +} + +String * NNTPFetchAllArticlesOperation::groupName() +{ + return mGroupName; +} + +IndexSet * NNTPFetchAllArticlesOperation::articles() +{ + return mArticles; +} + +void NNTPFetchAllArticlesOperation::main() +{ + ErrorCode error; + mArticles = session()->session()->fetchAllArticles(mGroupName, &error); + setError(error); + MC_SAFE_RETAIN(mArticles); +} diff --git a/src/async/nntp/MCNNTPFetchArticleOperation.cc b/src/async/nntp/MCNNTPFetchArticleOperation.cc deleted file mode 100644 index 1df0dc33..00000000 --- a/src/async/nntp/MCNNTPFetchArticleOperation.cc +++ /dev/null @@ -1,69 +0,0 @@ -// -// MCNNTPFetchArticleOperation.cpp -// mailcore2 -// -// Created by Robert Widmann on 8/13/14. -// Copyright (c) 2014 MailCore. All rights reserved. -// - -#include "MCNNTPFetchArticleOperation.h" - -#include "MCNNTPAsyncSession.h" -#include "MCNNTPSession.h" - -using namespace mailcore; - -NNTPFetchArticleOperation::NNTPFetchArticleOperation() -{ - mMessageIndex = 0; - mData = NULL; -} - -NNTPFetchArticleOperation::~NNTPFetchArticleOperation() -{ - MC_SAFE_RELEASE(mData); -} - -void NNTPFetchArticleOperation::setGroupName(String * groupName) { - MC_SAFE_REPLACE_COPY(String, mGroupName, groupName); -} - -String * NNTPFetchArticleOperation::groupName() { - return mGroupName; -} - -void NNTPFetchArticleOperation::setMessageID(String * groupName) { - MC_SAFE_REPLACE_COPY(String, mMessageID, groupName); -} - -String * NNTPFetchArticleOperation::messageID() { - return mMessageID; -} - -void NNTPFetchArticleOperation::setMessageIndex(unsigned int messageIndex) -{ - mMessageIndex = messageIndex; -} - -unsigned int NNTPFetchArticleOperation::messageIndex() -{ - return mMessageIndex; -} - -Data * NNTPFetchArticleOperation::data() -{ - return mData; -} - -void NNTPFetchArticleOperation::main() -{ - ErrorCode error; - if (mMessageID == NULL) { - mData = session()->session()->fetchArticle(mGroupName, mMessageIndex, this, &error); - } else { - mData = session()->session()->fetchArticleByMessageID(mGroupName, mMessageID, &error); - } - MC_SAFE_RETAIN(mData); - setError(error); -} - diff --git a/src/async/nntp/MCNNTPFetchArticleOperation.cpp b/src/async/nntp/MCNNTPFetchArticleOperation.cpp new file mode 100644 index 00000000..1df0dc33 --- /dev/null +++ b/src/async/nntp/MCNNTPFetchArticleOperation.cpp @@ -0,0 +1,69 @@ +// +// MCNNTPFetchArticleOperation.cpp +// mailcore2 +// +// Created by Robert Widmann on 8/13/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#include "MCNNTPFetchArticleOperation.h" + +#include "MCNNTPAsyncSession.h" +#include "MCNNTPSession.h" + +using namespace mailcore; + +NNTPFetchArticleOperation::NNTPFetchArticleOperation() +{ + mMessageIndex = 0; + mData = NULL; +} + +NNTPFetchArticleOperation::~NNTPFetchArticleOperation() +{ + MC_SAFE_RELEASE(mData); +} + +void NNTPFetchArticleOperation::setGroupName(String * groupName) { + MC_SAFE_REPLACE_COPY(String, mGroupName, groupName); +} + +String * NNTPFetchArticleOperation::groupName() { + return mGroupName; +} + +void NNTPFetchArticleOperation::setMessageID(String * groupName) { + MC_SAFE_REPLACE_COPY(String, mMessageID, groupName); +} + +String * NNTPFetchArticleOperation::messageID() { + return mMessageID; +} + +void NNTPFetchArticleOperation::setMessageIndex(unsigned int messageIndex) +{ + mMessageIndex = messageIndex; +} + +unsigned int NNTPFetchArticleOperation::messageIndex() +{ + return mMessageIndex; +} + +Data * NNTPFetchArticleOperation::data() +{ + return mData; +} + +void NNTPFetchArticleOperation::main() +{ + ErrorCode error; + if (mMessageID == NULL) { + mData = session()->session()->fetchArticle(mGroupName, mMessageIndex, this, &error); + } else { + mData = session()->session()->fetchArticleByMessageID(mGroupName, mMessageID, &error); + } + MC_SAFE_RETAIN(mData); + setError(error); +} + diff --git a/src/async/nntp/MCNNTPFetchHeaderOperation.cc b/src/async/nntp/MCNNTPFetchHeaderOperation.cc deleted file mode 100644 index 386dc142..00000000 --- a/src/async/nntp/MCNNTPFetchHeaderOperation.cc +++ /dev/null @@ -1,59 +0,0 @@ -// -// MCNNTPFetchHeaderOperation.cpp -// mailcore2 -// -// Created by Robert Widmann on 8/13/14. -// Copyright (c) 2014 MailCore. All rights reserved. -// - -#include "MCNNTPFetchHeaderOperation.h" - -#include "MCNNTPAsyncSession.h" -#include "MCNNTPSession.h" -#include "MCMessageHeader.h" - -using namespace mailcore; - -NNTPFetchHeaderOperation::NNTPFetchHeaderOperation() -{ - mMessageIndex = 0; - mHeader = NULL; -} - -NNTPFetchHeaderOperation::~NNTPFetchHeaderOperation() -{ - MC_SAFE_RELEASE(mHeader); -} - -void NNTPFetchHeaderOperation::setGroupName(String * groupName) { - MC_SAFE_REPLACE_COPY(String, mGroupName, groupName); -} - -String * NNTPFetchHeaderOperation::groupName() { - return mGroupName; -} - -void NNTPFetchHeaderOperation::setMessageIndex(unsigned int messageIndex) -{ - mMessageIndex = messageIndex; -} - -unsigned int NNTPFetchHeaderOperation::messageIndex() -{ - return mMessageIndex; -} - -MessageHeader * NNTPFetchHeaderOperation::header() -{ - return mHeader; -} - -void NNTPFetchHeaderOperation::main() -{ - ErrorCode error; - mHeader = session()->session()->fetchHeader(mGroupName, mMessageIndex, &error); - if (mHeader != NULL) { - mHeader->retain(); - } - setError(error); -} diff --git a/src/async/nntp/MCNNTPFetchHeaderOperation.cpp b/src/async/nntp/MCNNTPFetchHeaderOperation.cpp new file mode 100644 index 00000000..386dc142 --- /dev/null +++ b/src/async/nntp/MCNNTPFetchHeaderOperation.cpp @@ -0,0 +1,59 @@ +// +// MCNNTPFetchHeaderOperation.cpp +// mailcore2 +// +// Created by Robert Widmann on 8/13/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#include "MCNNTPFetchHeaderOperation.h" + +#include "MCNNTPAsyncSession.h" +#include "MCNNTPSession.h" +#include "MCMessageHeader.h" + +using namespace mailcore; + +NNTPFetchHeaderOperation::NNTPFetchHeaderOperation() +{ + mMessageIndex = 0; + mHeader = NULL; +} + +NNTPFetchHeaderOperation::~NNTPFetchHeaderOperation() +{ + MC_SAFE_RELEASE(mHeader); +} + +void NNTPFetchHeaderOperation::setGroupName(String * groupName) { + MC_SAFE_REPLACE_COPY(String, mGroupName, groupName); +} + +String * NNTPFetchHeaderOperation::groupName() { + return mGroupName; +} + +void NNTPFetchHeaderOperation::setMessageIndex(unsigned int messageIndex) +{ + mMessageIndex = messageIndex; +} + +unsigned int NNTPFetchHeaderOperation::messageIndex() +{ + return mMessageIndex; +} + +MessageHeader * NNTPFetchHeaderOperation::header() +{ + return mHeader; +} + +void NNTPFetchHeaderOperation::main() +{ + ErrorCode error; + mHeader = session()->session()->fetchHeader(mGroupName, mMessageIndex, &error); + if (mHeader != NULL) { + mHeader->retain(); + } + setError(error); +} diff --git a/src/async/nntp/MCNNTPFetchOverviewOperation.cc b/src/async/nntp/MCNNTPFetchOverviewOperation.cc deleted file mode 100644 index b05b29e6..00000000 --- a/src/async/nntp/MCNNTPFetchOverviewOperation.cc +++ /dev/null @@ -1,68 +0,0 @@ -// -// NNTPFetchOverviewOperation.cpp -// mailcore2 -// -// Created by Robert Widmann on 10/21/14. -// Copyright (c) 2014 MailCore. All rights reserved. -// - -#include "MCNNTPFetchOverviewOperation.h" - -#include "MCNNTPAsyncSession.h" -#include "MCNNTPSession.h" - -using namespace mailcore; - -NNTPFetchOverviewOperation::NNTPFetchOverviewOperation() -{ - mArticles = NULL; - mIndexes = NULL; - mGroupName = NULL; -} - -NNTPFetchOverviewOperation::~NNTPFetchOverviewOperation() -{ - MC_SAFE_RELEASE(mIndexes); - MC_SAFE_RELEASE(mGroupName); -} - -void NNTPFetchOverviewOperation::setIndexes(IndexSet * indexes) -{ - MC_SAFE_REPLACE_RETAIN(IndexSet, mIndexes, indexes); -} - -IndexSet * NNTPFetchOverviewOperation::indexes() -{ - return mIndexes; -} - -void NNTPFetchOverviewOperation::setGroupName(String * groupname) -{ - MC_SAFE_REPLACE_COPY(String, mGroupName, groupname); -} - -String * NNTPFetchOverviewOperation::groupName() -{ - return mGroupName; -} - -Array * NNTPFetchOverviewOperation::articles() { - return mArticles; -} - -void NNTPFetchOverviewOperation::main() -{ - ErrorCode error; - mArticles = Array::array(); - for(unsigned int i = 0 ; i < mIndexes->rangesCount() ; i ++) { - Range range = mIndexes->allRanges()[i]; - Array * articles = session()->session()->fetchOverArticlesInRange(range, mGroupName, &error); - if (error != ErrorNone) { - setError(error); - return; - } - mArticles->addObjectsFromArray(articles); - } - - setError(error); -} diff --git a/src/async/nntp/MCNNTPFetchOverviewOperation.cpp b/src/async/nntp/MCNNTPFetchOverviewOperation.cpp new file mode 100644 index 00000000..b05b29e6 --- /dev/null +++ b/src/async/nntp/MCNNTPFetchOverviewOperation.cpp @@ -0,0 +1,68 @@ +// +// NNTPFetchOverviewOperation.cpp +// mailcore2 +// +// Created by Robert Widmann on 10/21/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#include "MCNNTPFetchOverviewOperation.h" + +#include "MCNNTPAsyncSession.h" +#include "MCNNTPSession.h" + +using namespace mailcore; + +NNTPFetchOverviewOperation::NNTPFetchOverviewOperation() +{ + mArticles = NULL; + mIndexes = NULL; + mGroupName = NULL; +} + +NNTPFetchOverviewOperation::~NNTPFetchOverviewOperation() +{ + MC_SAFE_RELEASE(mIndexes); + MC_SAFE_RELEASE(mGroupName); +} + +void NNTPFetchOverviewOperation::setIndexes(IndexSet * indexes) +{ + MC_SAFE_REPLACE_RETAIN(IndexSet, mIndexes, indexes); +} + +IndexSet * NNTPFetchOverviewOperation::indexes() +{ + return mIndexes; +} + +void NNTPFetchOverviewOperation::setGroupName(String * groupname) +{ + MC_SAFE_REPLACE_COPY(String, mGroupName, groupname); +} + +String * NNTPFetchOverviewOperation::groupName() +{ + return mGroupName; +} + +Array * NNTPFetchOverviewOperation::articles() { + return mArticles; +} + +void NNTPFetchOverviewOperation::main() +{ + ErrorCode error; + mArticles = Array::array(); + for(unsigned int i = 0 ; i < mIndexes->rangesCount() ; i ++) { + Range range = mIndexes->allRanges()[i]; + Array * articles = session()->session()->fetchOverArticlesInRange(range, mGroupName, &error); + if (error != ErrorNone) { + setError(error); + return; + } + mArticles->addObjectsFromArray(articles); + } + + setError(error); +} diff --git a/src/async/nntp/MCNNTPFetchServerTimeOperation.cc b/src/async/nntp/MCNNTPFetchServerTimeOperation.cc deleted file mode 100644 index 86800733..00000000 --- a/src/async/nntp/MCNNTPFetchServerTimeOperation.cc +++ /dev/null @@ -1,34 +0,0 @@ -// -// MCNNTPFetchServerTimeOperation.cpp -// mailcore2 -// -// Created by Robert Widmann on 10/21/14. -// Copyright (c) 2014 MailCore. All rights reserved. -// - -#include "MCNNTPFetchServerTimeOperation.h" - -#include "MCNNTPAsyncSession.h" -#include "MCNNTPSession.h" - -using namespace mailcore; - -NNTPFetchServerTimeOperation::NNTPFetchServerTimeOperation() -{ -} - -NNTPFetchServerTimeOperation::~NNTPFetchServerTimeOperation() -{ -} - -time_t NNTPFetchServerTimeOperation::time() -{ - return mTime; -} - -void NNTPFetchServerTimeOperation::main() -{ - ErrorCode error; - mTime = session()->session()->fetchServerDate(&error); - setError(error); -} diff --git a/src/async/nntp/MCNNTPFetchServerTimeOperation.cpp b/src/async/nntp/MCNNTPFetchServerTimeOperation.cpp new file mode 100644 index 00000000..86800733 --- /dev/null +++ b/src/async/nntp/MCNNTPFetchServerTimeOperation.cpp @@ -0,0 +1,34 @@ +// +// MCNNTPFetchServerTimeOperation.cpp +// mailcore2 +// +// Created by Robert Widmann on 10/21/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#include "MCNNTPFetchServerTimeOperation.h" + +#include "MCNNTPAsyncSession.h" +#include "MCNNTPSession.h" + +using namespace mailcore; + +NNTPFetchServerTimeOperation::NNTPFetchServerTimeOperation() +{ +} + +NNTPFetchServerTimeOperation::~NNTPFetchServerTimeOperation() +{ +} + +time_t NNTPFetchServerTimeOperation::time() +{ + return mTime; +} + +void NNTPFetchServerTimeOperation::main() +{ + ErrorCode error; + mTime = session()->session()->fetchServerDate(&error); + setError(error); +} diff --git a/src/async/nntp/MCNNTPListNewsgroupsOperation.cc b/src/async/nntp/MCNNTPListNewsgroupsOperation.cc deleted file mode 100644 index 3747bacf..00000000 --- a/src/async/nntp/MCNNTPListNewsgroupsOperation.cc +++ /dev/null @@ -1,48 +0,0 @@ -// -// MCNNTPListNewsgroupsMessagesOperation.cpp -// mailcore2 -// -// Created by Robert Widmann on 8/13/14. -// Copyright (c) 2014 MailCore. All rights reserved. -// - -#include "MCNNTPListNewsgroupsOperation.h" - -#include "MCNNTPAsyncSession.h" -#include "MCNNTPSession.h" - -using namespace mailcore; - -NNTPListNewsgroupsOperation::NNTPListNewsgroupsOperation() -{ -} - -NNTPListNewsgroupsOperation::~NNTPListNewsgroupsOperation() -{ -} - -void NNTPListNewsgroupsOperation::setListsSubscribed(bool listsSubscribed) -{ - mListsSuscribed = listsSubscribed; -} - -bool NNTPListNewsgroupsOperation::listsSubscribed() -{ - return mListsSuscribed; -} - -Array * NNTPListNewsgroupsOperation::groups() { - return mGroups; -} - -void NNTPListNewsgroupsOperation::main() -{ - ErrorCode error; - - if (mListsSuscribed) { - mGroups = session()->session()->listDefaultNewsgroups(&error); - } else { - mGroups = session()->session()->listAllNewsgroups(&error); - } - setError(error); -} diff --git a/src/async/nntp/MCNNTPListNewsgroupsOperation.cpp b/src/async/nntp/MCNNTPListNewsgroupsOperation.cpp new file mode 100644 index 00000000..3747bacf --- /dev/null +++ b/src/async/nntp/MCNNTPListNewsgroupsOperation.cpp @@ -0,0 +1,48 @@ +// +// MCNNTPListNewsgroupsMessagesOperation.cpp +// mailcore2 +// +// Created by Robert Widmann on 8/13/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#include "MCNNTPListNewsgroupsOperation.h" + +#include "MCNNTPAsyncSession.h" +#include "MCNNTPSession.h" + +using namespace mailcore; + +NNTPListNewsgroupsOperation::NNTPListNewsgroupsOperation() +{ +} + +NNTPListNewsgroupsOperation::~NNTPListNewsgroupsOperation() +{ +} + +void NNTPListNewsgroupsOperation::setListsSubscribed(bool listsSubscribed) +{ + mListsSuscribed = listsSubscribed; +} + +bool NNTPListNewsgroupsOperation::listsSubscribed() +{ + return mListsSuscribed; +} + +Array * NNTPListNewsgroupsOperation::groups() { + return mGroups; +} + +void NNTPListNewsgroupsOperation::main() +{ + ErrorCode error; + + if (mListsSuscribed) { + mGroups = session()->session()->listDefaultNewsgroups(&error); + } else { + mGroups = session()->session()->listAllNewsgroups(&error); + } + setError(error); +} diff --git a/src/async/nntp/MCNNTPOperation.cc b/src/async/nntp/MCNNTPOperation.cc deleted file mode 100644 index 3368ba0e..00000000 --- a/src/async/nntp/MCNNTPOperation.cc +++ /dev/null @@ -1,104 +0,0 @@ -// -// MCNNTPOperation.cpp -// mailcore2 -// -// Created by Robert Widmann on 8/13/14. -// Copyright (c) 2014 MailCore. All rights reserved. -// - -#include "MCNNTPOperation.h" - -#include - -#include "MCNNTPSession.h" -#include "MCNNTPAsyncSession.h" -#include "MCNNTPOperationCallback.h" - -using namespace mailcore; - -NNTPOperation::NNTPOperation() -{ - mSession = NULL; - mPopCallback = NULL; - mError = ErrorNone; -} - -NNTPOperation::~NNTPOperation() -{ - MC_SAFE_RELEASE(mSession); -} - -void NNTPOperation::setSession(NNTPAsyncSession * session) -{ - MC_SAFE_REPLACE_RETAIN(NNTPAsyncSession, mSession, session); -#if __APPLE__ - dispatch_queue_t queue; - if (session != NULL) { - queue = session->dispatchQueue(); - } - else { - queue = dispatch_get_main_queue(); - } - setCallbackDispatchQueue(queue); -#endif -} - -NNTPAsyncSession * NNTPOperation::session() -{ - return mSession; -} - -void NNTPOperation::setNNTPCallback(NNTPOperationCallback * callback) -{ - mPopCallback = callback; -} - -NNTPOperationCallback * NNTPOperation::nntpCallback() -{ - return mPopCallback; -} - -void NNTPOperation::setError(ErrorCode error) -{ - mError = error; -} - -ErrorCode NNTPOperation::error() -{ - return mError; -} - -void NNTPOperation::start() -{ - mSession->runOperation(this); -} - -struct progressContext { - unsigned int current; - unsigned int maximum; -}; - -void NNTPOperation::bodyProgress(NNTPSession * session, unsigned int current, unsigned int maximum) -{ - struct progressContext * context = (struct progressContext *) calloc(sizeof(* context), 1); - context->current = current; - context->maximum = maximum; - - retain(); - performMethodOnCallbackThread((Object::Method) &NNTPOperation::bodyProgressOnMainThread, context); -} - -void NNTPOperation::bodyProgressOnMainThread(void * ctx) -{ - if (isCancelled()) { - release(); - return; - } - - struct progressContext * context = (struct progressContext *) ctx; - if (mPopCallback != NULL) { - mPopCallback->bodyProgress(this, context->current, context->maximum); - } - free(context); - release(); -} diff --git a/src/async/nntp/MCNNTPOperation.cpp b/src/async/nntp/MCNNTPOperation.cpp new file mode 100644 index 00000000..3368ba0e --- /dev/null +++ b/src/async/nntp/MCNNTPOperation.cpp @@ -0,0 +1,104 @@ +// +// MCNNTPOperation.cpp +// mailcore2 +// +// Created by Robert Widmann on 8/13/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#include "MCNNTPOperation.h" + +#include + +#include "MCNNTPSession.h" +#include "MCNNTPAsyncSession.h" +#include "MCNNTPOperationCallback.h" + +using namespace mailcore; + +NNTPOperation::NNTPOperation() +{ + mSession = NULL; + mPopCallback = NULL; + mError = ErrorNone; +} + +NNTPOperation::~NNTPOperation() +{ + MC_SAFE_RELEASE(mSession); +} + +void NNTPOperation::setSession(NNTPAsyncSession * session) +{ + MC_SAFE_REPLACE_RETAIN(NNTPAsyncSession, mSession, session); +#if __APPLE__ + dispatch_queue_t queue; + if (session != NULL) { + queue = session->dispatchQueue(); + } + else { + queue = dispatch_get_main_queue(); + } + setCallbackDispatchQueue(queue); +#endif +} + +NNTPAsyncSession * NNTPOperation::session() +{ + return mSession; +} + +void NNTPOperation::setNNTPCallback(NNTPOperationCallback * callback) +{ + mPopCallback = callback; +} + +NNTPOperationCallback * NNTPOperation::nntpCallback() +{ + return mPopCallback; +} + +void NNTPOperation::setError(ErrorCode error) +{ + mError = error; +} + +ErrorCode NNTPOperation::error() +{ + return mError; +} + +void NNTPOperation::start() +{ + mSession->runOperation(this); +} + +struct progressContext { + unsigned int current; + unsigned int maximum; +}; + +void NNTPOperation::bodyProgress(NNTPSession * session, unsigned int current, unsigned int maximum) +{ + struct progressContext * context = (struct progressContext *) calloc(sizeof(* context), 1); + context->current = current; + context->maximum = maximum; + + retain(); + performMethodOnCallbackThread((Object::Method) &NNTPOperation::bodyProgressOnMainThread, context); +} + +void NNTPOperation::bodyProgressOnMainThread(void * ctx) +{ + if (isCancelled()) { + release(); + return; + } + + struct progressContext * context = (struct progressContext *) ctx; + if (mPopCallback != NULL) { + mPopCallback->bodyProgress(this, context->current, context->maximum); + } + free(context); + release(); +} diff --git a/src/async/pop/MCPOPAsyncSession.cc b/src/async/pop/MCPOPAsyncSession.cc deleted file mode 100644 index 2a6bd3b0..00000000 --- a/src/async/pop/MCPOPAsyncSession.cc +++ /dev/null @@ -1,275 +0,0 @@ -// -// MCPopAsyncSession.cpp -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/16/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCPOPAsyncSession.h" - -#include "MCPOP.h" -#include "MCPOPFetchHeaderOperation.h" -#include "MCPOPFetchMessageOperation.h" -#include "MCPOPDeleteMessagesOperation.h" -#include "MCPOPFetchMessagesOperation.h" -#include "MCPOPCheckAccountOperation.h" -#include "MCPOPNoopOperation.h" -#include "MCOperationQueueCallback.h" -#include "MCConnectionLogger.h" - -using namespace mailcore; - -namespace mailcore { - class POPOperationQueueCallback : public Object, public OperationQueueCallback { - public: - POPOperationQueueCallback(POPAsyncSession * session) { - mSession = session; - } - - virtual ~POPOperationQueueCallback() { - } - - virtual void queueStartRunning() { - mSession->retain(); - } - - virtual void queueStoppedRunning() { - mSession->release(); - } - - private: - POPAsyncSession * mSession; - }; - - class POPConnectionLogger : public Object, public ConnectionLogger { - public: - POPConnectionLogger(POPAsyncSession * session) { - mSession = session; - } - - virtual ~POPConnectionLogger() { - } - - virtual void log(void * sender, ConnectionLogType logType, Data * buffer) - { - mSession->logConnection(logType, buffer); - } - - private: - POPAsyncSession * mSession; - }; - -} - -POPAsyncSession::POPAsyncSession() -{ - mSession = new POPSession(); - 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); -} - -void POPAsyncSession::setHostname(String * hostname) -{ - mSession->setHostname(hostname); -} - -String * POPAsyncSession::hostname() -{ - return mSession->hostname(); -} - -void POPAsyncSession::setPort(unsigned int port) -{ - mSession->setPort(port); -} - -unsigned int POPAsyncSession::port() -{ - return mSession->port(); -} - -void POPAsyncSession::setUsername(String * username) -{ - mSession->setUsername(username); -} - -String * POPAsyncSession::username() -{ - return mSession->username(); -} - -void POPAsyncSession::setPassword(String * password) -{ - mSession->setPassword(password); -} - -String * POPAsyncSession::password() -{ - return mSession->password(); -} - -void POPAsyncSession::setAuthType(AuthType authType) -{ - mSession->setAuthType(authType); -} - -AuthType POPAsyncSession::authType() -{ - return mSession->authType(); -} - -void POPAsyncSession::setConnectionType(ConnectionType connectionType) -{ - mSession->setConnectionType(connectionType); -} - -ConnectionType POPAsyncSession::connectionType() -{ - return mSession->connectionType(); -} - -void POPAsyncSession::setTimeout(time_t timeout) -{ - mSession->setTimeout(timeout); -} - -time_t POPAsyncSession::timeout() -{ - return mSession->timeout(); -} - -void POPAsyncSession::setCheckCertificateEnabled(bool enabled) -{ - mSession->setCheckCertificateEnabled(enabled); -} - -bool POPAsyncSession::isCheckCertificateEnabled() -{ - return mSession->isCheckCertificateEnabled(); -} - -POPFetchMessagesOperation * POPAsyncSession::fetchMessagesOperation() -{ - POPFetchMessagesOperation * op = new POPFetchMessagesOperation(); - op->setSession(this); - op->autorelease(); - return op; -} - -POPFetchHeaderOperation * POPAsyncSession::fetchHeaderOperation(unsigned int index) -{ - POPFetchHeaderOperation * op = new POPFetchHeaderOperation(); - op->setSession(this); - op->setMessageIndex(index); - op->autorelease(); - return op; -} - -POPFetchMessageOperation * POPAsyncSession::fetchMessageOperation(unsigned int index) -{ - POPFetchMessageOperation * op = new POPFetchMessageOperation(); - op->setSession(this); - op->setMessageIndex(index); - op->autorelease(); - return op; -} - -POPOperation * POPAsyncSession::deleteMessagesOperation(IndexSet * indexes) -{ - POPDeleteMessagesOperation * op = new POPDeleteMessagesOperation(); - op->setSession(this); - op->setMessageIndexes(indexes); - op->autorelease(); - return op; -} - -POPOperation * POPAsyncSession::disconnectOperation() -{ - return deleteMessagesOperation(IndexSet::indexSet()); -} - -POPOperation * POPAsyncSession::checkAccountOperation() -{ - POPCheckAccountOperation * op = new POPCheckAccountOperation(); - op->setSession(this); - op->autorelease(); - return op; -} - -POPOperation * POPAsyncSession::noopOperation() -{ - POPNoopOperation * op = new POPNoopOperation(); - op->setSession(this); - op->autorelease(); - return op; -} - -POPSession * POPAsyncSession::session() -{ - return mSession; -} - -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); -} - -#if __APPLE__ -void POPAsyncSession::setDispatchQueue(dispatch_queue_t dispatchQueue) -{ - mQueue->setDispatchQueue(dispatchQueue); -} - -dispatch_queue_t POPAsyncSession::dispatchQueue() -{ - return mQueue->dispatchQueue(); -} -#endif diff --git a/src/async/pop/MCPOPAsyncSession.cpp b/src/async/pop/MCPOPAsyncSession.cpp new file mode 100644 index 00000000..2a6bd3b0 --- /dev/null +++ b/src/async/pop/MCPOPAsyncSession.cpp @@ -0,0 +1,275 @@ +// +// MCPopAsyncSession.cpp +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/16/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCPOPAsyncSession.h" + +#include "MCPOP.h" +#include "MCPOPFetchHeaderOperation.h" +#include "MCPOPFetchMessageOperation.h" +#include "MCPOPDeleteMessagesOperation.h" +#include "MCPOPFetchMessagesOperation.h" +#include "MCPOPCheckAccountOperation.h" +#include "MCPOPNoopOperation.h" +#include "MCOperationQueueCallback.h" +#include "MCConnectionLogger.h" + +using namespace mailcore; + +namespace mailcore { + class POPOperationQueueCallback : public Object, public OperationQueueCallback { + public: + POPOperationQueueCallback(POPAsyncSession * session) { + mSession = session; + } + + virtual ~POPOperationQueueCallback() { + } + + virtual void queueStartRunning() { + mSession->retain(); + } + + virtual void queueStoppedRunning() { + mSession->release(); + } + + private: + POPAsyncSession * mSession; + }; + + class POPConnectionLogger : public Object, public ConnectionLogger { + public: + POPConnectionLogger(POPAsyncSession * session) { + mSession = session; + } + + virtual ~POPConnectionLogger() { + } + + virtual void log(void * sender, ConnectionLogType logType, Data * buffer) + { + mSession->logConnection(logType, buffer); + } + + private: + POPAsyncSession * mSession; + }; + +} + +POPAsyncSession::POPAsyncSession() +{ + mSession = new POPSession(); + 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); +} + +void POPAsyncSession::setHostname(String * hostname) +{ + mSession->setHostname(hostname); +} + +String * POPAsyncSession::hostname() +{ + return mSession->hostname(); +} + +void POPAsyncSession::setPort(unsigned int port) +{ + mSession->setPort(port); +} + +unsigned int POPAsyncSession::port() +{ + return mSession->port(); +} + +void POPAsyncSession::setUsername(String * username) +{ + mSession->setUsername(username); +} + +String * POPAsyncSession::username() +{ + return mSession->username(); +} + +void POPAsyncSession::setPassword(String * password) +{ + mSession->setPassword(password); +} + +String * POPAsyncSession::password() +{ + return mSession->password(); +} + +void POPAsyncSession::setAuthType(AuthType authType) +{ + mSession->setAuthType(authType); +} + +AuthType POPAsyncSession::authType() +{ + return mSession->authType(); +} + +void POPAsyncSession::setConnectionType(ConnectionType connectionType) +{ + mSession->setConnectionType(connectionType); +} + +ConnectionType POPAsyncSession::connectionType() +{ + return mSession->connectionType(); +} + +void POPAsyncSession::setTimeout(time_t timeout) +{ + mSession->setTimeout(timeout); +} + +time_t POPAsyncSession::timeout() +{ + return mSession->timeout(); +} + +void POPAsyncSession::setCheckCertificateEnabled(bool enabled) +{ + mSession->setCheckCertificateEnabled(enabled); +} + +bool POPAsyncSession::isCheckCertificateEnabled() +{ + return mSession->isCheckCertificateEnabled(); +} + +POPFetchMessagesOperation * POPAsyncSession::fetchMessagesOperation() +{ + POPFetchMessagesOperation * op = new POPFetchMessagesOperation(); + op->setSession(this); + op->autorelease(); + return op; +} + +POPFetchHeaderOperation * POPAsyncSession::fetchHeaderOperation(unsigned int index) +{ + POPFetchHeaderOperation * op = new POPFetchHeaderOperation(); + op->setSession(this); + op->setMessageIndex(index); + op->autorelease(); + return op; +} + +POPFetchMessageOperation * POPAsyncSession::fetchMessageOperation(unsigned int index) +{ + POPFetchMessageOperation * op = new POPFetchMessageOperation(); + op->setSession(this); + op->setMessageIndex(index); + op->autorelease(); + return op; +} + +POPOperation * POPAsyncSession::deleteMessagesOperation(IndexSet * indexes) +{ + POPDeleteMessagesOperation * op = new POPDeleteMessagesOperation(); + op->setSession(this); + op->setMessageIndexes(indexes); + op->autorelease(); + return op; +} + +POPOperation * POPAsyncSession::disconnectOperation() +{ + return deleteMessagesOperation(IndexSet::indexSet()); +} + +POPOperation * POPAsyncSession::checkAccountOperation() +{ + POPCheckAccountOperation * op = new POPCheckAccountOperation(); + op->setSession(this); + op->autorelease(); + return op; +} + +POPOperation * POPAsyncSession::noopOperation() +{ + POPNoopOperation * op = new POPNoopOperation(); + op->setSession(this); + op->autorelease(); + return op; +} + +POPSession * POPAsyncSession::session() +{ + return mSession; +} + +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); +} + +#if __APPLE__ +void POPAsyncSession::setDispatchQueue(dispatch_queue_t dispatchQueue) +{ + mQueue->setDispatchQueue(dispatchQueue); +} + +dispatch_queue_t POPAsyncSession::dispatchQueue() +{ + return mQueue->dispatchQueue(); +} +#endif diff --git a/src/async/pop/MCPOPCheckAccountOperation.cc b/src/async/pop/MCPOPCheckAccountOperation.cc deleted file mode 100644 index f83cd740..00000000 --- a/src/async/pop/MCPOPCheckAccountOperation.cc +++ /dev/null @@ -1,30 +0,0 @@ -// -// MCPOPCheckAccountOperation.cpp -// mailcore2 -// -// Created by DINH Viêt Hoà on 4/6/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCPOPCheckAccountOperation.h" - -#include "MCPOPAsyncSession.h" -#include "MCPOPSession.h" - -using namespace mailcore; - -POPCheckAccountOperation::POPCheckAccountOperation() -{ -} - -POPCheckAccountOperation::~POPCheckAccountOperation() -{ -} - -void POPCheckAccountOperation::main() -{ - ErrorCode error; - - session()->session()->checkAccount(&error); - setError(error); -} diff --git a/src/async/pop/MCPOPCheckAccountOperation.cpp b/src/async/pop/MCPOPCheckAccountOperation.cpp new file mode 100644 index 00000000..f83cd740 --- /dev/null +++ b/src/async/pop/MCPOPCheckAccountOperation.cpp @@ -0,0 +1,30 @@ +// +// MCPOPCheckAccountOperation.cpp +// mailcore2 +// +// Created by DINH Viêt Hoà on 4/6/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCPOPCheckAccountOperation.h" + +#include "MCPOPAsyncSession.h" +#include "MCPOPSession.h" + +using namespace mailcore; + +POPCheckAccountOperation::POPCheckAccountOperation() +{ +} + +POPCheckAccountOperation::~POPCheckAccountOperation() +{ +} + +void POPCheckAccountOperation::main() +{ + ErrorCode error; + + session()->session()->checkAccount(&error); + setError(error); +} diff --git a/src/async/pop/MCPOPDeleteMessagesOperation.cc b/src/async/pop/MCPOPDeleteMessagesOperation.cc deleted file mode 100644 index 40cf11f6..00000000 --- a/src/async/pop/MCPOPDeleteMessagesOperation.cc +++ /dev/null @@ -1,63 +0,0 @@ -// -// MCPOPDeleteMessagesOperation.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/16/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCPOPDeleteMessagesOperation.h" - -#include "MCPOPAsyncSession.h" -#include "MCPOPSession.h" - -using namespace mailcore; - -POPDeleteMessagesOperation::POPDeleteMessagesOperation() -{ - mMessageIndexes = NULL; -} - -POPDeleteMessagesOperation::~POPDeleteMessagesOperation() -{ - MC_SAFE_RELEASE(mMessageIndexes); -} - -void POPDeleteMessagesOperation::setMessageIndexes(IndexSet * indexes) -{ - MC_SAFE_REPLACE_RETAIN(IndexSet, mMessageIndexes, indexes); -} - -IndexSet * POPDeleteMessagesOperation::messageIndexes() -{ - return mMessageIndexes; -} - -void POPDeleteMessagesOperation::main() -{ - if (mMessageIndexes == NULL) - return; - - ErrorCode error; -#if 0 - for(unsigned int i = 0 ; i < mMessageIndexes->rangesCount() ; i ++) { - Range range = mMessageIndexes->allRanges()[i]; - for(unsigned int k = 0 ; k <= range.length ; k ++) { - session()->session()->deleteMessage((unsigned int) (range.location + k), &error); - if (error != ErrorNone) { - setError(error); - return; - } - } - } -#endif - mc_foreachindexset(index, mMessageIndexes) { - session()->session()->deleteMessage((unsigned int) index, &error); - if (error != ErrorNone) { - setError(error); - return; - } - } - session()->session()->disconnect(); -} - diff --git a/src/async/pop/MCPOPDeleteMessagesOperation.cpp b/src/async/pop/MCPOPDeleteMessagesOperation.cpp new file mode 100644 index 00000000..40cf11f6 --- /dev/null +++ b/src/async/pop/MCPOPDeleteMessagesOperation.cpp @@ -0,0 +1,63 @@ +// +// MCPOPDeleteMessagesOperation.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/16/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCPOPDeleteMessagesOperation.h" + +#include "MCPOPAsyncSession.h" +#include "MCPOPSession.h" + +using namespace mailcore; + +POPDeleteMessagesOperation::POPDeleteMessagesOperation() +{ + mMessageIndexes = NULL; +} + +POPDeleteMessagesOperation::~POPDeleteMessagesOperation() +{ + MC_SAFE_RELEASE(mMessageIndexes); +} + +void POPDeleteMessagesOperation::setMessageIndexes(IndexSet * indexes) +{ + MC_SAFE_REPLACE_RETAIN(IndexSet, mMessageIndexes, indexes); +} + +IndexSet * POPDeleteMessagesOperation::messageIndexes() +{ + return mMessageIndexes; +} + +void POPDeleteMessagesOperation::main() +{ + if (mMessageIndexes == NULL) + return; + + ErrorCode error; +#if 0 + for(unsigned int i = 0 ; i < mMessageIndexes->rangesCount() ; i ++) { + Range range = mMessageIndexes->allRanges()[i]; + for(unsigned int k = 0 ; k <= range.length ; k ++) { + session()->session()->deleteMessage((unsigned int) (range.location + k), &error); + if (error != ErrorNone) { + setError(error); + return; + } + } + } +#endif + mc_foreachindexset(index, mMessageIndexes) { + session()->session()->deleteMessage((unsigned int) index, &error); + if (error != ErrorNone) { + setError(error); + return; + } + } + session()->session()->disconnect(); +} + diff --git a/src/async/pop/MCPOPFetchHeaderOperation.cc b/src/async/pop/MCPOPFetchHeaderOperation.cc deleted file mode 100644 index 60a0e8a6..00000000 --- a/src/async/pop/MCPOPFetchHeaderOperation.cc +++ /dev/null @@ -1,51 +0,0 @@ -// -// MCPOPFetchHeaderOperation.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/16/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCPOPFetchHeaderOperation.h" - -#include "MCPOPAsyncSession.h" -#include "MCPOPSession.h" -#include "MCMessageHeader.h" - -using namespace mailcore; - -POPFetchHeaderOperation::POPFetchHeaderOperation() -{ - mMessageIndex = 0; - mHeader = NULL; -} - -POPFetchHeaderOperation::~POPFetchHeaderOperation() -{ - MC_SAFE_RELEASE(mHeader); -} - -void POPFetchHeaderOperation::setMessageIndex(unsigned int messageIndex) -{ - mMessageIndex = messageIndex; -} - -unsigned int POPFetchHeaderOperation::messageIndex() -{ - return mMessageIndex; -} - -MessageHeader * POPFetchHeaderOperation::header() -{ - return mHeader; -} - -void POPFetchHeaderOperation::main() -{ - ErrorCode error; - mHeader = session()->session()->fetchHeader(mMessageIndex, &error); - if (mHeader != NULL) { - mHeader->retain(); - } - setError(error); -} diff --git a/src/async/pop/MCPOPFetchHeaderOperation.cpp b/src/async/pop/MCPOPFetchHeaderOperation.cpp new file mode 100644 index 00000000..60a0e8a6 --- /dev/null +++ b/src/async/pop/MCPOPFetchHeaderOperation.cpp @@ -0,0 +1,51 @@ +// +// MCPOPFetchHeaderOperation.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/16/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCPOPFetchHeaderOperation.h" + +#include "MCPOPAsyncSession.h" +#include "MCPOPSession.h" +#include "MCMessageHeader.h" + +using namespace mailcore; + +POPFetchHeaderOperation::POPFetchHeaderOperation() +{ + mMessageIndex = 0; + mHeader = NULL; +} + +POPFetchHeaderOperation::~POPFetchHeaderOperation() +{ + MC_SAFE_RELEASE(mHeader); +} + +void POPFetchHeaderOperation::setMessageIndex(unsigned int messageIndex) +{ + mMessageIndex = messageIndex; +} + +unsigned int POPFetchHeaderOperation::messageIndex() +{ + return mMessageIndex; +} + +MessageHeader * POPFetchHeaderOperation::header() +{ + return mHeader; +} + +void POPFetchHeaderOperation::main() +{ + ErrorCode error; + mHeader = session()->session()->fetchHeader(mMessageIndex, &error); + if (mHeader != NULL) { + mHeader->retain(); + } + setError(error); +} diff --git a/src/async/pop/MCPOPFetchMessageOperation.cc b/src/async/pop/MCPOPFetchMessageOperation.cc deleted file mode 100644 index ca822a9e..00000000 --- a/src/async/pop/MCPOPFetchMessageOperation.cc +++ /dev/null @@ -1,49 +0,0 @@ -// -// MCPOPFetchMessageOperation.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/16/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCPOPFetchMessageOperation.h" - -#include "MCPOPAsyncSession.h" -#include "MCPOPSession.h" - -using namespace mailcore; - -POPFetchMessageOperation::POPFetchMessageOperation() -{ - mMessageIndex = 0; - mData = NULL; -} - -POPFetchMessageOperation::~POPFetchMessageOperation() -{ - MC_SAFE_RELEASE(mData); -} - -void POPFetchMessageOperation::setMessageIndex(unsigned int messageIndex) -{ - mMessageIndex = messageIndex; -} - -unsigned int POPFetchMessageOperation::messageIndex() -{ - return mMessageIndex; -} - -Data * POPFetchMessageOperation::data() -{ - return mData; -} - -void POPFetchMessageOperation::main() -{ - ErrorCode error; - mData = session()->session()->fetchMessage(mMessageIndex, this, &error); - MC_SAFE_RETAIN(mData); - setError(error); -} - diff --git a/src/async/pop/MCPOPFetchMessageOperation.cpp b/src/async/pop/MCPOPFetchMessageOperation.cpp new file mode 100644 index 00000000..ca822a9e --- /dev/null +++ b/src/async/pop/MCPOPFetchMessageOperation.cpp @@ -0,0 +1,49 @@ +// +// MCPOPFetchMessageOperation.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/16/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCPOPFetchMessageOperation.h" + +#include "MCPOPAsyncSession.h" +#include "MCPOPSession.h" + +using namespace mailcore; + +POPFetchMessageOperation::POPFetchMessageOperation() +{ + mMessageIndex = 0; + mData = NULL; +} + +POPFetchMessageOperation::~POPFetchMessageOperation() +{ + MC_SAFE_RELEASE(mData); +} + +void POPFetchMessageOperation::setMessageIndex(unsigned int messageIndex) +{ + mMessageIndex = messageIndex; +} + +unsigned int POPFetchMessageOperation::messageIndex() +{ + return mMessageIndex; +} + +Data * POPFetchMessageOperation::data() +{ + return mData; +} + +void POPFetchMessageOperation::main() +{ + ErrorCode error; + mData = session()->session()->fetchMessage(mMessageIndex, this, &error); + MC_SAFE_RETAIN(mData); + setError(error); +} + diff --git a/src/async/pop/MCPOPFetchMessagesOperation.cc b/src/async/pop/MCPOPFetchMessagesOperation.cc deleted file mode 100644 index 9b7627fa..00000000 --- a/src/async/pop/MCPOPFetchMessagesOperation.cc +++ /dev/null @@ -1,37 +0,0 @@ -// -// MCPOPFetchMessagesOperation.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/16/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCPOPFetchMessagesOperation.h" - -#include "MCPOPAsyncSession.h" -#include "MCPOPSession.h" - -using namespace mailcore; - -POPFetchMessagesOperation::POPFetchMessagesOperation() -{ - mMessages = NULL; -} - -POPFetchMessagesOperation::~POPFetchMessagesOperation() -{ - MC_SAFE_RELEASE(mMessages); -} - -Array * POPFetchMessagesOperation::messages() -{ - return mMessages; -} - -void POPFetchMessagesOperation::main() -{ - ErrorCode error; - mMessages = session()->session()->fetchMessages(&error); - setError(error); - MC_SAFE_RETAIN(mMessages); -} diff --git a/src/async/pop/MCPOPFetchMessagesOperation.cpp b/src/async/pop/MCPOPFetchMessagesOperation.cpp new file mode 100644 index 00000000..9b7627fa --- /dev/null +++ b/src/async/pop/MCPOPFetchMessagesOperation.cpp @@ -0,0 +1,37 @@ +// +// MCPOPFetchMessagesOperation.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/16/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCPOPFetchMessagesOperation.h" + +#include "MCPOPAsyncSession.h" +#include "MCPOPSession.h" + +using namespace mailcore; + +POPFetchMessagesOperation::POPFetchMessagesOperation() +{ + mMessages = NULL; +} + +POPFetchMessagesOperation::~POPFetchMessagesOperation() +{ + MC_SAFE_RELEASE(mMessages); +} + +Array * POPFetchMessagesOperation::messages() +{ + return mMessages; +} + +void POPFetchMessagesOperation::main() +{ + ErrorCode error; + mMessages = session()->session()->fetchMessages(&error); + setError(error); + MC_SAFE_RETAIN(mMessages); +} diff --git a/src/async/pop/MCPOPNoopOperation.cc b/src/async/pop/MCPOPNoopOperation.cc deleted file mode 100644 index 034b1fa8..00000000 --- a/src/async/pop/MCPOPNoopOperation.cc +++ /dev/null @@ -1,30 +0,0 @@ -// -// MCPOPNoopOperation.cpp -// mailcore2 -// -// Created by Robert Widmann on 9/24/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCPOPNoopOperation.h" - -#include "MCPOPAsyncSession.h" -#include "MCPOPSession.h" - -using namespace mailcore; - -POPNoopOperation::POPNoopOperation() -{ -} - -POPNoopOperation::~POPNoopOperation() -{ -} - -void POPNoopOperation::main() -{ - ErrorCode error; - - session()->session()->noop(&error); - setError(error); -} diff --git a/src/async/pop/MCPOPNoopOperation.cpp b/src/async/pop/MCPOPNoopOperation.cpp new file mode 100644 index 00000000..034b1fa8 --- /dev/null +++ b/src/async/pop/MCPOPNoopOperation.cpp @@ -0,0 +1,30 @@ +// +// MCPOPNoopOperation.cpp +// mailcore2 +// +// Created by Robert Widmann on 9/24/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCPOPNoopOperation.h" + +#include "MCPOPAsyncSession.h" +#include "MCPOPSession.h" + +using namespace mailcore; + +POPNoopOperation::POPNoopOperation() +{ +} + +POPNoopOperation::~POPNoopOperation() +{ +} + +void POPNoopOperation::main() +{ + ErrorCode error; + + session()->session()->noop(&error); + setError(error); +} diff --git a/src/async/pop/MCPOPOperation.cc b/src/async/pop/MCPOPOperation.cc deleted file mode 100644 index 479876b6..00000000 --- a/src/async/pop/MCPOPOperation.cc +++ /dev/null @@ -1,104 +0,0 @@ -// -// MCPOPOperation.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/16/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCPOPOperation.h" - -#include - -#include "MCPOPSession.h" -#include "MCPOPAsyncSession.h" -#include "MCPOPOperationCallback.h" - -using namespace mailcore; - -POPOperation::POPOperation() -{ - mSession = NULL; - mPopCallback = NULL; - mError = ErrorNone; -} - -POPOperation::~POPOperation() -{ - MC_SAFE_RELEASE(mSession); -} - -void POPOperation::setSession(POPAsyncSession * session) -{ - MC_SAFE_REPLACE_RETAIN(POPAsyncSession, mSession, session); -#if __APPLE__ - dispatch_queue_t queue; - if (session != NULL) { - queue = session->dispatchQueue(); - } - else { - queue = dispatch_get_main_queue(); - } - setCallbackDispatchQueue(queue); -#endif -} - -POPAsyncSession * POPOperation::session() -{ - return mSession; -} - -void POPOperation::setPopCallback(POPOperationCallback * callback) -{ - mPopCallback = callback; -} - -POPOperationCallback * POPOperation::popCallback() -{ - return mPopCallback; -} - -void POPOperation::setError(ErrorCode error) -{ - mError = error; -} - -ErrorCode POPOperation::error() -{ - return mError; -} - -void POPOperation::start() -{ - mSession->runOperation(this); -} - -struct progressContext { - unsigned int current; - unsigned int maximum; -}; - -void POPOperation::bodyProgress(POPSession * session, unsigned int current, unsigned int maximum) -{ - struct progressContext * context = (struct progressContext *) calloc(sizeof(* context), 1); - context->current = current; - context->maximum = maximum; - - retain(); - performMethodOnCallbackThread((Object::Method) &POPOperation::bodyProgressOnMainThread, context); -} - -void POPOperation::bodyProgressOnMainThread(void * ctx) -{ - if (isCancelled()) { - release(); - return; - } - - struct progressContext * context = (struct progressContext *) ctx; - if (mPopCallback != NULL) { - mPopCallback->bodyProgress(this, context->current, context->maximum); - } - free(context); - release(); -} diff --git a/src/async/pop/MCPOPOperation.cpp b/src/async/pop/MCPOPOperation.cpp new file mode 100644 index 00000000..479876b6 --- /dev/null +++ b/src/async/pop/MCPOPOperation.cpp @@ -0,0 +1,104 @@ +// +// MCPOPOperation.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/16/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCPOPOperation.h" + +#include + +#include "MCPOPSession.h" +#include "MCPOPAsyncSession.h" +#include "MCPOPOperationCallback.h" + +using namespace mailcore; + +POPOperation::POPOperation() +{ + mSession = NULL; + mPopCallback = NULL; + mError = ErrorNone; +} + +POPOperation::~POPOperation() +{ + MC_SAFE_RELEASE(mSession); +} + +void POPOperation::setSession(POPAsyncSession * session) +{ + MC_SAFE_REPLACE_RETAIN(POPAsyncSession, mSession, session); +#if __APPLE__ + dispatch_queue_t queue; + if (session != NULL) { + queue = session->dispatchQueue(); + } + else { + queue = dispatch_get_main_queue(); + } + setCallbackDispatchQueue(queue); +#endif +} + +POPAsyncSession * POPOperation::session() +{ + return mSession; +} + +void POPOperation::setPopCallback(POPOperationCallback * callback) +{ + mPopCallback = callback; +} + +POPOperationCallback * POPOperation::popCallback() +{ + return mPopCallback; +} + +void POPOperation::setError(ErrorCode error) +{ + mError = error; +} + +ErrorCode POPOperation::error() +{ + return mError; +} + +void POPOperation::start() +{ + mSession->runOperation(this); +} + +struct progressContext { + unsigned int current; + unsigned int maximum; +}; + +void POPOperation::bodyProgress(POPSession * session, unsigned int current, unsigned int maximum) +{ + struct progressContext * context = (struct progressContext *) calloc(sizeof(* context), 1); + context->current = current; + context->maximum = maximum; + + retain(); + performMethodOnCallbackThread((Object::Method) &POPOperation::bodyProgressOnMainThread, context); +} + +void POPOperation::bodyProgressOnMainThread(void * ctx) +{ + if (isCancelled()) { + release(); + return; + } + + struct progressContext * context = (struct progressContext *) ctx; + if (mPopCallback != NULL) { + mPopCallback->bodyProgress(this, context->current, context->maximum); + } + free(context); + release(); +} diff --git a/src/async/smtp/MCSMTPAsyncSession.cc b/src/async/smtp/MCSMTPAsyncSession.cc deleted file mode 100644 index 8acfc9c5..00000000 --- a/src/async/smtp/MCSMTPAsyncSession.cc +++ /dev/null @@ -1,294 +0,0 @@ -#include "MCSMTPAsyncSession.h" - -#include "MCSMTPSession.h" -#include "MCSMTPLoginOperation.h" -#include "MCSMTPSendWithDataOperation.h" -#include "MCSMTPCheckAccountOperation.h" -#include "MCSMTPDisconnectOperation.h" -#include "MCSMTPNoopOperation.h" -#include "MCSMTPOperation.h" -#include "MCOperationQueueCallback.h" - -using namespace mailcore; - -namespace mailcore { - - class SMTPOperationQueueCallback : public Object, public OperationQueueCallback { - public: - SMTPOperationQueueCallback(SMTPAsyncSession * session) { - mSession = session; - } - - virtual ~SMTPOperationQueueCallback() { - } - - virtual void queueStartRunning() { - mSession->retain(); - } - - virtual void queueStoppedRunning() { - mSession->tryAutomaticDisconnect(); - mSession->release(); - } - - private: - SMTPAsyncSession * mSession; - }; - - class SMTPConnectionLogger : public Object, public ConnectionLogger { - public: - SMTPConnectionLogger(SMTPAsyncSession * session) { - mSession = session; - } - - virtual ~SMTPConnectionLogger() { - } - - virtual void log(void * sender, ConnectionLogType logType, Data * buffer) - { - mSession->logConnection(logType, buffer); - } - - private: - SMTPAsyncSession * mSession; - }; - -} - -SMTPAsyncSession::SMTPAsyncSession() -{ - mSession = new SMTPSession(); - 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); - MC_SAFE_RELEASE(mSession); -} - -void SMTPAsyncSession::setHostname(String * hostname) -{ - mSession->setHostname(hostname); -} - -String * SMTPAsyncSession::hostname() -{ - return mSession->hostname(); -} - -void SMTPAsyncSession::setPort(unsigned int port) -{ - mSession->setPort(port); -} - -unsigned int SMTPAsyncSession::port() -{ - return mSession->port(); -} - -void SMTPAsyncSession::setUsername(String * username) -{ - return mSession->setUsername(username); -} - -String * SMTPAsyncSession::username() -{ - return mSession->username(); -} - -void SMTPAsyncSession::setPassword(String * password) -{ - mSession->setPassword(password); -} - -String * SMTPAsyncSession::password() -{ - return mSession->password(); -} - -void SMTPAsyncSession::setOAuth2Token(String * token) -{ - mSession->setOAuth2Token(token); -} - -String * SMTPAsyncSession::OAuth2Token() -{ - return mSession->OAuth2Token(); -} - -void SMTPAsyncSession::setAuthType(AuthType authType) -{ - mSession->setAuthType(authType); -} - -AuthType SMTPAsyncSession::authType() -{ - return mSession->authType(); -} - -void SMTPAsyncSession::setConnectionType(ConnectionType connectionType) -{ - mSession->setConnectionType(connectionType); -} - -ConnectionType SMTPAsyncSession::connectionType() -{ - return mSession->connectionType(); -} - -void SMTPAsyncSession::setTimeout(time_t timeout) -{ - return mSession->setTimeout(timeout); -} - -time_t SMTPAsyncSession::timeout() -{ - return mSession->timeout(); -} - -void SMTPAsyncSession::setCheckCertificateEnabled(bool enabled) -{ - return mSession->setCheckCertificateEnabled(enabled); -} - -bool SMTPAsyncSession::isCheckCertificateEnabled() -{ - return mSession->isCheckCertificateEnabled(); -} - -void SMTPAsyncSession::setUseHeloIPEnabled(bool enabled) -{ - mSession->setUseHeloIPEnabled(enabled); -} - -bool SMTPAsyncSession::useHeloIPEnabled() -{ - return mSession->useHeloIPEnabled(); -} - -void SMTPAsyncSession::runOperation(SMTPOperation * operation) -{ - cancelDelayedPerformMethod((Object::Method) &SMTPAsyncSession::tryAutomaticDisconnectAfterDelay, NULL); - mQueue->addOperation(operation); -} - -SMTPSession * SMTPAsyncSession::session() -{ - return mSession; -} - -void SMTPAsyncSession::tryAutomaticDisconnect() -{ - // It's safe since no thread is running when this function is called. - if (mSession->isDisconnected()) { - return; - } - - cancelDelayedPerformMethod((Object::Method) &SMTPAsyncSession::tryAutomaticDisconnectAfterDelay, NULL); - performMethodAfterDelay((Object::Method) &SMTPAsyncSession::tryAutomaticDisconnectAfterDelay, NULL, 30); -} - -void SMTPAsyncSession::tryAutomaticDisconnectAfterDelay(void * context) -{ - SMTPDisconnectOperation * op = new SMTPDisconnectOperation(); - op->setSession(this); - op->autorelease(); - op->start(); -} - -SMTPOperation * SMTPAsyncSession::loginOperation() -{ - SMTPLoginOperation * op = new SMTPLoginOperation(); - op->setSession(this); - return (SMTPOperation *) op->autorelease(); -} - -SMTPOperation * SMTPAsyncSession::sendMessageOperation(Data * messageData) -{ - SMTPSendWithDataOperation * op = new SMTPSendWithDataOperation(); - op->setSession(this); - op->setMessageData(messageData); - return (SMTPOperation *) op->autorelease(); -} - -SMTPOperation * SMTPAsyncSession::sendMessageOperation(Address * from, Array * recipients, - Data * messageData) -{ - SMTPSendWithDataOperation * op = new SMTPSendWithDataOperation(); - op->setSession(this); - op->setMessageData(messageData); - op->setFrom(from); - op->setRecipients(recipients); - return (SMTPOperation *) op->autorelease(); -} - -SMTPOperation * SMTPAsyncSession::checkAccountOperation(Address * from) -{ - SMTPCheckAccountOperation * op = new SMTPCheckAccountOperation(); - op->setFrom(from); - op->setSession(this); - return (SMTPOperation *) op->autorelease(); -} - -SMTPOperation * SMTPAsyncSession::noopOperation() -{ - SMTPNoopOperation * op = new SMTPNoopOperation(); - 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); -} - -#if __APPLE__ -void SMTPAsyncSession::setDispatchQueue(dispatch_queue_t dispatchQueue) -{ - mQueue->setDispatchQueue(dispatchQueue); -} - -dispatch_queue_t SMTPAsyncSession::dispatchQueue() -{ - return mQueue->dispatchQueue(); -} -#endif diff --git a/src/async/smtp/MCSMTPAsyncSession.cpp b/src/async/smtp/MCSMTPAsyncSession.cpp new file mode 100644 index 00000000..8acfc9c5 --- /dev/null +++ b/src/async/smtp/MCSMTPAsyncSession.cpp @@ -0,0 +1,294 @@ +#include "MCSMTPAsyncSession.h" + +#include "MCSMTPSession.h" +#include "MCSMTPLoginOperation.h" +#include "MCSMTPSendWithDataOperation.h" +#include "MCSMTPCheckAccountOperation.h" +#include "MCSMTPDisconnectOperation.h" +#include "MCSMTPNoopOperation.h" +#include "MCSMTPOperation.h" +#include "MCOperationQueueCallback.h" + +using namespace mailcore; + +namespace mailcore { + + class SMTPOperationQueueCallback : public Object, public OperationQueueCallback { + public: + SMTPOperationQueueCallback(SMTPAsyncSession * session) { + mSession = session; + } + + virtual ~SMTPOperationQueueCallback() { + } + + virtual void queueStartRunning() { + mSession->retain(); + } + + virtual void queueStoppedRunning() { + mSession->tryAutomaticDisconnect(); + mSession->release(); + } + + private: + SMTPAsyncSession * mSession; + }; + + class SMTPConnectionLogger : public Object, public ConnectionLogger { + public: + SMTPConnectionLogger(SMTPAsyncSession * session) { + mSession = session; + } + + virtual ~SMTPConnectionLogger() { + } + + virtual void log(void * sender, ConnectionLogType logType, Data * buffer) + { + mSession->logConnection(logType, buffer); + } + + private: + SMTPAsyncSession * mSession; + }; + +} + +SMTPAsyncSession::SMTPAsyncSession() +{ + mSession = new SMTPSession(); + 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); + MC_SAFE_RELEASE(mSession); +} + +void SMTPAsyncSession::setHostname(String * hostname) +{ + mSession->setHostname(hostname); +} + +String * SMTPAsyncSession::hostname() +{ + return mSession->hostname(); +} + +void SMTPAsyncSession::setPort(unsigned int port) +{ + mSession->setPort(port); +} + +unsigned int SMTPAsyncSession::port() +{ + return mSession->port(); +} + +void SMTPAsyncSession::setUsername(String * username) +{ + return mSession->setUsername(username); +} + +String * SMTPAsyncSession::username() +{ + return mSession->username(); +} + +void SMTPAsyncSession::setPassword(String * password) +{ + mSession->setPassword(password); +} + +String * SMTPAsyncSession::password() +{ + return mSession->password(); +} + +void SMTPAsyncSession::setOAuth2Token(String * token) +{ + mSession->setOAuth2Token(token); +} + +String * SMTPAsyncSession::OAuth2Token() +{ + return mSession->OAuth2Token(); +} + +void SMTPAsyncSession::setAuthType(AuthType authType) +{ + mSession->setAuthType(authType); +} + +AuthType SMTPAsyncSession::authType() +{ + return mSession->authType(); +} + +void SMTPAsyncSession::setConnectionType(ConnectionType connectionType) +{ + mSession->setConnectionType(connectionType); +} + +ConnectionType SMTPAsyncSession::connectionType() +{ + return mSession->connectionType(); +} + +void SMTPAsyncSession::setTimeout(time_t timeout) +{ + return mSession->setTimeout(timeout); +} + +time_t SMTPAsyncSession::timeout() +{ + return mSession->timeout(); +} + +void SMTPAsyncSession::setCheckCertificateEnabled(bool enabled) +{ + return mSession->setCheckCertificateEnabled(enabled); +} + +bool SMTPAsyncSession::isCheckCertificateEnabled() +{ + return mSession->isCheckCertificateEnabled(); +} + +void SMTPAsyncSession::setUseHeloIPEnabled(bool enabled) +{ + mSession->setUseHeloIPEnabled(enabled); +} + +bool SMTPAsyncSession::useHeloIPEnabled() +{ + return mSession->useHeloIPEnabled(); +} + +void SMTPAsyncSession::runOperation(SMTPOperation * operation) +{ + cancelDelayedPerformMethod((Object::Method) &SMTPAsyncSession::tryAutomaticDisconnectAfterDelay, NULL); + mQueue->addOperation(operation); +} + +SMTPSession * SMTPAsyncSession::session() +{ + return mSession; +} + +void SMTPAsyncSession::tryAutomaticDisconnect() +{ + // It's safe since no thread is running when this function is called. + if (mSession->isDisconnected()) { + return; + } + + cancelDelayedPerformMethod((Object::Method) &SMTPAsyncSession::tryAutomaticDisconnectAfterDelay, NULL); + performMethodAfterDelay((Object::Method) &SMTPAsyncSession::tryAutomaticDisconnectAfterDelay, NULL, 30); +} + +void SMTPAsyncSession::tryAutomaticDisconnectAfterDelay(void * context) +{ + SMTPDisconnectOperation * op = new SMTPDisconnectOperation(); + op->setSession(this); + op->autorelease(); + op->start(); +} + +SMTPOperation * SMTPAsyncSession::loginOperation() +{ + SMTPLoginOperation * op = new SMTPLoginOperation(); + op->setSession(this); + return (SMTPOperation *) op->autorelease(); +} + +SMTPOperation * SMTPAsyncSession::sendMessageOperation(Data * messageData) +{ + SMTPSendWithDataOperation * op = new SMTPSendWithDataOperation(); + op->setSession(this); + op->setMessageData(messageData); + return (SMTPOperation *) op->autorelease(); +} + +SMTPOperation * SMTPAsyncSession::sendMessageOperation(Address * from, Array * recipients, + Data * messageData) +{ + SMTPSendWithDataOperation * op = new SMTPSendWithDataOperation(); + op->setSession(this); + op->setMessageData(messageData); + op->setFrom(from); + op->setRecipients(recipients); + return (SMTPOperation *) op->autorelease(); +} + +SMTPOperation * SMTPAsyncSession::checkAccountOperation(Address * from) +{ + SMTPCheckAccountOperation * op = new SMTPCheckAccountOperation(); + op->setFrom(from); + op->setSession(this); + return (SMTPOperation *) op->autorelease(); +} + +SMTPOperation * SMTPAsyncSession::noopOperation() +{ + SMTPNoopOperation * op = new SMTPNoopOperation(); + 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); +} + +#if __APPLE__ +void SMTPAsyncSession::setDispatchQueue(dispatch_queue_t dispatchQueue) +{ + mQueue->setDispatchQueue(dispatchQueue); +} + +dispatch_queue_t SMTPAsyncSession::dispatchQueue() +{ + return mQueue->dispatchQueue(); +} +#endif diff --git a/src/async/smtp/MCSMTPCheckAccountOperation.cc b/src/async/smtp/MCSMTPCheckAccountOperation.cc deleted file mode 100644 index f711c6ec..00000000 --- a/src/async/smtp/MCSMTPCheckAccountOperation.cc +++ /dev/null @@ -1,42 +0,0 @@ -// -// MCSMTPCheckAccountOperation.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/12/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCSMTPCheckAccountOperation.h" - -#include "MCSMTPAsyncSession.h" -#include "MCSMTPSession.h" - -using namespace mailcore; - -SMTPCheckAccountOperation::SMTPCheckAccountOperation() -{ - mFrom = NULL; -} - -SMTPCheckAccountOperation::~SMTPCheckAccountOperation() -{ - MC_SAFE_RELEASE(mFrom); -} - -void SMTPCheckAccountOperation::setFrom(Address * from) -{ - MC_SAFE_REPLACE_RETAIN(Address, mFrom, from); -} - -Address * SMTPCheckAccountOperation::from() -{ - return mFrom; -} - -void SMTPCheckAccountOperation::main() -{ - ErrorCode error; - - session()->session()->checkAccount(mFrom, &error); - setError(error); -} diff --git a/src/async/smtp/MCSMTPCheckAccountOperation.cpp b/src/async/smtp/MCSMTPCheckAccountOperation.cpp new file mode 100644 index 00000000..f711c6ec --- /dev/null +++ b/src/async/smtp/MCSMTPCheckAccountOperation.cpp @@ -0,0 +1,42 @@ +// +// MCSMTPCheckAccountOperation.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCSMTPCheckAccountOperation.h" + +#include "MCSMTPAsyncSession.h" +#include "MCSMTPSession.h" + +using namespace mailcore; + +SMTPCheckAccountOperation::SMTPCheckAccountOperation() +{ + mFrom = NULL; +} + +SMTPCheckAccountOperation::~SMTPCheckAccountOperation() +{ + MC_SAFE_RELEASE(mFrom); +} + +void SMTPCheckAccountOperation::setFrom(Address * from) +{ + MC_SAFE_REPLACE_RETAIN(Address, mFrom, from); +} + +Address * SMTPCheckAccountOperation::from() +{ + return mFrom; +} + +void SMTPCheckAccountOperation::main() +{ + ErrorCode error; + + session()->session()->checkAccount(mFrom, &error); + setError(error); +} diff --git a/src/async/smtp/MCSMTPDisconnectOperation.cc b/src/async/smtp/MCSMTPDisconnectOperation.cc deleted file mode 100644 index ba20567b..00000000 --- a/src/async/smtp/MCSMTPDisconnectOperation.cc +++ /dev/null @@ -1,28 +0,0 @@ -// -// SMTPDisconnectOperation.cpp -// mailcore2 -// -// Created by DINH Viêt Hoà on 6/22/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCSMTPDisconnectOperation.h" - -#include "MCSMTPAsyncSession.h" -#include "MCSMTPSession.h" - -using namespace mailcore; - -SMTPDisconnectOperation::SMTPDisconnectOperation() -{ -} - -SMTPDisconnectOperation::~SMTPDisconnectOperation() -{ -} - -void SMTPDisconnectOperation::main() -{ - session()->session()->disconnect(); - setError(ErrorNone); -} diff --git a/src/async/smtp/MCSMTPDisconnectOperation.cpp b/src/async/smtp/MCSMTPDisconnectOperation.cpp new file mode 100644 index 00000000..ba20567b --- /dev/null +++ b/src/async/smtp/MCSMTPDisconnectOperation.cpp @@ -0,0 +1,28 @@ +// +// SMTPDisconnectOperation.cpp +// mailcore2 +// +// Created by DINH Viêt Hoà on 6/22/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCSMTPDisconnectOperation.h" + +#include "MCSMTPAsyncSession.h" +#include "MCSMTPSession.h" + +using namespace mailcore; + +SMTPDisconnectOperation::SMTPDisconnectOperation() +{ +} + +SMTPDisconnectOperation::~SMTPDisconnectOperation() +{ +} + +void SMTPDisconnectOperation::main() +{ + session()->session()->disconnect(); + setError(ErrorNone); +} diff --git a/src/async/smtp/MCSMTPLoginOperation.cc b/src/async/smtp/MCSMTPLoginOperation.cc deleted file mode 100644 index 58866df9..00000000 --- a/src/async/smtp/MCSMTPLoginOperation.cc +++ /dev/null @@ -1,29 +0,0 @@ -// -// MCSMTPLoginOperation.cc -// mailcore2 -// -// Created by Hironori Yoshida on 10/29/14. -// Copyright (c) 2014 MailCore. All rights reserved. -// - -#include "MCSMTPLoginOperation.h" - -#include "MCSMTPAsyncSession.h" -#include "MCSMTPSession.h" - -using namespace mailcore; - -SMTPLoginOperation::SMTPLoginOperation() -{ -} - -SMTPLoginOperation::~SMTPLoginOperation() -{ -} - -void SMTPLoginOperation::main() -{ - ErrorCode error; - session()->session()->loginIfNeeded(&error); - setError(error); -} diff --git a/src/async/smtp/MCSMTPLoginOperation.cpp b/src/async/smtp/MCSMTPLoginOperation.cpp new file mode 100644 index 00000000..58866df9 --- /dev/null +++ b/src/async/smtp/MCSMTPLoginOperation.cpp @@ -0,0 +1,29 @@ +// +// MCSMTPLoginOperation.cc +// mailcore2 +// +// Created by Hironori Yoshida on 10/29/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#include "MCSMTPLoginOperation.h" + +#include "MCSMTPAsyncSession.h" +#include "MCSMTPSession.h" + +using namespace mailcore; + +SMTPLoginOperation::SMTPLoginOperation() +{ +} + +SMTPLoginOperation::~SMTPLoginOperation() +{ +} + +void SMTPLoginOperation::main() +{ + ErrorCode error; + session()->session()->loginIfNeeded(&error); + setError(error); +} diff --git a/src/async/smtp/MCSMTPNoopOperation.cc b/src/async/smtp/MCSMTPNoopOperation.cc deleted file mode 100644 index 310ccb8e..00000000 --- a/src/async/smtp/MCSMTPNoopOperation.cc +++ /dev/null @@ -1,29 +0,0 @@ -// -// MCSMTPNoopOperation.cc -// mailcore2 -// -// Created by Robert Widmann on 9/24/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCSMTPNoopOperation.h" - -#include "MCSMTPAsyncSession.h" -#include "MCSMTPSession.h" - -using namespace mailcore; - -SMTPNoopOperation::SMTPNoopOperation() -{ -} - -SMTPNoopOperation::~SMTPNoopOperation() -{ -} - -void SMTPNoopOperation::main() -{ - ErrorCode error; - session()->session()->noop(&error); - setError(error); -} diff --git a/src/async/smtp/MCSMTPNoopOperation.cpp b/src/async/smtp/MCSMTPNoopOperation.cpp new file mode 100644 index 00000000..310ccb8e --- /dev/null +++ b/src/async/smtp/MCSMTPNoopOperation.cpp @@ -0,0 +1,29 @@ +// +// MCSMTPNoopOperation.cc +// mailcore2 +// +// Created by Robert Widmann on 9/24/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCSMTPNoopOperation.h" + +#include "MCSMTPAsyncSession.h" +#include "MCSMTPSession.h" + +using namespace mailcore; + +SMTPNoopOperation::SMTPNoopOperation() +{ +} + +SMTPNoopOperation::~SMTPNoopOperation() +{ +} + +void SMTPNoopOperation::main() +{ + ErrorCode error; + session()->session()->noop(&error); + setError(error); +} diff --git a/src/async/smtp/MCSMTPOperation.cc b/src/async/smtp/MCSMTPOperation.cc deleted file mode 100644 index 9ddcede2..00000000 --- a/src/async/smtp/MCSMTPOperation.cc +++ /dev/null @@ -1,102 +0,0 @@ -// -// MCSMTPOperation.cpp -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/11/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCSMTPOperation.h" - -#include - -#include "MCSMTPAsyncSession.h" -#include "MCSMTPOperationCallback.h" - -using namespace mailcore; - -SMTPOperation::SMTPOperation() -{ - mSession = NULL; - mError = ErrorNone; -} - -SMTPOperation::~SMTPOperation() -{ - MC_SAFE_RELEASE(mSession); -} - -void SMTPOperation::setSession(SMTPAsyncSession * session) -{ - MC_SAFE_REPLACE_RETAIN(SMTPAsyncSession, mSession, session); -#if __APPLE__ - dispatch_queue_t queue; - if (session != NULL) { - queue = session->dispatchQueue(); - } - else { - queue = dispatch_get_main_queue(); - } - setCallbackDispatchQueue(queue); -#endif -} - -SMTPAsyncSession * SMTPOperation::session() -{ - return mSession; -} - -void SMTPOperation::start() -{ - mSession->runOperation(this); -} - -void SMTPOperation::setSmtpCallback(SMTPOperationCallback * callback) -{ - mSmtpCallback = callback; -} - -SMTPOperationCallback * SMTPOperation::smtpCallback() -{ - return mSmtpCallback; -} - -void SMTPOperation::setError(ErrorCode error) -{ - mError = error; -} - -ErrorCode SMTPOperation::error() -{ - return mError; -} - -struct progressContext { - unsigned int current; - unsigned int maximum; -}; - -void SMTPOperation::bodyProgress(SMTPSession * session, unsigned int current, unsigned int maximum) -{ - struct progressContext * context = (struct progressContext *) calloc(sizeof(* context), 1); - context->current = current; - context->maximum = maximum; - - retain(); - performMethodOnCallbackThread((Object::Method) &SMTPOperation::bodyProgressOnMainThread, context); -} - -void SMTPOperation::bodyProgressOnMainThread(void * ctx) -{ - if (isCancelled()) { - release(); - return; - } - - struct progressContext * context = (struct progressContext *) ctx; - if (mSmtpCallback != NULL) { - mSmtpCallback->bodyProgress(this, context->current, context->maximum); - } - free(context); - release(); -} diff --git a/src/async/smtp/MCSMTPOperation.cpp b/src/async/smtp/MCSMTPOperation.cpp new file mode 100644 index 00000000..9ddcede2 --- /dev/null +++ b/src/async/smtp/MCSMTPOperation.cpp @@ -0,0 +1,102 @@ +// +// MCSMTPOperation.cpp +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/11/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCSMTPOperation.h" + +#include + +#include "MCSMTPAsyncSession.h" +#include "MCSMTPOperationCallback.h" + +using namespace mailcore; + +SMTPOperation::SMTPOperation() +{ + mSession = NULL; + mError = ErrorNone; +} + +SMTPOperation::~SMTPOperation() +{ + MC_SAFE_RELEASE(mSession); +} + +void SMTPOperation::setSession(SMTPAsyncSession * session) +{ + MC_SAFE_REPLACE_RETAIN(SMTPAsyncSession, mSession, session); +#if __APPLE__ + dispatch_queue_t queue; + if (session != NULL) { + queue = session->dispatchQueue(); + } + else { + queue = dispatch_get_main_queue(); + } + setCallbackDispatchQueue(queue); +#endif +} + +SMTPAsyncSession * SMTPOperation::session() +{ + return mSession; +} + +void SMTPOperation::start() +{ + mSession->runOperation(this); +} + +void SMTPOperation::setSmtpCallback(SMTPOperationCallback * callback) +{ + mSmtpCallback = callback; +} + +SMTPOperationCallback * SMTPOperation::smtpCallback() +{ + return mSmtpCallback; +} + +void SMTPOperation::setError(ErrorCode error) +{ + mError = error; +} + +ErrorCode SMTPOperation::error() +{ + return mError; +} + +struct progressContext { + unsigned int current; + unsigned int maximum; +}; + +void SMTPOperation::bodyProgress(SMTPSession * session, unsigned int current, unsigned int maximum) +{ + struct progressContext * context = (struct progressContext *) calloc(sizeof(* context), 1); + context->current = current; + context->maximum = maximum; + + retain(); + performMethodOnCallbackThread((Object::Method) &SMTPOperation::bodyProgressOnMainThread, context); +} + +void SMTPOperation::bodyProgressOnMainThread(void * ctx) +{ + if (isCancelled()) { + release(); + return; + } + + struct progressContext * context = (struct progressContext *) ctx; + if (mSmtpCallback != NULL) { + mSmtpCallback->bodyProgress(this, context->current, context->maximum); + } + free(context); + release(); +} diff --git a/src/async/smtp/MCSMTPSendWithDataOperation.cc b/src/async/smtp/MCSMTPSendWithDataOperation.cc deleted file mode 100644 index 03f6a530..00000000 --- a/src/async/smtp/MCSMTPSendWithDataOperation.cc +++ /dev/null @@ -1,70 +0,0 @@ -// -// SMTPSendWithDataOperation.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 1/10/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCSMTPSendWithDataOperation.h" - -#include "MCSMTPAsyncSession.h" -#include "MCSMTPSession.h" - -using namespace mailcore; - -SMTPSendWithDataOperation::SMTPSendWithDataOperation() -{ - mMessageData = NULL; - mFrom = NULL; - mRecipients = NULL; -} - -SMTPSendWithDataOperation::~SMTPSendWithDataOperation() -{ - MC_SAFE_RELEASE(mFrom); - MC_SAFE_RELEASE(mRecipients); - MC_SAFE_RELEASE(mMessageData); -} - -void SMTPSendWithDataOperation::setMessageData(Data * data) -{ - MC_SAFE_REPLACE_RETAIN(Data, mMessageData, data); -} - -Data * SMTPSendWithDataOperation::messageData() -{ - return mMessageData; -} - -void SMTPSendWithDataOperation::setFrom(Address * from) -{ - MC_SAFE_REPLACE_COPY(Address, mFrom, from); -} - -Address * SMTPSendWithDataOperation::from() -{ - return mFrom; -} - -void SMTPSendWithDataOperation::setRecipients(Array * recipients) -{ - MC_SAFE_REPLACE_COPY(Array, mRecipients, recipients); -} - -Array * SMTPSendWithDataOperation::recipients() -{ - return mRecipients; -} - -void SMTPSendWithDataOperation::main() -{ - ErrorCode error; - if ((mFrom != NULL) && (mRecipients != NULL)) { - session()->session()->sendMessage(mFrom, mRecipients, mMessageData, this, &error); - } - else { - session()->session()->sendMessage(mMessageData, this, &error); - } - setError(error); -} diff --git a/src/async/smtp/MCSMTPSendWithDataOperation.cpp b/src/async/smtp/MCSMTPSendWithDataOperation.cpp new file mode 100644 index 00000000..03f6a530 --- /dev/null +++ b/src/async/smtp/MCSMTPSendWithDataOperation.cpp @@ -0,0 +1,70 @@ +// +// SMTPSendWithDataOperation.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/10/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCSMTPSendWithDataOperation.h" + +#include "MCSMTPAsyncSession.h" +#include "MCSMTPSession.h" + +using namespace mailcore; + +SMTPSendWithDataOperation::SMTPSendWithDataOperation() +{ + mMessageData = NULL; + mFrom = NULL; + mRecipients = NULL; +} + +SMTPSendWithDataOperation::~SMTPSendWithDataOperation() +{ + MC_SAFE_RELEASE(mFrom); + MC_SAFE_RELEASE(mRecipients); + MC_SAFE_RELEASE(mMessageData); +} + +void SMTPSendWithDataOperation::setMessageData(Data * data) +{ + MC_SAFE_REPLACE_RETAIN(Data, mMessageData, data); +} + +Data * SMTPSendWithDataOperation::messageData() +{ + return mMessageData; +} + +void SMTPSendWithDataOperation::setFrom(Address * from) +{ + MC_SAFE_REPLACE_COPY(Address, mFrom, from); +} + +Address * SMTPSendWithDataOperation::from() +{ + return mFrom; +} + +void SMTPSendWithDataOperation::setRecipients(Array * recipients) +{ + MC_SAFE_REPLACE_COPY(Array, mRecipients, recipients); +} + +Array * SMTPSendWithDataOperation::recipients() +{ + return mRecipients; +} + +void SMTPSendWithDataOperation::main() +{ + ErrorCode error; + if ((mFrom != NULL) && (mRecipients != NULL)) { + session()->session()->sendMessage(mFrom, mRecipients, mMessageData, this, &error); + } + else { + session()->session()->sendMessage(mMessageData, this, &error); + } + setError(error); +} diff --git a/src/cmake/async.cmake b/src/cmake/async.cmake index dc4a7243..2f6910f2 100644 --- a/src/cmake/async.cmake +++ b/src/cmake/async.cmake @@ -1,70 +1,70 @@ # Files to build set(async_imap_files - async/imap/MCIMAPAppendMessageOperation.cc - async/imap/MCIMAPAsyncConnection.cc - async/imap/MCIMAPAsyncSession.cc - async/imap/MCIMAPCapabilityOperation.cc - async/imap/MCIMAPCheckAccountOperation.cc - async/imap/MCIMAPConnectOperation.cc - async/imap/MCIMAPCopyMessagesOperation.cc - async/imap/MCIMAPCreateFolderOperation.cc - async/imap/MCIMAPDeleteFolderOperation.cc - async/imap/MCIMAPDisconnectOperation.cc - async/imap/MCIMAPExpungeOperation.cc - async/imap/MCIMAPFetchContentOperation.cc - async/imap/MCIMAPFetchParsedContentOperation.cc - async/imap/MCIMAPFetchFoldersOperation.cc - async/imap/MCIMAPFetchMessagesOperation.cc - async/imap/MCIMAPFetchNamespaceOperation.cc - async/imap/MCIMAPFolderInfoOperation.cc - async/imap/MCIMAPFolderStatusOperation.cc - async/imap/MCIMAPIdentityOperation.cc - async/imap/MCIMAPIdleOperation.cc - async/imap/MCIMAPMessageRenderingOperation.cc - async/imap/MCIMAPMultiDisconnectOperation.cc - async/imap/MCIMAPOperation.cc - async/imap/MCIMAPQuotaOperation.cc - async/imap/MCIMAPRenameFolderOperation.cc - async/imap/MCIMAPSearchOperation.cc - async/imap/MCIMAPStoreFlagsOperation.cc - async/imap/MCIMAPStoreLabelsOperation.cc - async/imap/MCIMAPSubscribeFolderOperation.cc - async/imap/MCIMAPNoopOperation.cc + async/imap/MCIMAPAppendMessageOperation.cpp + async/imap/MCIMAPAsyncConnection.cpp + async/imap/MCIMAPAsyncSession.cpp + async/imap/MCIMAPCapabilityOperation.cpp + async/imap/MCIMAPCheckAccountOperation.cpp + async/imap/MCIMAPConnectOperation.cpp + async/imap/MCIMAPCopyMessagesOperation.cpp + async/imap/MCIMAPCreateFolderOperation.cpp + async/imap/MCIMAPDeleteFolderOperation.cpp + async/imap/MCIMAPDisconnectOperation.cpp + async/imap/MCIMAPExpungeOperation.cpp + async/imap/MCIMAPFetchContentOperation.cpp + async/imap/MCIMAPFetchParsedContentOperation.cpp + async/imap/MCIMAPFetchFoldersOperation.cpp + async/imap/MCIMAPFetchMessagesOperation.cpp + async/imap/MCIMAPFetchNamespaceOperation.cpp + async/imap/MCIMAPFolderInfoOperation.cpp + async/imap/MCIMAPFolderStatusOperation.cpp + async/imap/MCIMAPIdentityOperation.cpp + async/imap/MCIMAPIdleOperation.cpp + async/imap/MCIMAPMessageRenderingOperation.cpp + async/imap/MCIMAPMultiDisconnectOperation.cpp + async/imap/MCIMAPOperation.cpp + async/imap/MCIMAPQuotaOperation.cpp + async/imap/MCIMAPRenameFolderOperation.cpp + async/imap/MCIMAPSearchOperation.cpp + async/imap/MCIMAPStoreFlagsOperation.cpp + async/imap/MCIMAPStoreLabelsOperation.cpp + async/imap/MCIMAPSubscribeFolderOperation.cpp + async/imap/MCIMAPNoopOperation.cpp ) set(async_pop_files - async/pop/MCPOPAsyncSession.cc - async/pop/MCPOPCheckAccountOperation.cc - async/pop/MCPOPDeleteMessagesOperation.cc - async/pop/MCPOPFetchHeaderOperation.cc - async/pop/MCPOPFetchMessageOperation.cc - async/pop/MCPOPFetchMessagesOperation.cc - async/pop/MCPOPNoopOperation.cc - async/pop/MCPOPOperation.cc + async/pop/MCPOPAsyncSession.cpp + async/pop/MCPOPCheckAccountOperation.cpp + async/pop/MCPOPDeleteMessagesOperation.cpp + async/pop/MCPOPFetchHeaderOperation.cpp + async/pop/MCPOPFetchMessageOperation.cpp + async/pop/MCPOPFetchMessagesOperation.cpp + async/pop/MCPOPNoopOperation.cpp + async/pop/MCPOPOperation.cpp ) set(async_smtp_files - async/smtp/MCSMTPAsyncSession.cc - async/smtp/MCSMTPCheckAccountOperation.cc - async/smtp/MCSMTPDisconnectOperation.cc - async/smtp/MCSMTPOperation.cc - async/smtp/MCSMTPLoginOperation.cc - async/smtp/MCSMTPSendWithDataOperation.cc - async/smtp/MCSMTPNoopOperation.cc + async/smtp/MCSMTPAsyncSession.cpp + async/smtp/MCSMTPCheckAccountOperation.cpp + async/smtp/MCSMTPDisconnectOperation.cpp + async/smtp/MCSMTPOperation.cpp + async/smtp/MCSMTPLoginOperation.cpp + async/smtp/MCSMTPSendWithDataOperation.cpp + async/smtp/MCSMTPNoopOperation.cpp ) set(async_nntp_files - async/nntp/MCNNTPAsyncSession.cc - async/nntp/MCNNTPCheckAccountOperation.cc - async/nntp/MCNNTPDisconnectOperation.cc - async/nntp/MCNNTPFetchArticleOperation.cc - async/nntp/MCNNTPFetchAllArticlesOperation.cc - async/nntp/MCNNTPFetchHeaderOperation.cc - async/nntp/MCNNTPListNewsgroupsOperation.cc - async/nntp/MCNNTPFetchOverviewOperation.cc - async/nntp/MCNNTPFetchServerTimeOperation.cc - async/nntp/MCNNTPOperation.cc + async/nntp/MCNNTPAsyncSession.cpp + async/nntp/MCNNTPCheckAccountOperation.cpp + async/nntp/MCNNTPDisconnectOperation.cpp + async/nntp/MCNNTPFetchArticleOperation.cpp + async/nntp/MCNNTPFetchAllArticlesOperation.cpp + async/nntp/MCNNTPFetchHeaderOperation.cpp + async/nntp/MCNNTPListNewsgroupsOperation.cpp + async/nntp/MCNNTPFetchOverviewOperation.cpp + async/nntp/MCNNTPFetchServerTimeOperation.cpp + async/nntp/MCNNTPOperation.cpp ) set(async_files diff --git a/src/cmake/core.cmake b/src/cmake/core.cmake index 989acb38..e8aa0185 100644 --- a/src/cmake/core.cmake +++ b/src/cmake/core.cmake @@ -1,12 +1,12 @@ # Files to build set(abstract_files - core/abstract/MCAbstractMessage.cc - core/abstract/MCAbstractMessagePart.cc - core/abstract/MCAbstractMultipart.cc - core/abstract/MCAbstractPart.cc - core/abstract/MCAddress.cc - core/abstract/MCMessageHeader.cc + core/abstract/MCAbstractMessage.cpp + core/abstract/MCAbstractMessagePart.cpp + core/abstract/MCAbstractMultipart.cpp + core/abstract/MCAbstractPart.cpp + core/abstract/MCAddress.cpp + core/abstract/MCMessageHeader.cpp ) IF(APPLE) @@ -27,97 +27,97 @@ ENDIF() set(basetypes_files - core/basetypes/MCArray.cc + core/basetypes/MCArray.cpp core/basetypes/MCAssert.c - core/basetypes/MCAutoreleasePool.cc + core/basetypes/MCAutoreleasePool.cpp core/basetypes/MCBase64.c - core/basetypes/MCConnectionLoggerUtils.cc - core/basetypes/MCData.cc - core/basetypes/MCHash.cc - core/basetypes/MCHashMap.cc - core/basetypes/MCHTMLCleaner.cc - core/basetypes/MCIndexSet.cc - core/basetypes/MCJSON.cc - core/basetypes/MCJSONParser.cc - core/basetypes/MCLibetpan.cc + core/basetypes/MCConnectionLoggerUtils.cpp + core/basetypes/MCData.cpp + core/basetypes/MCHash.cpp + core/basetypes/MCHashMap.cpp + core/basetypes/MCHTMLCleaner.cpp + core/basetypes/MCIndexSet.cpp + core/basetypes/MCJSON.cpp + core/basetypes/MCJSONParser.cpp + core/basetypes/MCLibetpan.cpp core/basetypes/MCLog.cpp - core/basetypes/MCMD5.cc - core/basetypes/MCNull.cc - core/basetypes/MCObject.cc - core/basetypes/MCOperation.cc - core/basetypes/MCOperationQueue.cc - core/basetypes/MCRange.cc - core/basetypes/MCSet.cc - core/basetypes/MCString.cc - core/basetypes/MCValue.cc + core/basetypes/MCMD5.cpp + core/basetypes/MCNull.cpp + core/basetypes/MCObject.cpp + core/basetypes/MCOperation.cpp + core/basetypes/MCOperationQueue.cpp + core/basetypes/MCRange.cpp + core/basetypes/MCSet.cpp + core/basetypes/MCString.cpp + core/basetypes/MCValue.cpp core/basetypes/ConvertUTF.c ${basetypes_files_apple} ${basetypes_files_linux} ) set(imap_files - core/imap/MCIMAPFolder.cc - core/imap/MCIMAPFolderStatus.cc - core/imap/MCIMAPIdentity.cc - core/imap/MCIMAPMessage.cc - core/imap/MCIMAPMessagePart.cc - core/imap/MCIMAPMultipart.cc - core/imap/MCIMAPNamespace.cc - core/imap/MCIMAPNamespaceItem.cc - core/imap/MCIMAPPart.cc - core/imap/MCIMAPSearchExpression.cc - core/imap/MCIMAPSession.cc - core/imap/MCIMAPSyncResult.cc + core/imap/MCIMAPFolder.cpp + core/imap/MCIMAPFolderStatus.cpp + core/imap/MCIMAPIdentity.cpp + core/imap/MCIMAPMessage.cpp + core/imap/MCIMAPMessagePart.cpp + core/imap/MCIMAPMultipart.cpp + core/imap/MCIMAPNamespace.cpp + core/imap/MCIMAPNamespaceItem.cpp + core/imap/MCIMAPPart.cpp + core/imap/MCIMAPSearchExpression.cpp + core/imap/MCIMAPSession.cpp + core/imap/MCIMAPSyncResult.cpp ) set(pop_files - core/pop/MCPOPMessageInfo.cc - core/pop/MCPOPSession.cc + core/pop/MCPOPMessageInfo.cpp + core/pop/MCPOPSession.cpp ) set(nntp_files - core/nntp/MCNNTPGroupInfo.cc - core/nntp/MCNNTPSession.cc + core/nntp/MCNNTPGroupInfo.cpp + core/nntp/MCNNTPSession.cpp ) set(provider_files - core/provider/MCMailProvider.cc - core/provider/MCMailProvidersManager.cc - core/provider/MCNetService.cc + core/provider/MCMailProvider.cpp + core/provider/MCMailProvidersManager.cpp + core/provider/MCNetService.cpp ) set(renderer_files - core/renderer/MCAddressDisplay.cc - core/renderer/MCDateFormatter.cc - core/renderer/MCHTMLBodyRendererTemplateCallback.cc - core/renderer/MCHTMLRenderer.cc - core/renderer/MCHTMLRendererCallback.cc - core/renderer/MCHTMLRendererIMAPDataCallback.cc - core/renderer/MCSizeFormatter.cc + core/renderer/MCAddressDisplay.cpp + core/renderer/MCDateFormatter.cpp + core/renderer/MCHTMLBodyRendererTemplateCallback.cpp + core/renderer/MCHTMLRenderer.cpp + core/renderer/MCHTMLRendererCallback.cpp + core/renderer/MCHTMLRendererIMAPDataCallback.cpp + core/renderer/MCSizeFormatter.cpp ) set(rfc822_files - core/rfc822/MCAttachment.cc - core/rfc822/MCMessageBuilder.cc - core/rfc822/MCMessageParser.cc - core/rfc822/MCMessagePart.cc - core/rfc822/MCMultipart.cc + core/rfc822/MCAttachment.cpp + core/rfc822/MCMessageBuilder.cpp + core/rfc822/MCMessageParser.cpp + core/rfc822/MCMessagePart.cpp + core/rfc822/MCMultipart.cpp ) set(smtp_files - core/smtp/MCSMTPSession.cc + core/smtp/MCSMTPSession.cpp ) set(zip_files - core/zip/MCZip.cc + core/zip/MCZip.cpp core/zip/MiniZip/ioapi.c core/zip/MiniZip/unzip.c core/zip/MiniZip/zip.c ) set(security_files - core/security/MCCertificateUtils.cc + core/security/MCCertificateUtils.cpp ) set(core_files diff --git a/src/core/abstract/MCAbstractMessage.cc b/src/core/abstract/MCAbstractMessage.cc deleted file mode 100644 index 1d1d7efc..00000000 --- a/src/core/abstract/MCAbstractMessage.cc +++ /dev/null @@ -1,100 +0,0 @@ -#include "MCAbstractMessage.h" - -#include "MCMessageHeader.h" -#include "MCHTMLRenderer.h" - -using namespace mailcore; - -AbstractMessage::AbstractMessage() -{ - init(); -} - -AbstractMessage::AbstractMessage(AbstractMessage * other) -{ - init(); - mHeader = (MessageHeader *) MC_SAFE_COPY(other->mHeader); -} - -void AbstractMessage::init() -{ - mHeader = NULL; -} - -AbstractMessage::~AbstractMessage() -{ - MC_SAFE_RELEASE(mHeader); -} - -String * AbstractMessage::description() -{ - if (mHeader != NULL) { - String * result = String::string(); - result->appendUTF8Format("<%s:%p\n", className()->UTF8Characters(), this); - result->appendString(mHeader->description()); - result->appendUTF8Characters(">"); - return result; - } - else { - return Object::description(); - } -} - -Object * AbstractMessage::copy() -{ - return new AbstractMessage(this); -} - -MessageHeader * AbstractMessage::header() -{ - if (mHeader == NULL) { - mHeader = new MessageHeader(); - } - return mHeader; -} - -void AbstractMessage::setHeader(MessageHeader * header) -{ - MC_SAFE_REPLACE_RETAIN(MessageHeader, mHeader, header); -} - -AbstractPart * AbstractMessage::partForContentID(String * contentID) -{ - MCAssert(0); - return NULL; -} - -AbstractPart * AbstractMessage::partForUniqueID(String * uniqueID) -{ - MCAssert(0); - return NULL; -} - -Array * AbstractMessage::attachments() -{ - return HTMLRenderer::attachmentsForMessage(this); -} - -Array * AbstractMessage::htmlInlineAttachments() -{ - return HTMLRenderer::htmlInlineAttachmentsForMessage(this); -} - -Array * AbstractMessage::requiredPartsForRendering() -{ - return HTMLRenderer::requiredPartsForRendering(this); -} - -HashMap * AbstractMessage::serializable() -{ - HashMap * result = Object::serializable(); - if (header() != NULL) { - result->setObjectForKey(MCSTR("header"), mHeader->serializable()); - } - return result; -} - -void AbstractMessage::importSerializable(HashMap * hashmap) -{ - setHeader((MessageHeader *) Object::objectWithSerializable((HashMap *) hashmap->objectForKey(MCSTR("header")))); -} diff --git a/src/core/abstract/MCAbstractMessage.cpp b/src/core/abstract/MCAbstractMessage.cpp new file mode 100644 index 00000000..1d1d7efc --- /dev/null +++ b/src/core/abstract/MCAbstractMessage.cpp @@ -0,0 +1,100 @@ +#include "MCAbstractMessage.h" + +#include "MCMessageHeader.h" +#include "MCHTMLRenderer.h" + +using namespace mailcore; + +AbstractMessage::AbstractMessage() +{ + init(); +} + +AbstractMessage::AbstractMessage(AbstractMessage * other) +{ + init(); + mHeader = (MessageHeader *) MC_SAFE_COPY(other->mHeader); +} + +void AbstractMessage::init() +{ + mHeader = NULL; +} + +AbstractMessage::~AbstractMessage() +{ + MC_SAFE_RELEASE(mHeader); +} + +String * AbstractMessage::description() +{ + if (mHeader != NULL) { + String * result = String::string(); + result->appendUTF8Format("<%s:%p\n", className()->UTF8Characters(), this); + result->appendString(mHeader->description()); + result->appendUTF8Characters(">"); + return result; + } + else { + return Object::description(); + } +} + +Object * AbstractMessage::copy() +{ + return new AbstractMessage(this); +} + +MessageHeader * AbstractMessage::header() +{ + if (mHeader == NULL) { + mHeader = new MessageHeader(); + } + return mHeader; +} + +void AbstractMessage::setHeader(MessageHeader * header) +{ + MC_SAFE_REPLACE_RETAIN(MessageHeader, mHeader, header); +} + +AbstractPart * AbstractMessage::partForContentID(String * contentID) +{ + MCAssert(0); + return NULL; +} + +AbstractPart * AbstractMessage::partForUniqueID(String * uniqueID) +{ + MCAssert(0); + return NULL; +} + +Array * AbstractMessage::attachments() +{ + return HTMLRenderer::attachmentsForMessage(this); +} + +Array * AbstractMessage::htmlInlineAttachments() +{ + return HTMLRenderer::htmlInlineAttachmentsForMessage(this); +} + +Array * AbstractMessage::requiredPartsForRendering() +{ + return HTMLRenderer::requiredPartsForRendering(this); +} + +HashMap * AbstractMessage::serializable() +{ + HashMap * result = Object::serializable(); + if (header() != NULL) { + result->setObjectForKey(MCSTR("header"), mHeader->serializable()); + } + return result; +} + +void AbstractMessage::importSerializable(HashMap * hashmap) +{ + setHeader((MessageHeader *) Object::objectWithSerializable((HashMap *) hashmap->objectForKey(MCSTR("header")))); +} diff --git a/src/core/abstract/MCAbstractMessagePart.cc b/src/core/abstract/MCAbstractMessagePart.cc deleted file mode 100644 index 65d7b8cc..00000000 --- a/src/core/abstract/MCAbstractMessagePart.cc +++ /dev/null @@ -1,98 +0,0 @@ -#include "MCAbstractMessagePart.h" - -#include "MCMessageHeader.h" - -using namespace mailcore; - -void AbstractMessagePart::init() -{ - mMainPart = NULL; - mHeader = NULL; - setPartType(PartTypeMessage); -} - -AbstractMessagePart::AbstractMessagePart() -{ - init(); -} - -AbstractMessagePart::AbstractMessagePart(AbstractMessagePart * other) : AbstractPart(other) -{ - init(); - if (other->mainPart() != NULL) { - setMainPart((AbstractPart *) other->mainPart()->copy()->autorelease()); - } - if (other->mHeader != NULL) { - setHeader((MessageHeader *) other->header()->copy()->autorelease()); - } -} - -AbstractMessagePart::~AbstractMessagePart() -{ - MC_SAFE_RELEASE(mMainPart); - MC_SAFE_RELEASE(mHeader); -} - -String * AbstractMessagePart::description() -{ - String * result = String::string(); - result->appendUTF8Format("<%s:%p %s>", className()->UTF8Characters(), this, mMainPart->description()->UTF8Characters()); - return result; -} - -Object * AbstractMessagePart::copy() -{ - return new AbstractMessagePart(this); -} - -MessageHeader * AbstractMessagePart::header() -{ - if (mHeader == NULL) { - mHeader = new MessageHeader(); - } - return mHeader; -} - -void AbstractMessagePart::setHeader(MessageHeader * header) -{ - MC_SAFE_REPLACE_RETAIN(MessageHeader, mHeader, header); -} - -AbstractPart * AbstractMessagePart::mainPart() -{ - return mMainPart; -} - -void AbstractMessagePart::setMainPart(AbstractPart * mainPart) -{ - MC_SAFE_REPLACE_RETAIN(AbstractPart, mMainPart, mainPart); -} - -AbstractPart * AbstractMessagePart::partForContentID(String * contentID) -{ - return mainPart()->partForContentID(contentID); -} - -AbstractPart * AbstractMessagePart::partForUniqueID(String * contentID) -{ - return mainPart()->partForUniqueID(contentID); -} - -HashMap * AbstractMessagePart::serializable() -{ - HashMap * result = (HashMap *) AbstractPart::serializable(); - if (mainPart() != NULL) { - result->setObjectForKey(MCSTR("mainPart"), mainPart()->serializable()); - } - if (header() != NULL) { - result->setObjectForKey(MCSTR("header"), header()->serializable()); - } - return result; -} - -void AbstractMessagePart::importSerializable(HashMap * serializable) -{ - AbstractPart::importSerializable(serializable); - setMainPart((AbstractPart *) Object::objectWithSerializable((HashMap *) serializable->objectForKey(MCSTR("mainPart")))); - setHeader((MessageHeader *) Object::objectWithSerializable((HashMap *) serializable->objectForKey(MCSTR("header")))); -} diff --git a/src/core/abstract/MCAbstractMessagePart.cpp b/src/core/abstract/MCAbstractMessagePart.cpp new file mode 100644 index 00000000..65d7b8cc --- /dev/null +++ b/src/core/abstract/MCAbstractMessagePart.cpp @@ -0,0 +1,98 @@ +#include "MCAbstractMessagePart.h" + +#include "MCMessageHeader.h" + +using namespace mailcore; + +void AbstractMessagePart::init() +{ + mMainPart = NULL; + mHeader = NULL; + setPartType(PartTypeMessage); +} + +AbstractMessagePart::AbstractMessagePart() +{ + init(); +} + +AbstractMessagePart::AbstractMessagePart(AbstractMessagePart * other) : AbstractPart(other) +{ + init(); + if (other->mainPart() != NULL) { + setMainPart((AbstractPart *) other->mainPart()->copy()->autorelease()); + } + if (other->mHeader != NULL) { + setHeader((MessageHeader *) other->header()->copy()->autorelease()); + } +} + +AbstractMessagePart::~AbstractMessagePart() +{ + MC_SAFE_RELEASE(mMainPart); + MC_SAFE_RELEASE(mHeader); +} + +String * AbstractMessagePart::description() +{ + String * result = String::string(); + result->appendUTF8Format("<%s:%p %s>", className()->UTF8Characters(), this, mMainPart->description()->UTF8Characters()); + return result; +} + +Object * AbstractMessagePart::copy() +{ + return new AbstractMessagePart(this); +} + +MessageHeader * AbstractMessagePart::header() +{ + if (mHeader == NULL) { + mHeader = new MessageHeader(); + } + return mHeader; +} + +void AbstractMessagePart::setHeader(MessageHeader * header) +{ + MC_SAFE_REPLACE_RETAIN(MessageHeader, mHeader, header); +} + +AbstractPart * AbstractMessagePart::mainPart() +{ + return mMainPart; +} + +void AbstractMessagePart::setMainPart(AbstractPart * mainPart) +{ + MC_SAFE_REPLACE_RETAIN(AbstractPart, mMainPart, mainPart); +} + +AbstractPart * AbstractMessagePart::partForContentID(String * contentID) +{ + return mainPart()->partForContentID(contentID); +} + +AbstractPart * AbstractMessagePart::partForUniqueID(String * contentID) +{ + return mainPart()->partForUniqueID(contentID); +} + +HashMap * AbstractMessagePart::serializable() +{ + HashMap * result = (HashMap *) AbstractPart::serializable(); + if (mainPart() != NULL) { + result->setObjectForKey(MCSTR("mainPart"), mainPart()->serializable()); + } + if (header() != NULL) { + result->setObjectForKey(MCSTR("header"), header()->serializable()); + } + return result; +} + +void AbstractMessagePart::importSerializable(HashMap * serializable) +{ + AbstractPart::importSerializable(serializable); + setMainPart((AbstractPart *) Object::objectWithSerializable((HashMap *) serializable->objectForKey(MCSTR("mainPart")))); + setHeader((MessageHeader *) Object::objectWithSerializable((HashMap *) serializable->objectForKey(MCSTR("header")))); +} diff --git a/src/core/abstract/MCAbstractMultipart.cc b/src/core/abstract/MCAbstractMultipart.cc deleted file mode 100644 index d46a0c75..00000000 --- a/src/core/abstract/MCAbstractMultipart.cc +++ /dev/null @@ -1,111 +0,0 @@ -#include "MCAbstractMultipart.h" - -using namespace mailcore; - -AbstractMultipart::AbstractMultipart() -{ - init(); -} - -AbstractMultipart::AbstractMultipart(AbstractMultipart * other) : AbstractPart(other) -{ - init(); - - setPartType(other->partType()); - Array * parts = Array::array(); - for(unsigned int i = 0 ; i < other->parts()->count() ; i ++) { - AbstractPart * part = (AbstractPart *) other->parts()->objectAtIndex(i); - parts->addObject(part->copy()->autorelease()); - } - setParts(parts); -} - -void AbstractMultipart::init() -{ - mParts = NULL; - setPartType(PartTypeMultipartMixed); -} - -AbstractMultipart::~AbstractMultipart() -{ - MC_SAFE_RELEASE(mParts); -} - -Array * AbstractMultipart::parts() -{ - return mParts; -} - -void AbstractMultipart::setParts(Array * parts) -{ - MC_SAFE_REPLACE_COPY(Array, mParts, parts); -} - -String * AbstractMultipart::description() -{ - String * result = String::string(); - - const char * partTypeName = NULL; - switch (partType()) { - default: - case PartTypeMultipartMixed: - partTypeName = "mixed"; - break; - case PartTypeMultipartRelated: - partTypeName = "related"; - break; - case PartTypeMultipartAlternative: - partTypeName = "alternative"; - break; - case PartTypeMultipartSigned: - partTypeName = "signed"; - break; - } - - result->appendUTF8Format("<%s:%p %s %s>", - MCUTF8(className()), this, partTypeName, MCUTF8(mParts->description())); - return result; -} - -Object * AbstractMultipart::copy() -{ - return new AbstractMultipart(this); -} - -AbstractPart * AbstractMultipart::partForContentID(String * contentID) -{ - for(unsigned int i = 0 ; i < parts()->count() ; i ++) { - mailcore::AbstractPart * subpart = (mailcore::AbstractPart *) parts()->objectAtIndex(i); - mailcore::AbstractPart * result = subpart->partForContentID(contentID); - if (result != NULL) - return result; - } - return NULL; -} - - -AbstractPart * AbstractMultipart::partForUniqueID(String * uniqueID) -{ - for(unsigned int i = 0 ; i < parts()->count() ; i ++) { - mailcore::AbstractPart * subpart = (mailcore::AbstractPart *) parts()->objectAtIndex(i); - mailcore::AbstractPart * result = subpart->partForUniqueID(uniqueID); - if (result != NULL) - return result; - } - return NULL; -} - -HashMap * AbstractMultipart::serializable() -{ - HashMap * result = (HashMap *) AbstractPart::serializable(); - if (mParts != NULL) { - result->setObjectForKey(MCSTR("parts"), mParts->serializable()); - } - return result; -} - -void AbstractMultipart::importSerializable(HashMap * serializable) -{ - AbstractPart::importSerializable(serializable); - setParts((Array *) Object::objectWithSerializable((HashMap *) serializable->objectForKey(MCSTR("parts")))); -} diff --git a/src/core/abstract/MCAbstractMultipart.cpp b/src/core/abstract/MCAbstractMultipart.cpp new file mode 100644 index 00000000..d46a0c75 --- /dev/null +++ b/src/core/abstract/MCAbstractMultipart.cpp @@ -0,0 +1,111 @@ +#include "MCAbstractMultipart.h" + +using namespace mailcore; + +AbstractMultipart::AbstractMultipart() +{ + init(); +} + +AbstractMultipart::AbstractMultipart(AbstractMultipart * other) : AbstractPart(other) +{ + init(); + + setPartType(other->partType()); + Array * parts = Array::array(); + for(unsigned int i = 0 ; i < other->parts()->count() ; i ++) { + AbstractPart * part = (AbstractPart *) other->parts()->objectAtIndex(i); + parts->addObject(part->copy()->autorelease()); + } + setParts(parts); +} + +void AbstractMultipart::init() +{ + mParts = NULL; + setPartType(PartTypeMultipartMixed); +} + +AbstractMultipart::~AbstractMultipart() +{ + MC_SAFE_RELEASE(mParts); +} + +Array * AbstractMultipart::parts() +{ + return mParts; +} + +void AbstractMultipart::setParts(Array * parts) +{ + MC_SAFE_REPLACE_COPY(Array, mParts, parts); +} + +String * AbstractMultipart::description() +{ + String * result = String::string(); + + const char * partTypeName = NULL; + switch (partType()) { + default: + case PartTypeMultipartMixed: + partTypeName = "mixed"; + break; + case PartTypeMultipartRelated: + partTypeName = "related"; + break; + case PartTypeMultipartAlternative: + partTypeName = "alternative"; + break; + case PartTypeMultipartSigned: + partTypeName = "signed"; + break; + } + + result->appendUTF8Format("<%s:%p %s %s>", + MCUTF8(className()), this, partTypeName, MCUTF8(mParts->description())); + return result; +} + +Object * AbstractMultipart::copy() +{ + return new AbstractMultipart(this); +} + +AbstractPart * AbstractMultipart::partForContentID(String * contentID) +{ + for(unsigned int i = 0 ; i < parts()->count() ; i ++) { + mailcore::AbstractPart * subpart = (mailcore::AbstractPart *) parts()->objectAtIndex(i); + mailcore::AbstractPart * result = subpart->partForContentID(contentID); + if (result != NULL) + return result; + } + return NULL; +} + + +AbstractPart * AbstractMultipart::partForUniqueID(String * uniqueID) +{ + for(unsigned int i = 0 ; i < parts()->count() ; i ++) { + mailcore::AbstractPart * subpart = (mailcore::AbstractPart *) parts()->objectAtIndex(i); + mailcore::AbstractPart * result = subpart->partForUniqueID(uniqueID); + if (result != NULL) + return result; + } + return NULL; +} + +HashMap * AbstractMultipart::serializable() +{ + HashMap * result = (HashMap *) AbstractPart::serializable(); + if (mParts != NULL) { + result->setObjectForKey(MCSTR("parts"), mParts->serializable()); + } + return result; +} + +void AbstractMultipart::importSerializable(HashMap * serializable) +{ + AbstractPart::importSerializable(serializable); + setParts((Array *) Object::objectWithSerializable((HashMap *) serializable->objectForKey(MCSTR("parts")))); +} diff --git a/src/core/abstract/MCAbstractPart.cc b/src/core/abstract/MCAbstractPart.cc deleted file mode 100644 index 783d47a9..00000000 --- a/src/core/abstract/MCAbstractPart.cc +++ /dev/null @@ -1,451 +0,0 @@ -#include "MCWin32.h" // should be first include. - -#include "MCAbstractPart.h" - -#include -#include -#include -#include "MCData.h" -#include "MCAbstractMessagePart.h" -#include "MCAbstractMultipart.h" -#include "MCArray.h" - -using namespace mailcore; - -AbstractPart::AbstractPart() -{ - init(); -} - -AbstractPart::AbstractPart(AbstractPart * other) -{ - init(); - setUniqueID(other->mUniqueID); - setFilename(other->mFilename); - setMimeType(other->mMimeType); - setCharset(other->mCharset); - setContentID(other->mContentID); - setContentLocation(other->mContentLocation); - setContentDescription(other->mContentDescription); - setInlineAttachment(other->mInlineAttachment); - setPartType(other->mPartType); - setContentTypeParameters(other->mContentTypeParameters); -} - -void AbstractPart::init() -{ - mUniqueID = NULL; - mFilename = NULL; - mMimeType = NULL; - mCharset = NULL; - mContentID = NULL; - mContentLocation = NULL; - mContentDescription = NULL; - mInlineAttachment = false; - mPartType = PartTypeSingle; - mContentTypeParameters = NULL; -} - -AbstractPart::~AbstractPart() -{ - MC_SAFE_RELEASE(mUniqueID); - MC_SAFE_RELEASE(mFilename); - MC_SAFE_RELEASE(mMimeType); - MC_SAFE_RELEASE(mCharset); - MC_SAFE_RELEASE(mContentID); - MC_SAFE_RELEASE(mContentLocation); - MC_SAFE_RELEASE(mContentDescription); - MC_SAFE_RELEASE(mContentTypeParameters); -} - -String * AbstractPart::description() -{ - String * result = String::string(); - result->appendUTF8Format("<%s:%p\n", className()->UTF8Characters(), this); - if (mFilename != NULL) { - result->appendUTF8Format("filename: %s\n", mFilename->UTF8Characters()); - } - if (mMimeType != NULL) { - result->appendUTF8Format("mime type: %s\n", mMimeType->UTF8Characters()); - } - if (mCharset != NULL) { - result->appendUTF8Format("charset: %s\n", mCharset->UTF8Characters()); - } - if (mContentID != NULL) { - result->appendUTF8Format("content-ID: %s\n", mContentID->UTF8Characters()); - } - if (mContentLocation != NULL) { - result->appendUTF8Format("content-location: %s\n", mContentLocation->UTF8Characters()); - } - if (mContentDescription != NULL) { - result->appendUTF8Format("content-description: %s\n", mContentDescription->UTF8Characters()); - } - result->appendUTF8Format("inline: %i\n", mInlineAttachment); - if (mContentTypeParameters != NULL) { - mc_foreachhashmapKeyAndValue(String, key, String, value, mContentTypeParameters) { - result->appendUTF8Format("%s: %s\n", key->UTF8Characters(), value->UTF8Characters()); - } - } - result->appendUTF8Format(">"); - - return result; -} - -Object * AbstractPart::copy() -{ - return new AbstractPart(this); -} - -PartType AbstractPart::partType() -{ - return mPartType; -} - -void AbstractPart::setPartType(PartType type) -{ - mPartType = type; -} - -String * AbstractPart::uniqueID() -{ - return mUniqueID; -} - -void AbstractPart::setUniqueID(String * uniqueID) -{ - MC_SAFE_REPLACE_COPY(String, mUniqueID, uniqueID); -} - -String * AbstractPart::filename() -{ - return mFilename; -} - -void AbstractPart::setFilename(String * filename) -{ - MC_SAFE_REPLACE_COPY(String, mFilename, filename); -} - -String * AbstractPart::mimeType() -{ - return mMimeType; -} - -void AbstractPart::setMimeType(String * mimeType) -{ - MC_SAFE_REPLACE_COPY(String, mMimeType, mimeType); -} - -String * AbstractPart::charset() -{ - return mCharset; -} - -void AbstractPart::setCharset(String * charset) -{ - MC_SAFE_REPLACE_COPY(String, mCharset, charset); -} - -String * AbstractPart::contentID() -{ - return mContentID; -} - -void AbstractPart::setContentID(String * contentID) -{ - MC_SAFE_REPLACE_COPY(String, mContentID, contentID); -} - -String * AbstractPart::contentLocation() -{ - return mContentLocation; -} - -void AbstractPart::setContentLocation(String * contentLocation) -{ - MC_SAFE_REPLACE_COPY(String, mContentLocation, contentLocation); -} - -String * AbstractPart::contentDescription() -{ - return mContentDescription; -} - -void AbstractPart::setContentDescription(String * contentDescription) -{ - MC_SAFE_REPLACE_COPY(String, mContentDescription, contentDescription); -} - -bool AbstractPart::isInlineAttachment() -{ - return mInlineAttachment; -} - -void AbstractPart::setInlineAttachment(bool inlineAttachment) -{ - mInlineAttachment = inlineAttachment; -} - -void AbstractPart::importIMAPFields(struct mailimap_body_fields * fields, - struct mailimap_body_ext_1part * extension) -{ - if (fields->bd_parameter != NULL) { - clistiter * cur; - - for(cur = clist_begin(fields->bd_parameter->pa_list) ; cur != NULL ; - cur = clist_next(cur)) { - struct mailimap_single_body_fld_param * imap_param; - - imap_param = (struct mailimap_single_body_fld_param *) clist_content(cur); - - if (strcasecmp(imap_param->pa_name, "name") == 0) { - setFilename(String::stringByDecodingMIMEHeaderValue(imap_param->pa_value)); - } - else if (strcasecmp(imap_param->pa_name, "charset") == 0) { - setCharset(String::stringByDecodingMIMEHeaderValue(imap_param->pa_value)); - } - } - } - if (fields->bd_id != NULL) { - char * contentid; - size_t cur_token; - int r; - - cur_token = 0; - r = mailimf_msg_id_parse(fields->bd_id, strlen(fields->bd_id), - &cur_token, &contentid); - if (r == MAILIMF_NO_ERROR) { - // msg id - setContentID(String::stringWithUTF8Characters(contentid)); - free(contentid); - } - } - if (fields->bd_description != NULL) { - setContentDescription(String::stringWithUTF8Characters(fields->bd_description)); - } - - if (extension != NULL) { - if (extension->bd_disposition != NULL) { - if (strcasecmp(extension->bd_disposition->dsp_type, "inline") == 0) { - setInlineAttachment(true); - } - - if (extension->bd_disposition->dsp_attributes != NULL) { - clistiter * cur; - - for(cur = clist_begin(extension->bd_disposition->dsp_attributes->pa_list) ; cur != NULL ; - cur = clist_next(cur)) { - struct mailimap_single_body_fld_param * imap_param; - - imap_param = (struct mailimap_single_body_fld_param *) clist_content(cur); - - if (strcasecmp(imap_param->pa_name, "filename") == 0) { - setFilename(String::stringByDecodingMIMEHeaderValue(imap_param->pa_value)); - } - } - } - } - - if (extension->bd_loc != NULL) { - setContentLocation(String::stringWithUTF8Characters(extension->bd_loc)); - } - } -} - -AbstractPart * AbstractPart::partForContentID(String * contentID) -{ - if (contentID->isEqual(mContentID)) { - return this; - } - else { - return NULL; - } -} - -AbstractPart * AbstractPart::partForUniqueID(String * uniqueID) -{ - if (uniqueID->isEqual(mUniqueID)) { - return this; - } - else { - return NULL; - } -} - -String * AbstractPart::decodedStringForData(Data * data) -{ - String *lowerMimeType = mMimeType ? mMimeType->lowercaseString() : NULL; - - if (lowerMimeType && lowerMimeType->hasPrefix(MCSTR("text/"))) { - bool isHTML = lowerMimeType->isEqual(MCSTR("text/html")); - return data->stringWithDetectedCharset(mCharset, isHTML); - } - else { - return NULL; - } -} - -void AbstractPart::applyUniquePartID() -{ - Array * queue = new Array(); - queue->addObject(this); - unsigned int queueIndex = 0; - unsigned int identifier = 0; - while (queueIndex < queue->count()) { - AbstractPart * part = (AbstractPart *) queue->objectAtIndex(queueIndex); - switch (part->partType()) { - case PartTypeSingle: - part->setUniqueID(String::stringWithUTF8Format("%u", identifier)); - identifier ++; - break; - case PartTypeMessage: - queue->addObject(((AbstractMessagePart *) part)->mainPart()); - break; - case PartTypeMultipartMixed: - case PartTypeMultipartRelated: - case PartTypeMultipartAlternative: - case PartTypeMultipartSigned: - queue->addObjectsFromArray(((AbstractMultipart *) part)->parts()); - break; - } - queueIndex ++; - } - queue->release(); -} - -HashMap * AbstractPart::serializable() -{ - HashMap * result = Object::serializable(); - - if (uniqueID() != NULL) { - result->setObjectForKey(MCSTR("uniqueID"), uniqueID()); - } - if (filename() != NULL) { - result->setObjectForKey(MCSTR("filename"), filename()); - } - if (mimeType() != NULL) { - result->setObjectForKey(MCSTR("mimeType"), mimeType()); - } - if (charset() != NULL) { - result->setObjectForKey(MCSTR("charset"), charset()); - } - if (contentID() != NULL) { - result->setObjectForKey(MCSTR("contentID"), contentID()); - } - if (contentLocation() != NULL) { - result->setObjectForKey(MCSTR("contentLocation"), contentLocation()); - } - if (contentDescription() != NULL) { - result->setObjectForKey(MCSTR("contentDescription"), contentDescription()); - } - if (mInlineAttachment) { - result->setObjectForKey(MCSTR("inlineAttachment"), MCSTR("1")); - } - String * partTypeStr; - switch (mPartType) { - default: - case PartTypeSingle: - partTypeStr = MCSTR("single"); - break; - case PartTypeMessage: - partTypeStr = MCSTR("message"); - break; - case PartTypeMultipartMixed: - partTypeStr = MCSTR("multipart/mixed"); - break; - case PartTypeMultipartRelated: - partTypeStr = MCSTR("multipart/related"); - break; - case PartTypeMultipartAlternative: - partTypeStr = MCSTR("multipart/alternative"); - break; - case PartTypeMultipartSigned: - partTypeStr = MCSTR("multipart/signed"); - break; - } - result->setObjectForKey(MCSTR("partType"), partTypeStr); - - return result; -} - -void AbstractPart::importSerializable(HashMap * serializable) -{ - setUniqueID((String *) serializable->objectForKey(MCSTR("uniqueID"))); - setFilename((String *) serializable->objectForKey(MCSTR("filename"))); - setMimeType((String *) serializable->objectForKey(MCSTR("mimeType"))); - setCharset((String *) serializable->objectForKey(MCSTR("charset"))); - setContentID((String *) serializable->objectForKey(MCSTR("contentID"))); - setContentLocation((String *) serializable->objectForKey(MCSTR("contentLocation"))); - setContentDescription((String *) serializable->objectForKey(MCSTR("contentDescription"))); - String * value = (String *) serializable->objectForKey(MCSTR("inlineAttachment")); - if (value != NULL) { - if (value->intValue()) { - setInlineAttachment(true); - } - } - value = (String *) serializable->objectForKey(MCSTR("partType")); - if (value != NULL) { - if (value->isEqual(MCSTR("single"))) { - setPartType(PartTypeSingle); - } - else if (value->isEqual(MCSTR("message"))) { - setPartType(PartTypeMessage); - } - else if (value->isEqual(MCSTR("multipart/mixed"))) { - setPartType(PartTypeMultipartMixed); - } - else if (value->isEqual(MCSTR("multipart/related"))) { - setPartType(PartTypeMultipartRelated); - } - else if (value->isEqual(MCSTR("multipart/alternative"))) { - setPartType(PartTypeMultipartAlternative); - } - else if (value->isEqual(MCSTR("multipart/signed"))) { - setPartType(PartTypeMultipartSigned); - } - } -} - -void AbstractPart::setContentTypeParameters(HashMap * parameters) -{ - MC_SAFE_REPLACE_COPY(HashMap, mContentTypeParameters, parameters); -} - -Array * AbstractPart::allContentTypeParametersNames() -{ - if (mContentTypeParameters == NULL) - return Array::array(); - return mContentTypeParameters->allKeys(); -} - -void AbstractPart::setContentTypeParameter(String * name, String * object) -{ - if (mContentTypeParameters == NULL) { - mContentTypeParameters = new HashMap(); - } - removeContentTypeParameter(name); - mContentTypeParameters->setObjectForKey(name, object); -} - -void AbstractPart::removeContentTypeParameter(String * name) -{ - if (mContentTypeParameters == NULL) - return; - mc_foreachhashmapKey(String, key, mContentTypeParameters) { - if (key->isEqualCaseInsensitive(name)) { - mContentTypeParameters->removeObjectForKey(key); - break; - } - } -} - -String * AbstractPart::contentTypeParameterValueForName(String * name) -{ - String * result = NULL; - mc_foreachhashmapKey(String, key, mContentTypeParameters) { - if (key->isEqualCaseInsensitive(name)) { - result = (String *) mContentTypeParameters->objectForKey(key); - } - } - return result; -} diff --git a/src/core/abstract/MCAbstractPart.cpp b/src/core/abstract/MCAbstractPart.cpp new file mode 100644 index 00000000..783d47a9 --- /dev/null +++ b/src/core/abstract/MCAbstractPart.cpp @@ -0,0 +1,451 @@ +#include "MCWin32.h" // should be first include. + +#include "MCAbstractPart.h" + +#include +#include +#include +#include "MCData.h" +#include "MCAbstractMessagePart.h" +#include "MCAbstractMultipart.h" +#include "MCArray.h" + +using namespace mailcore; + +AbstractPart::AbstractPart() +{ + init(); +} + +AbstractPart::AbstractPart(AbstractPart * other) +{ + init(); + setUniqueID(other->mUniqueID); + setFilename(other->mFilename); + setMimeType(other->mMimeType); + setCharset(other->mCharset); + setContentID(other->mContentID); + setContentLocation(other->mContentLocation); + setContentDescription(other->mContentDescription); + setInlineAttachment(other->mInlineAttachment); + setPartType(other->mPartType); + setContentTypeParameters(other->mContentTypeParameters); +} + +void AbstractPart::init() +{ + mUniqueID = NULL; + mFilename = NULL; + mMimeType = NULL; + mCharset = NULL; + mContentID = NULL; + mContentLocation = NULL; + mContentDescription = NULL; + mInlineAttachment = false; + mPartType = PartTypeSingle; + mContentTypeParameters = NULL; +} + +AbstractPart::~AbstractPart() +{ + MC_SAFE_RELEASE(mUniqueID); + MC_SAFE_RELEASE(mFilename); + MC_SAFE_RELEASE(mMimeType); + MC_SAFE_RELEASE(mCharset); + MC_SAFE_RELEASE(mContentID); + MC_SAFE_RELEASE(mContentLocation); + MC_SAFE_RELEASE(mContentDescription); + MC_SAFE_RELEASE(mContentTypeParameters); +} + +String * AbstractPart::description() +{ + String * result = String::string(); + result->appendUTF8Format("<%s:%p\n", className()->UTF8Characters(), this); + if (mFilename != NULL) { + result->appendUTF8Format("filename: %s\n", mFilename->UTF8Characters()); + } + if (mMimeType != NULL) { + result->appendUTF8Format("mime type: %s\n", mMimeType->UTF8Characters()); + } + if (mCharset != NULL) { + result->appendUTF8Format("charset: %s\n", mCharset->UTF8Characters()); + } + if (mContentID != NULL) { + result->appendUTF8Format("content-ID: %s\n", mContentID->UTF8Characters()); + } + if (mContentLocation != NULL) { + result->appendUTF8Format("content-location: %s\n", mContentLocation->UTF8Characters()); + } + if (mContentDescription != NULL) { + result->appendUTF8Format("content-description: %s\n", mContentDescription->UTF8Characters()); + } + result->appendUTF8Format("inline: %i\n", mInlineAttachment); + if (mContentTypeParameters != NULL) { + mc_foreachhashmapKeyAndValue(String, key, String, value, mContentTypeParameters) { + result->appendUTF8Format("%s: %s\n", key->UTF8Characters(), value->UTF8Characters()); + } + } + result->appendUTF8Format(">"); + + return result; +} + +Object * AbstractPart::copy() +{ + return new AbstractPart(this); +} + +PartType AbstractPart::partType() +{ + return mPartType; +} + +void AbstractPart::setPartType(PartType type) +{ + mPartType = type; +} + +String * AbstractPart::uniqueID() +{ + return mUniqueID; +} + +void AbstractPart::setUniqueID(String * uniqueID) +{ + MC_SAFE_REPLACE_COPY(String, mUniqueID, uniqueID); +} + +String * AbstractPart::filename() +{ + return mFilename; +} + +void AbstractPart::setFilename(String * filename) +{ + MC_SAFE_REPLACE_COPY(String, mFilename, filename); +} + +String * AbstractPart::mimeType() +{ + return mMimeType; +} + +void AbstractPart::setMimeType(String * mimeType) +{ + MC_SAFE_REPLACE_COPY(String, mMimeType, mimeType); +} + +String * AbstractPart::charset() +{ + return mCharset; +} + +void AbstractPart::setCharset(String * charset) +{ + MC_SAFE_REPLACE_COPY(String, mCharset, charset); +} + +String * AbstractPart::contentID() +{ + return mContentID; +} + +void AbstractPart::setContentID(String * contentID) +{ + MC_SAFE_REPLACE_COPY(String, mContentID, contentID); +} + +String * AbstractPart::contentLocation() +{ + return mContentLocation; +} + +void AbstractPart::setContentLocation(String * contentLocation) +{ + MC_SAFE_REPLACE_COPY(String, mContentLocation, contentLocation); +} + +String * AbstractPart::contentDescription() +{ + return mContentDescription; +} + +void AbstractPart::setContentDescription(String * contentDescription) +{ + MC_SAFE_REPLACE_COPY(String, mContentDescription, contentDescription); +} + +bool AbstractPart::isInlineAttachment() +{ + return mInlineAttachment; +} + +void AbstractPart::setInlineAttachment(bool inlineAttachment) +{ + mInlineAttachment = inlineAttachment; +} + +void AbstractPart::importIMAPFields(struct mailimap_body_fields * fields, + struct mailimap_body_ext_1part * extension) +{ + if (fields->bd_parameter != NULL) { + clistiter * cur; + + for(cur = clist_begin(fields->bd_parameter->pa_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_single_body_fld_param * imap_param; + + imap_param = (struct mailimap_single_body_fld_param *) clist_content(cur); + + if (strcasecmp(imap_param->pa_name, "name") == 0) { + setFilename(String::stringByDecodingMIMEHeaderValue(imap_param->pa_value)); + } + else if (strcasecmp(imap_param->pa_name, "charset") == 0) { + setCharset(String::stringByDecodingMIMEHeaderValue(imap_param->pa_value)); + } + } + } + if (fields->bd_id != NULL) { + char * contentid; + size_t cur_token; + int r; + + cur_token = 0; + r = mailimf_msg_id_parse(fields->bd_id, strlen(fields->bd_id), + &cur_token, &contentid); + if (r == MAILIMF_NO_ERROR) { + // msg id + setContentID(String::stringWithUTF8Characters(contentid)); + free(contentid); + } + } + if (fields->bd_description != NULL) { + setContentDescription(String::stringWithUTF8Characters(fields->bd_description)); + } + + if (extension != NULL) { + if (extension->bd_disposition != NULL) { + if (strcasecmp(extension->bd_disposition->dsp_type, "inline") == 0) { + setInlineAttachment(true); + } + + if (extension->bd_disposition->dsp_attributes != NULL) { + clistiter * cur; + + for(cur = clist_begin(extension->bd_disposition->dsp_attributes->pa_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_single_body_fld_param * imap_param; + + imap_param = (struct mailimap_single_body_fld_param *) clist_content(cur); + + if (strcasecmp(imap_param->pa_name, "filename") == 0) { + setFilename(String::stringByDecodingMIMEHeaderValue(imap_param->pa_value)); + } + } + } + } + + if (extension->bd_loc != NULL) { + setContentLocation(String::stringWithUTF8Characters(extension->bd_loc)); + } + } +} + +AbstractPart * AbstractPart::partForContentID(String * contentID) +{ + if (contentID->isEqual(mContentID)) { + return this; + } + else { + return NULL; + } +} + +AbstractPart * AbstractPart::partForUniqueID(String * uniqueID) +{ + if (uniqueID->isEqual(mUniqueID)) { + return this; + } + else { + return NULL; + } +} + +String * AbstractPart::decodedStringForData(Data * data) +{ + String *lowerMimeType = mMimeType ? mMimeType->lowercaseString() : NULL; + + if (lowerMimeType && lowerMimeType->hasPrefix(MCSTR("text/"))) { + bool isHTML = lowerMimeType->isEqual(MCSTR("text/html")); + return data->stringWithDetectedCharset(mCharset, isHTML); + } + else { + return NULL; + } +} + +void AbstractPart::applyUniquePartID() +{ + Array * queue = new Array(); + queue->addObject(this); + unsigned int queueIndex = 0; + unsigned int identifier = 0; + while (queueIndex < queue->count()) { + AbstractPart * part = (AbstractPart *) queue->objectAtIndex(queueIndex); + switch (part->partType()) { + case PartTypeSingle: + part->setUniqueID(String::stringWithUTF8Format("%u", identifier)); + identifier ++; + break; + case PartTypeMessage: + queue->addObject(((AbstractMessagePart *) part)->mainPart()); + break; + case PartTypeMultipartMixed: + case PartTypeMultipartRelated: + case PartTypeMultipartAlternative: + case PartTypeMultipartSigned: + queue->addObjectsFromArray(((AbstractMultipart *) part)->parts()); + break; + } + queueIndex ++; + } + queue->release(); +} + +HashMap * AbstractPart::serializable() +{ + HashMap * result = Object::serializable(); + + if (uniqueID() != NULL) { + result->setObjectForKey(MCSTR("uniqueID"), uniqueID()); + } + if (filename() != NULL) { + result->setObjectForKey(MCSTR("filename"), filename()); + } + if (mimeType() != NULL) { + result->setObjectForKey(MCSTR("mimeType"), mimeType()); + } + if (charset() != NULL) { + result->setObjectForKey(MCSTR("charset"), charset()); + } + if (contentID() != NULL) { + result->setObjectForKey(MCSTR("contentID"), contentID()); + } + if (contentLocation() != NULL) { + result->setObjectForKey(MCSTR("contentLocation"), contentLocation()); + } + if (contentDescription() != NULL) { + result->setObjectForKey(MCSTR("contentDescription"), contentDescription()); + } + if (mInlineAttachment) { + result->setObjectForKey(MCSTR("inlineAttachment"), MCSTR("1")); + } + String * partTypeStr; + switch (mPartType) { + default: + case PartTypeSingle: + partTypeStr = MCSTR("single"); + break; + case PartTypeMessage: + partTypeStr = MCSTR("message"); + break; + case PartTypeMultipartMixed: + partTypeStr = MCSTR("multipart/mixed"); + break; + case PartTypeMultipartRelated: + partTypeStr = MCSTR("multipart/related"); + break; + case PartTypeMultipartAlternative: + partTypeStr = MCSTR("multipart/alternative"); + break; + case PartTypeMultipartSigned: + partTypeStr = MCSTR("multipart/signed"); + break; + } + result->setObjectForKey(MCSTR("partType"), partTypeStr); + + return result; +} + +void AbstractPart::importSerializable(HashMap * serializable) +{ + setUniqueID((String *) serializable->objectForKey(MCSTR("uniqueID"))); + setFilename((String *) serializable->objectForKey(MCSTR("filename"))); + setMimeType((String *) serializable->objectForKey(MCSTR("mimeType"))); + setCharset((String *) serializable->objectForKey(MCSTR("charset"))); + setContentID((String *) serializable->objectForKey(MCSTR("contentID"))); + setContentLocation((String *) serializable->objectForKey(MCSTR("contentLocation"))); + setContentDescription((String *) serializable->objectForKey(MCSTR("contentDescription"))); + String * value = (String *) serializable->objectForKey(MCSTR("inlineAttachment")); + if (value != NULL) { + if (value->intValue()) { + setInlineAttachment(true); + } + } + value = (String *) serializable->objectForKey(MCSTR("partType")); + if (value != NULL) { + if (value->isEqual(MCSTR("single"))) { + setPartType(PartTypeSingle); + } + else if (value->isEqual(MCSTR("message"))) { + setPartType(PartTypeMessage); + } + else if (value->isEqual(MCSTR("multipart/mixed"))) { + setPartType(PartTypeMultipartMixed); + } + else if (value->isEqual(MCSTR("multipart/related"))) { + setPartType(PartTypeMultipartRelated); + } + else if (value->isEqual(MCSTR("multipart/alternative"))) { + setPartType(PartTypeMultipartAlternative); + } + else if (value->isEqual(MCSTR("multipart/signed"))) { + setPartType(PartTypeMultipartSigned); + } + } +} + +void AbstractPart::setContentTypeParameters(HashMap * parameters) +{ + MC_SAFE_REPLACE_COPY(HashMap, mContentTypeParameters, parameters); +} + +Array * AbstractPart::allContentTypeParametersNames() +{ + if (mContentTypeParameters == NULL) + return Array::array(); + return mContentTypeParameters->allKeys(); +} + +void AbstractPart::setContentTypeParameter(String * name, String * object) +{ + if (mContentTypeParameters == NULL) { + mContentTypeParameters = new HashMap(); + } + removeContentTypeParameter(name); + mContentTypeParameters->setObjectForKey(name, object); +} + +void AbstractPart::removeContentTypeParameter(String * name) +{ + if (mContentTypeParameters == NULL) + return; + mc_foreachhashmapKey(String, key, mContentTypeParameters) { + if (key->isEqualCaseInsensitive(name)) { + mContentTypeParameters->removeObjectForKey(key); + break; + } + } +} + +String * AbstractPart::contentTypeParameterValueForName(String * name) +{ + String * result = NULL; + mc_foreachhashmapKey(String, key, mContentTypeParameters) { + if (key->isEqualCaseInsensitive(name)) { + result = (String *) mContentTypeParameters->objectForKey(key); + } + } + return result; +} diff --git a/src/core/abstract/MCAddress.cc b/src/core/abstract/MCAddress.cc deleted file mode 100644 index 98b4d8ec..00000000 --- a/src/core/abstract/MCAddress.cc +++ /dev/null @@ -1,528 +0,0 @@ -#include "MCWin32.h" // should be included first. - -#include "MCAddress.h" - -#include -#include - -#include "MCDefines.h" - -using namespace mailcore; - -static Array * lep_address_list_from_lep_mailbox(struct mailimf_mailbox_list * mb_list, int encoded); -static Array * lep_address_list_from_lep_addr(struct mailimf_address_list * addr_list, int encoded); - -Address::Address() -{ - init(); -} - -Address::Address(Address * other) -{ - init(); - setDisplayName(other->displayName()); - setMailbox(other->mailbox()); -} - -void Address::init() -{ - mDisplayName = NULL; - mMailbox = NULL; -} - -Address::~Address() -{ - MC_SAFE_RELEASE(mDisplayName); - MC_SAFE_RELEASE(mMailbox); -} - -Address * Address::addressWithDisplayName(String * displayName, String * mailbox) -{ - Address * result = new Address(); - result->setDisplayName(displayName); - result->setMailbox(mailbox); - return (Address *) result->autorelease(); -} - -Address * Address::addressWithMailbox(String * mailbox) -{ - return addressWithDisplayName(NULL, mailbox); -} - -Address * Address::addressWithIMFMailbox(struct mailimf_mailbox * mailbox) -{ - Address * address; - - address = new Address(); - if (mailbox->mb_display_name != NULL) { - address->setDisplayName(String::stringByDecodingMIMEHeaderValue(mailbox->mb_display_name)); - } - if (mailbox->mb_addr_spec != NULL) { - address->setMailbox(String::stringWithUTF8Characters(mailbox->mb_addr_spec)); - } - if (address->mailbox() == NULL) { - address->setMailbox(String::string()); - } - - return (Address *) address->autorelease(); -} - -Address * Address::addressWithIMAPAddress(struct mailimap_address * imap_addr) -{ - char * dsp_name; - Address * address; - String * mailbox; - - if (imap_addr->ad_personal_name == NULL) - dsp_name = NULL; - else { - dsp_name = imap_addr->ad_personal_name; - } - - if (imap_addr->ad_host_name == NULL) { - const char * addr; - - if (imap_addr->ad_mailbox_name == NULL) { - addr = ""; - } - else { - addr = imap_addr->ad_mailbox_name; - } - mailbox = String::stringByDecodingMIMEHeaderValue(addr); - if (mailbox == NULL) { - mailbox = MCSTR(""); - } - } - else if (imap_addr->ad_mailbox_name == NULL) { - // fix by Gabor Cselle, (http://gaborcselle.com/), reported 8/16/2009 - mailbox = String::stringWithUTF8Format("@%s", imap_addr->ad_host_name); - } - else { - mailbox = String::stringWithUTF8Format("%s@%s", imap_addr->ad_mailbox_name, imap_addr->ad_host_name); - } - - address = new Address(); - if (dsp_name != NULL) { - address->setDisplayName(String::stringByDecodingMIMEHeaderValue(dsp_name)); - } - address->setMailbox(mailbox); - - return (Address *) address->autorelease(); -} - -Address * Address::addressWithRFC822String(String * RFC822String) -{ - const char * utf8String; - size_t currentIndex; - struct mailimf_mailbox * mb; - int r; - Address * result; - - utf8String = RFC822String->UTF8Characters(); - currentIndex = 0; - r = mailimf_mailbox_parse(utf8String, strlen(utf8String), ¤tIndex, &mb); - if (r != MAILIMF_NO_ERROR) - return NULL; - - result = addressWithIMFMailbox(mb); - mailimf_mailbox_free(mb); - - return result; -} - -Address * Address::addressWithNonEncodedIMFMailbox(struct mailimf_mailbox * mailbox) -{ - Address * address; - - address = new Address(); - if (mailbox->mb_display_name != NULL) { - address->setDisplayName(String::stringWithUTF8Characters(mailbox->mb_display_name)); - } - if (mailbox->mb_addr_spec != NULL) { - address->setMailbox(String::stringWithUTF8Characters(mailbox->mb_addr_spec)); - } - if (address->mailbox() == NULL) { - address->setMailbox(String::string()); - } - - return (Address *) address->autorelease(); -} - -Address * Address::addressWithNonEncodedRFC822String(String * nonEncodedRFC822String) -{ - const char * utf8String; - size_t currentIndex; - struct mailimf_mailbox * mb; - int r; - Address * result; - - utf8String = nonEncodedRFC822String->UTF8Characters(); - currentIndex = 0; - r = mailimf_mailbox_parse(utf8String, strlen(utf8String), ¤tIndex, &mb); - if (r != MAILIMF_NO_ERROR) - return NULL; - - result = addressWithNonEncodedIMFMailbox(mb); - mailimf_mailbox_free(mb); - - return result; -} - -Array * Address::addressesWithRFC822String(String * string) -{ - const char * utf8String; - size_t currentIndex; - struct mailimf_address_list * addr_list; - Array * result; - int r; - - utf8String = string->UTF8Characters(); - currentIndex = 0; - - r = mailimf_address_list_parse(utf8String, strlen(utf8String), ¤tIndex, &addr_list); - if (r != MAILIMF_NO_ERROR) - return NULL; - - result = lep_address_list_from_lep_addr(addr_list, 1); - mailimf_address_list_free(addr_list); - - return result; -} - -Array * Address::addressesWithNonEncodedRFC822String(String * string) -{ - const char * utf8String; - size_t currentIndex; - struct mailimf_address_list * addr_list; - Array * result; - int r; - - utf8String = string->UTF8Characters(); - currentIndex = 0; - - r = mailimf_address_list_parse(utf8String, strlen(utf8String), ¤tIndex, &addr_list); - if (r != MAILIMF_NO_ERROR) - return NULL; - - result = lep_address_list_from_lep_addr(addr_list, 0); - mailimf_address_list_free(addr_list); - - return result; -} - -String * Address::RFC822StringForAddresses(Array * addresses) -{ - String * result = String::string(); - for(unsigned int i = 0 ; i < addresses->count() ; i ++) { - Address * address = (Address *) addresses->objectAtIndex(i); - if (i != 0) { - result->appendString(MCSTR(", ")); - } - result->appendString(address->RFC822String()); - } - return result; -} - -String * Address::nonEncodedRFC822StringForAddresses(Array * addresses) -{ - String * result = String::string(); - for(unsigned int i = 0 ; i < addresses->count() ; i ++) { - Address * address = (Address *) addresses->objectAtIndex(i); - if (i != 0) { - result->appendString(MCSTR(", ")); - } - result->appendString(address->nonEncodedRFC822String()); - } - return result; -} - -String * Address::description() -{ - String * result = String::string(); - result->appendString(className()); - result->appendUTF8Format(":%p ", this); - if (mDisplayName != NULL) { - result->appendString(mDisplayName); - } - result->appendUTF8Characters(" <"); - if (mMailbox != NULL) { - result->appendString(mMailbox); - } - result->appendUTF8Characters(">"); - - return result; -} - -bool Address::isEqual(Object * otherObject) -{ - Address * otherAddress = (Address *) otherObject; - - if (mDisplayName == NULL) { - if (otherAddress->displayName() != NULL) { - return false; - } - } - else if (mDisplayName != NULL) { - if (otherAddress->displayName() == NULL) { - return false; - } - else { - if (!mDisplayName->isEqual(otherAddress->displayName())) - return false; - } - } - - if (mMailbox == NULL) { - if (otherAddress->mailbox() != NULL) { - return false; - } - } - else if (mMailbox != NULL) { - if (otherAddress->mailbox() == NULL) { - return false; - } - else { - if (!mMailbox->isEqual(otherAddress->mailbox())) - return false; - } - } - - return true; -} - -unsigned int Address::hash() -{ - unsigned int value; - - value = 0; - if (mDisplayName != NULL) { - value += mDisplayName->hash(); - } - if (mMailbox != NULL) { - value += mMailbox->hash(); - } - - return value; -} - -Object * Address::copy() -{ - return new Address(this); -} - -void Address::setDisplayName(String * displayName) -{ - MC_SAFE_REPLACE_COPY(String, mDisplayName, displayName); -} - -String * Address::displayName() -{ - return mDisplayName; -} - -void Address::setMailbox(String * mailbox) -{ - MC_SAFE_REPLACE_COPY(String, mMailbox, mailbox); -} - -String * Address::mailbox() -{ - return mMailbox; -} - -struct mailimf_address * Address::createIMFAddress() -{ - struct mailimf_mailbox * mailbox; - struct mailimf_address * result; - - mailbox = createIMFMailbox(); - result = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mailbox, NULL); - - return result; -} - -struct mailimf_mailbox * Address::createIMFMailbox() -{ - struct mailimf_mailbox * result; - char * display_name; - char * addr_spec; - - display_name = NULL; - if (displayName() != NULL) { - if (displayName()->length() > 0) { - Data * data; - - data = displayName()->encodedAddressDisplayNameValue(); - if (data->bytes() != NULL) { - display_name = strdup(data->bytes()); - } - } - } - addr_spec = strdup(mailbox()->UTF8Characters()); - result = mailimf_mailbox_new(display_name, addr_spec); - - return result; -} - -String * Address::RFC822String() -{ - struct mailimf_mailbox * mb; - MMAPString * str; - int col; - struct mailimf_mailbox_list * mb_list; - clist * list; - String * result; - - mb = createIMFMailbox(); - - list = clist_new(); - clist_append(list, mb); - mb_list = mailimf_mailbox_list_new(list); - - str = mmap_string_new(""); - col = 0; - mailimf_mailbox_list_write_mem(str, &col, mb_list); - - result = String::stringWithUTF8Characters(str->str); - - mailimf_mailbox_list_free(mb_list); - mmap_string_free(str); - - return result; -} - -String * Address::nonEncodedRFC822String() -{ - struct mailimf_mailbox * mb; - MMAPString * str; - int col; - struct mailimf_mailbox_list * mb_list; - clist * list; - String * result; - char * display_name; - char * addr_spec; - - display_name = NULL; - if (displayName() != NULL) { - if (displayName()->length() > 0) { - display_name = strdup(displayName()->UTF8Characters()); - } - } - if ((mailbox() == NULL) || (mailbox()->length() == 0)) { - addr_spec = strdup("invalid"); - } - else { - addr_spec = strdup(mailbox()->UTF8Characters()); - } - mb = mailimf_mailbox_new(display_name, addr_spec); - - list = clist_new(); - clist_append(list, mb); - mb_list = mailimf_mailbox_list_new(list); - - str = mmap_string_new(""); - col = 0; - mailimf_mailbox_list_write_mem(str, &col, mb_list); - - result = String::stringWithUTF8Characters(str->str); - - mailimf_mailbox_list_free(mb_list); - mmap_string_free(str); - - return result; -} - -static Array * lep_address_list_from_lep_mailbox(struct mailimf_mailbox_list * mb_list, int encoded) -{ - Array * result; - clistiter * cur; - - result = Array::array(); - for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; cur = clist_next(cur)) { - struct mailimf_mailbox * mb; - Address * address; - - mb = (mailimf_mailbox *) clist_content(cur); - if (encoded) { - address = Address::addressWithIMFMailbox(mb); - } - else { - address = Address::addressWithNonEncodedIMFMailbox(mb); - } - result->addObject(address); - } - - return result; -} - -static Array * lep_address_list_from_lep_addr(struct mailimf_address_list * addr_list, int encoded) -{ - Array * result; - clistiter * cur; - - result = Array::array(); - - for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; - cur = clist_next(cur)) { - struct mailimf_address * addr; - - addr = (mailimf_address *) clist_content(cur); - switch (addr->ad_type) { - case MAILIMF_ADDRESS_MAILBOX: - { - Address * address; - - if (encoded) { - address = Address::addressWithIMFMailbox(addr->ad_data.ad_mailbox); - } - else { - address = Address::addressWithNonEncodedIMFMailbox(addr->ad_data.ad_mailbox); - } - result->addObject(address); - break; - } - - case MAILIMF_ADDRESS_GROUP: - { - if (addr->ad_data.ad_group->grp_mb_list != NULL) { - Array * subArray; - - subArray = lep_address_list_from_lep_mailbox(addr->ad_data.ad_group->grp_mb_list, encoded); - result->addObjectsFromArray(subArray); - } - break; - } - } - } - - return result; -} - -static void * createObject() -{ - return new Address(); -} - -HashMap * Address::serializable() -{ - HashMap * result = Object::serializable(); - if (mailbox() != NULL) { - result->setObjectForKey(MCSTR("mailbox"), mailbox()); - } - if (displayName() != NULL) { - result->setObjectForKey(MCSTR("displayName"), displayName()); - } - return result; -} - -void Address::importSerializable(HashMap * serializable) -{ - setMailbox((String *) serializable->objectForKey(MCSTR("mailbox"))); - setDisplayName((String *) serializable->objectForKey(MCSTR("displayName"))); -} - -INITIALIZE(Address) -{ - Object::registerObjectConstructor("mailcore::Address", &createObject); -} - diff --git a/src/core/abstract/MCAddress.cpp b/src/core/abstract/MCAddress.cpp new file mode 100644 index 00000000..98b4d8ec --- /dev/null +++ b/src/core/abstract/MCAddress.cpp @@ -0,0 +1,528 @@ +#include "MCWin32.h" // should be included first. + +#include "MCAddress.h" + +#include +#include + +#include "MCDefines.h" + +using namespace mailcore; + +static Array * lep_address_list_from_lep_mailbox(struct mailimf_mailbox_list * mb_list, int encoded); +static Array * lep_address_list_from_lep_addr(struct mailimf_address_list * addr_list, int encoded); + +Address::Address() +{ + init(); +} + +Address::Address(Address * other) +{ + init(); + setDisplayName(other->displayName()); + setMailbox(other->mailbox()); +} + +void Address::init() +{ + mDisplayName = NULL; + mMailbox = NULL; +} + +Address::~Address() +{ + MC_SAFE_RELEASE(mDisplayName); + MC_SAFE_RELEASE(mMailbox); +} + +Address * Address::addressWithDisplayName(String * displayName, String * mailbox) +{ + Address * result = new Address(); + result->setDisplayName(displayName); + result->setMailbox(mailbox); + return (Address *) result->autorelease(); +} + +Address * Address::addressWithMailbox(String * mailbox) +{ + return addressWithDisplayName(NULL, mailbox); +} + +Address * Address::addressWithIMFMailbox(struct mailimf_mailbox * mailbox) +{ + Address * address; + + address = new Address(); + if (mailbox->mb_display_name != NULL) { + address->setDisplayName(String::stringByDecodingMIMEHeaderValue(mailbox->mb_display_name)); + } + if (mailbox->mb_addr_spec != NULL) { + address->setMailbox(String::stringWithUTF8Characters(mailbox->mb_addr_spec)); + } + if (address->mailbox() == NULL) { + address->setMailbox(String::string()); + } + + return (Address *) address->autorelease(); +} + +Address * Address::addressWithIMAPAddress(struct mailimap_address * imap_addr) +{ + char * dsp_name; + Address * address; + String * mailbox; + + if (imap_addr->ad_personal_name == NULL) + dsp_name = NULL; + else { + dsp_name = imap_addr->ad_personal_name; + } + + if (imap_addr->ad_host_name == NULL) { + const char * addr; + + if (imap_addr->ad_mailbox_name == NULL) { + addr = ""; + } + else { + addr = imap_addr->ad_mailbox_name; + } + mailbox = String::stringByDecodingMIMEHeaderValue(addr); + if (mailbox == NULL) { + mailbox = MCSTR(""); + } + } + else if (imap_addr->ad_mailbox_name == NULL) { + // fix by Gabor Cselle, (http://gaborcselle.com/), reported 8/16/2009 + mailbox = String::stringWithUTF8Format("@%s", imap_addr->ad_host_name); + } + else { + mailbox = String::stringWithUTF8Format("%s@%s", imap_addr->ad_mailbox_name, imap_addr->ad_host_name); + } + + address = new Address(); + if (dsp_name != NULL) { + address->setDisplayName(String::stringByDecodingMIMEHeaderValue(dsp_name)); + } + address->setMailbox(mailbox); + + return (Address *) address->autorelease(); +} + +Address * Address::addressWithRFC822String(String * RFC822String) +{ + const char * utf8String; + size_t currentIndex; + struct mailimf_mailbox * mb; + int r; + Address * result; + + utf8String = RFC822String->UTF8Characters(); + currentIndex = 0; + r = mailimf_mailbox_parse(utf8String, strlen(utf8String), ¤tIndex, &mb); + if (r != MAILIMF_NO_ERROR) + return NULL; + + result = addressWithIMFMailbox(mb); + mailimf_mailbox_free(mb); + + return result; +} + +Address * Address::addressWithNonEncodedIMFMailbox(struct mailimf_mailbox * mailbox) +{ + Address * address; + + address = new Address(); + if (mailbox->mb_display_name != NULL) { + address->setDisplayName(String::stringWithUTF8Characters(mailbox->mb_display_name)); + } + if (mailbox->mb_addr_spec != NULL) { + address->setMailbox(String::stringWithUTF8Characters(mailbox->mb_addr_spec)); + } + if (address->mailbox() == NULL) { + address->setMailbox(String::string()); + } + + return (Address *) address->autorelease(); +} + +Address * Address::addressWithNonEncodedRFC822String(String * nonEncodedRFC822String) +{ + const char * utf8String; + size_t currentIndex; + struct mailimf_mailbox * mb; + int r; + Address * result; + + utf8String = nonEncodedRFC822String->UTF8Characters(); + currentIndex = 0; + r = mailimf_mailbox_parse(utf8String, strlen(utf8String), ¤tIndex, &mb); + if (r != MAILIMF_NO_ERROR) + return NULL; + + result = addressWithNonEncodedIMFMailbox(mb); + mailimf_mailbox_free(mb); + + return result; +} + +Array * Address::addressesWithRFC822String(String * string) +{ + const char * utf8String; + size_t currentIndex; + struct mailimf_address_list * addr_list; + Array * result; + int r; + + utf8String = string->UTF8Characters(); + currentIndex = 0; + + r = mailimf_address_list_parse(utf8String, strlen(utf8String), ¤tIndex, &addr_list); + if (r != MAILIMF_NO_ERROR) + return NULL; + + result = lep_address_list_from_lep_addr(addr_list, 1); + mailimf_address_list_free(addr_list); + + return result; +} + +Array * Address::addressesWithNonEncodedRFC822String(String * string) +{ + const char * utf8String; + size_t currentIndex; + struct mailimf_address_list * addr_list; + Array * result; + int r; + + utf8String = string->UTF8Characters(); + currentIndex = 0; + + r = mailimf_address_list_parse(utf8String, strlen(utf8String), ¤tIndex, &addr_list); + if (r != MAILIMF_NO_ERROR) + return NULL; + + result = lep_address_list_from_lep_addr(addr_list, 0); + mailimf_address_list_free(addr_list); + + return result; +} + +String * Address::RFC822StringForAddresses(Array * addresses) +{ + String * result = String::string(); + for(unsigned int i = 0 ; i < addresses->count() ; i ++) { + Address * address = (Address *) addresses->objectAtIndex(i); + if (i != 0) { + result->appendString(MCSTR(", ")); + } + result->appendString(address->RFC822String()); + } + return result; +} + +String * Address::nonEncodedRFC822StringForAddresses(Array * addresses) +{ + String * result = String::string(); + for(unsigned int i = 0 ; i < addresses->count() ; i ++) { + Address * address = (Address *) addresses->objectAtIndex(i); + if (i != 0) { + result->appendString(MCSTR(", ")); + } + result->appendString(address->nonEncodedRFC822String()); + } + return result; +} + +String * Address::description() +{ + String * result = String::string(); + result->appendString(className()); + result->appendUTF8Format(":%p ", this); + if (mDisplayName != NULL) { + result->appendString(mDisplayName); + } + result->appendUTF8Characters(" <"); + if (mMailbox != NULL) { + result->appendString(mMailbox); + } + result->appendUTF8Characters(">"); + + return result; +} + +bool Address::isEqual(Object * otherObject) +{ + Address * otherAddress = (Address *) otherObject; + + if (mDisplayName == NULL) { + if (otherAddress->displayName() != NULL) { + return false; + } + } + else if (mDisplayName != NULL) { + if (otherAddress->displayName() == NULL) { + return false; + } + else { + if (!mDisplayName->isEqual(otherAddress->displayName())) + return false; + } + } + + if (mMailbox == NULL) { + if (otherAddress->mailbox() != NULL) { + return false; + } + } + else if (mMailbox != NULL) { + if (otherAddress->mailbox() == NULL) { + return false; + } + else { + if (!mMailbox->isEqual(otherAddress->mailbox())) + return false; + } + } + + return true; +} + +unsigned int Address::hash() +{ + unsigned int value; + + value = 0; + if (mDisplayName != NULL) { + value += mDisplayName->hash(); + } + if (mMailbox != NULL) { + value += mMailbox->hash(); + } + + return value; +} + +Object * Address::copy() +{ + return new Address(this); +} + +void Address::setDisplayName(String * displayName) +{ + MC_SAFE_REPLACE_COPY(String, mDisplayName, displayName); +} + +String * Address::displayName() +{ + return mDisplayName; +} + +void Address::setMailbox(String * mailbox) +{ + MC_SAFE_REPLACE_COPY(String, mMailbox, mailbox); +} + +String * Address::mailbox() +{ + return mMailbox; +} + +struct mailimf_address * Address::createIMFAddress() +{ + struct mailimf_mailbox * mailbox; + struct mailimf_address * result; + + mailbox = createIMFMailbox(); + result = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mailbox, NULL); + + return result; +} + +struct mailimf_mailbox * Address::createIMFMailbox() +{ + struct mailimf_mailbox * result; + char * display_name; + char * addr_spec; + + display_name = NULL; + if (displayName() != NULL) { + if (displayName()->length() > 0) { + Data * data; + + data = displayName()->encodedAddressDisplayNameValue(); + if (data->bytes() != NULL) { + display_name = strdup(data->bytes()); + } + } + } + addr_spec = strdup(mailbox()->UTF8Characters()); + result = mailimf_mailbox_new(display_name, addr_spec); + + return result; +} + +String * Address::RFC822String() +{ + struct mailimf_mailbox * mb; + MMAPString * str; + int col; + struct mailimf_mailbox_list * mb_list; + clist * list; + String * result; + + mb = createIMFMailbox(); + + list = clist_new(); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + str = mmap_string_new(""); + col = 0; + mailimf_mailbox_list_write_mem(str, &col, mb_list); + + result = String::stringWithUTF8Characters(str->str); + + mailimf_mailbox_list_free(mb_list); + mmap_string_free(str); + + return result; +} + +String * Address::nonEncodedRFC822String() +{ + struct mailimf_mailbox * mb; + MMAPString * str; + int col; + struct mailimf_mailbox_list * mb_list; + clist * list; + String * result; + char * display_name; + char * addr_spec; + + display_name = NULL; + if (displayName() != NULL) { + if (displayName()->length() > 0) { + display_name = strdup(displayName()->UTF8Characters()); + } + } + if ((mailbox() == NULL) || (mailbox()->length() == 0)) { + addr_spec = strdup("invalid"); + } + else { + addr_spec = strdup(mailbox()->UTF8Characters()); + } + mb = mailimf_mailbox_new(display_name, addr_spec); + + list = clist_new(); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + str = mmap_string_new(""); + col = 0; + mailimf_mailbox_list_write_mem(str, &col, mb_list); + + result = String::stringWithUTF8Characters(str->str); + + mailimf_mailbox_list_free(mb_list); + mmap_string_free(str); + + return result; +} + +static Array * lep_address_list_from_lep_mailbox(struct mailimf_mailbox_list * mb_list, int encoded) +{ + Array * result; + clistiter * cur; + + result = Array::array(); + for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + Address * address; + + mb = (mailimf_mailbox *) clist_content(cur); + if (encoded) { + address = Address::addressWithIMFMailbox(mb); + } + else { + address = Address::addressWithNonEncodedIMFMailbox(mb); + } + result->addObject(address); + } + + return result; +} + +static Array * lep_address_list_from_lep_addr(struct mailimf_address_list * addr_list, int encoded) +{ + Array * result; + clistiter * cur; + + result = Array::array(); + + for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_address * addr; + + addr = (mailimf_address *) clist_content(cur); + switch (addr->ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + { + Address * address; + + if (encoded) { + address = Address::addressWithIMFMailbox(addr->ad_data.ad_mailbox); + } + else { + address = Address::addressWithNonEncodedIMFMailbox(addr->ad_data.ad_mailbox); + } + result->addObject(address); + break; + } + + case MAILIMF_ADDRESS_GROUP: + { + if (addr->ad_data.ad_group->grp_mb_list != NULL) { + Array * subArray; + + subArray = lep_address_list_from_lep_mailbox(addr->ad_data.ad_group->grp_mb_list, encoded); + result->addObjectsFromArray(subArray); + } + break; + } + } + } + + return result; +} + +static void * createObject() +{ + return new Address(); +} + +HashMap * Address::serializable() +{ + HashMap * result = Object::serializable(); + if (mailbox() != NULL) { + result->setObjectForKey(MCSTR("mailbox"), mailbox()); + } + if (displayName() != NULL) { + result->setObjectForKey(MCSTR("displayName"), displayName()); + } + return result; +} + +void Address::importSerializable(HashMap * serializable) +{ + setMailbox((String *) serializable->objectForKey(MCSTR("mailbox"))); + setDisplayName((String *) serializable->objectForKey(MCSTR("displayName"))); +} + +INITIALIZE(Address) +{ + Object::registerObjectConstructor("mailcore::Address", &createObject); +} + diff --git a/src/core/abstract/MCMessageHeader.cc b/src/core/abstract/MCMessageHeader.cc deleted file mode 100644 index bc141424..00000000 --- a/src/core/abstract/MCMessageHeader.cc +++ /dev/null @@ -1,1291 +0,0 @@ -#include "MCWin32.h" // should be first include. - -#include "MCMessageHeader.h" - -#include "MCDefines.h" -#include "MCAddress.h" -#include "MCIterator.h" -#include "MCLibetpan.h" - -#include -#ifndef _MSC_VER -#include -#endif -#include - -using namespace mailcore; - -static struct mailimf_address_list * lep_address_list_from_array(Array * addresses); -static struct mailimf_mailbox_list * lep_mailbox_list_from_array(Array * addresses); -static Array * lep_address_list_from_lep_addr(struct mailimf_address_list * addr_list); -static Array * lep_address_list_from_lep_mailbox(struct mailimf_mailbox_list * mb_list); - -static Array * msg_id_to_string_array(clist * msgids); -static clist * msg_id_from_string_array(Array * msgids); - -#define MAX_HOSTNAME 512 - -MessageHeader::MessageHeader() -{ - init(true, true); -} - -MessageHeader::MessageHeader(MessageHeader * other) -{ - init(false, other->mMessageID == NULL); - if (other->mMessageID != NULL) { - setMessageID(other->mMessageID); - mMessageIDAutoGenerated = other->isMessageIDAutoGenerated(); - } - setReferences(other->mReferences); - setInReplyTo(other->mInReplyTo); - setSender(other->mSender); - setFrom(other->mFrom); - setTo(other->mTo); - setCc(other->mCc); - setBcc(other->mBcc); - setReplyTo(other->mReplyTo); - setSubject(other->mSubject); - setDate(other->date()); - setReceivedDate(other->receivedDate()); - setExtraHeaders(other->mExtraHeaders); -} - -void MessageHeader::init(bool generateDate, bool generateMessageID) -{ - mMessageID = NULL; - mMessageIDAutoGenerated = false; - mReferences = NULL; - mInReplyTo = NULL; - mSender = NULL; - mFrom = NULL; - mTo = NULL; - mCc = NULL; - mBcc = NULL; - mReplyTo = NULL; - mSubject = NULL; - mDate = (time_t) -1; - mReceivedDate = (time_t) -1; - mExtraHeaders = NULL; - - if (generateDate) { - time_t date; - date = time(NULL); - setDate(date); - setReceivedDate(date); - } - if (generateMessageID) { - static String * hostname = NULL; - static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; - - pthread_mutex_lock(&lock); - if (hostname == NULL) { - char name[MAX_HOSTNAME]; - int r; - - r = gethostname(name, MAX_HOSTNAME); - if (r < 0) { - hostname = NULL; - } - else { - hostname = new String(name); - } - if (hostname == NULL) { - hostname = new String("localhost"); - } - } - pthread_mutex_unlock(&lock); - - String * messageID = new String(); - messageID->appendString(String::uuidString()); - messageID->appendUTF8Characters("@"); - messageID->appendString(hostname); - setMessageID(messageID); - messageID->release(); - - mMessageIDAutoGenerated = true; - } -} - -MessageHeader::~MessageHeader() -{ - MC_SAFE_RELEASE(mMessageID); - MC_SAFE_RELEASE(mReferences); - MC_SAFE_RELEASE(mInReplyTo); - MC_SAFE_RELEASE(mSender); - MC_SAFE_RELEASE(mFrom); - MC_SAFE_RELEASE(mTo); - MC_SAFE_RELEASE(mCc); - MC_SAFE_RELEASE(mBcc); - MC_SAFE_RELEASE(mReplyTo); - MC_SAFE_RELEASE(mSubject); - MC_SAFE_RELEASE(mExtraHeaders); -} - -String * MessageHeader::description() -{ - String * result = String::string(); - result->appendUTF8Format("<%s:%p\n", className()->UTF8Characters(), this); - if (mMessageID != NULL) { - result->appendUTF8Format("Message-ID: %s\n", mMessageID->UTF8Characters()); - } - if (mReferences != NULL) { - result->appendUTF8Format("References: %s\n", mReferences->description()->UTF8Characters()); - } - if (mInReplyTo != NULL) { - result->appendUTF8Format("In-Reply-To: %s\n", mInReplyTo->description()->UTF8Characters()); - } - if (mSender != NULL) { - result->appendUTF8Format("Sender: %s\n", mSender->description()->UTF8Characters()); - } - if (mFrom != NULL) { - result->appendUTF8Format("From: %s\n", mFrom->description()->UTF8Characters()); - } - if (mTo != NULL) { - result->appendUTF8Format("To: %s\n", mTo->description()->UTF8Characters()); - } - if (mCc != NULL) { - result->appendUTF8Format("Cc: %s\n", mCc->description()->UTF8Characters()); - } - if (mBcc != NULL) { - result->appendUTF8Format("Bcc: %s\n", mBcc->description()->UTF8Characters()); - } - if (mReplyTo != NULL) { - result->appendUTF8Format("Reply-To: %s\n", mReplyTo->description()->UTF8Characters()); - } - if (mSubject != NULL) { - result->appendUTF8Format("Subject: %s\n", mSubject->UTF8Characters()); - } - if (mExtraHeaders != NULL) { - mc_foreachhashmapKeyAndValue(String, header, String, value, mExtraHeaders) { - result->appendUTF8Format("%s: %s\n", header->UTF8Characters(), value->UTF8Characters()); - } - } - result->appendUTF8Format(">"); - - return result; -} - -Object * MessageHeader::copy() -{ - return new MessageHeader(this); -} - -void MessageHeader::setMessageID(String * messageID) -{ - MC_SAFE_REPLACE_COPY(String, mMessageID, messageID); - mMessageIDAutoGenerated = false; -} - -String * MessageHeader::messageID() -{ - return mMessageID; -} - -bool MessageHeader::isMessageIDAutoGenerated() -{ - return mMessageIDAutoGenerated; -} - -void MessageHeader::setReferences(Array * references) -{ - MC_SAFE_REPLACE_COPY(Array, mReferences, references); -} - -Array * MessageHeader::references() -{ - return mReferences; -} - -void MessageHeader::setInReplyTo(Array * inReplyTo) -{ - MC_SAFE_REPLACE_COPY(Array, mInReplyTo, inReplyTo); -} - -Array * MessageHeader::inReplyTo() -{ - return mInReplyTo; -} - -void MessageHeader::setDate(time_t date) -{ - mDate = date; -} - -time_t MessageHeader::date() -{ - return mDate; -} - -void MessageHeader::setReceivedDate(time_t date) -{ - mReceivedDate = date; -} - -time_t MessageHeader::receivedDate() -{ - return mReceivedDate; -} - -void MessageHeader::setSender(Address * sender) -{ - MC_SAFE_REPLACE_RETAIN(Address, mSender, sender); -} - -Address * MessageHeader::sender() -{ - return mSender; -} - -void MessageHeader::setFrom(Address * from) -{ - MC_SAFE_REPLACE_RETAIN(Address, mFrom, from); -} - -Address * MessageHeader::from() -{ - return mFrom; -} - -void MessageHeader::setTo(Array * to) -{ - MC_SAFE_REPLACE_COPY(Array, mTo, to); -} - -Array * MessageHeader::to() -{ - return mTo; -} - -void MessageHeader::setCc(Array * cc) -{ - MC_SAFE_REPLACE_COPY(Array, mCc, cc); -} - -Array * MessageHeader::cc() -{ - return mCc; -} - -void MessageHeader::setBcc(Array * bcc) -{ - MC_SAFE_REPLACE_COPY(Array, mBcc, bcc); -} - -Array * MessageHeader::bcc() -{ - return mBcc; -} - -void MessageHeader::setReplyTo(Array * replyTo) -{ - MC_SAFE_REPLACE_COPY(Array, mReplyTo, replyTo); -} - -Array * MessageHeader::replyTo() -{ - return mReplyTo; -} - -void MessageHeader::setSubject(String * subject) -{ - MC_SAFE_REPLACE_COPY(String, mSubject, subject); -} - -String * MessageHeader::subject() -{ - return mSubject; -} - -void MessageHeader::setUserAgent(String * userAgent) -{ - setExtraHeader(MCSTR("X-Mailer"), userAgent); -} - -String * MessageHeader::userAgent() -{ - return extraHeaderValueForName(MCSTR("X-Mailer")); -} - -void MessageHeader::setExtraHeaders(HashMap * headers) -{ - MC_SAFE_REPLACE_COPY(HashMap, mExtraHeaders, headers); -} - -Array * MessageHeader::allExtraHeadersNames() -{ - if (mExtraHeaders == NULL) - return Array::array(); - return mExtraHeaders->allKeys(); -} - -void MessageHeader::setExtraHeader(String * name, String * object) -{ - if (mExtraHeaders == NULL) { - mExtraHeaders = new HashMap(); - } - removeExtraHeader(name); - mExtraHeaders->setObjectForKey(name, object); -} - -void MessageHeader::removeExtraHeader(String * name) -{ - if (mExtraHeaders == NULL) - return; - mc_foreachhashmapKey(String, key, mExtraHeaders) { - if (key->isEqualCaseInsensitive(name)) { - mExtraHeaders->removeObjectForKey(key); - break; - } - } -} - -String * MessageHeader::extraHeaderValueForName(String * name) -{ - String * result = NULL; - mc_foreachhashmapKey(String, key, mExtraHeaders) { - if (key->isEqualCaseInsensitive(name)) { - result = (String *) mExtraHeaders->objectForKey(key); - } - } - return result; -} - -String * MessageHeader::extractedSubject() -{ - if (subject() == NULL) - return NULL; - return subject()->extractedSubject(); -} - -String * MessageHeader::partialExtractedSubject() -{ - if (subject() == NULL) - return NULL; - return subject()->extractedSubjectAndKeepBracket(true); -} - -void MessageHeader::importHeadersData(Data * data) -{ - size_t cur_token; - struct mailimf_fields * fields; - int r; - - cur_token = 0; - r = mailimf_envelope_and_optional_fields_parse(data->bytes(), data->length(), &cur_token, &fields); - if (r != MAILIMF_NO_ERROR) { - return; - } - - importIMFFields(fields); - - mailimf_fields_free(fields); -} - -void MessageHeader::importIMFFields(struct mailimf_fields * fields) -{ - struct mailimf_single_fields single_fields; - - mailimf_single_fields_init(&single_fields, fields); - - /* date */ - - if (single_fields.fld_orig_date != NULL) { - time_t timestamp; - timestamp = timestampFromDate(single_fields.fld_orig_date->dt_date_time); - setDate(timestamp); - setReceivedDate(timestamp); - //MCLog("%lu %lu", (unsigned long) timestamp, date()); - } - - /* subject */ - if (single_fields.fld_subject != NULL) { - char * subject; - - subject = single_fields.fld_subject->sbj_value; - setSubject(String::stringByDecodingMIMEHeaderValue(subject)); - } - - /* sender */ - if (single_fields.fld_sender != NULL) { - struct mailimf_mailbox * mb; - Address * address; - - mb = single_fields.fld_sender->snd_mb; - if (mb != NULL) { - address = Address::addressWithIMFMailbox(mb); - setSender(address); - } - } - - /* from */ - if (single_fields.fld_from != NULL) { - struct mailimf_mailbox_list * mb_list; - Array * addresses; - - mb_list = single_fields.fld_from->frm_mb_list; - addresses = lep_address_list_from_lep_mailbox(mb_list); - if (addresses->count() > 0) { - setFrom((Address *) (addresses->objectAtIndex(0))); - } - } - - /* replyto */ - if (single_fields.fld_reply_to != NULL) { - struct mailimf_address_list * addr_list; - Array * addresses; - - addr_list = single_fields.fld_reply_to->rt_addr_list; - addresses = lep_address_list_from_lep_addr(addr_list); - setReplyTo(addresses); - } - - /* to */ - if (single_fields.fld_to != NULL) { - struct mailimf_address_list * addr_list; - Array * addresses; - - addr_list = single_fields.fld_to->to_addr_list; - addresses = lep_address_list_from_lep_addr(addr_list); - setTo(addresses); - } - - /* cc */ - if (single_fields.fld_cc != NULL) { - struct mailimf_address_list * addr_list; - Array * addresses; - - addr_list = single_fields.fld_cc->cc_addr_list; - addresses = lep_address_list_from_lep_addr(addr_list); - setCc(addresses); - } - - /* bcc */ - if (single_fields.fld_bcc != NULL) { - struct mailimf_address_list * addr_list; - Array * addresses; - - addr_list = single_fields.fld_bcc->bcc_addr_list; - addresses = lep_address_list_from_lep_addr(addr_list); - setBcc(addresses); - } - - /* msgid */ - if (single_fields.fld_message_id != NULL) { - char * msgid; - String * str; - - msgid = single_fields.fld_message_id->mid_value; - str = String::stringWithUTF8Characters(msgid); - setMessageID(str); - } - - /* references */ - if (single_fields.fld_references != NULL) { - clist * msg_id_list; - Array * msgids; - - msg_id_list = single_fields.fld_references->mid_list; - msgids = msg_id_to_string_array(msg_id_list); - setReferences(msgids); - } - - /* inreplyto */ - if (single_fields.fld_in_reply_to != NULL) { - clist * msg_id_list; - Array * msgids; - - msg_id_list = single_fields.fld_in_reply_to->mid_list; - msgids = msg_id_to_string_array(msg_id_list); - setInReplyTo(msgids); - } - - // Take care of other headers. - for(clistiter * cur = clist_begin(fields->fld_list) ; cur != NULL ; cur = clist_next(cur)) { - struct mailimf_field * field; - - field = (mailimf_field *)clist_content(cur); - - if (field->fld_type != MAILIMF_FIELD_OPTIONAL_FIELD) { - continue; - } - - char * fieldName; - String * fieldNameStr; - - fieldName = field->fld_data.fld_optional_field->fld_name; - fieldNameStr = String::stringWithUTF8Characters(fieldName); - // Set only if this optional-field is not set - if (extraHeaderValueForName(fieldNameStr) == NULL) { - char * fieldValue; - String * fieldValueStr; - - fieldValue = field->fld_data.fld_optional_field->fld_value; - fieldValueStr = String::stringByDecodingMIMEHeaderValue(fieldValue); - setExtraHeader(fieldNameStr, fieldValueStr); - } - } -} - -#pragma mark RFC 2822 mailbox conversion - -static Array * lep_address_list_from_lep_mailbox(struct mailimf_mailbox_list * mb_list) -{ - Array * result; - clistiter * cur; - - result = Array::array(); - for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; cur = clist_next(cur)) { - struct mailimf_mailbox * mb; - Address * address; - - mb = (struct mailimf_mailbox *) clist_content(cur); - address = Address::addressWithIMFMailbox(mb); - result->addObject(address); - } - - return result; -} - -static Array * lep_address_list_from_lep_addr(struct mailimf_address_list * addr_list) -{ - Array * result; - clistiter * cur; - - result = Array::array(); - - if (addr_list == NULL) { - return result; - } - - if (addr_list->ad_list == NULL) { - return result; - } - - for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; - cur = clist_next(cur)) { - struct mailimf_address * addr; - - addr = (struct mailimf_address *) clist_content(cur); - switch (addr->ad_type) { - case MAILIMF_ADDRESS_MAILBOX: - { - Address * address; - - address = Address::addressWithIMFMailbox(addr->ad_data.ad_mailbox); - result->addObject(address); - break; - } - - case MAILIMF_ADDRESS_GROUP: - { - if (addr->ad_data.ad_group->grp_mb_list != NULL) { - Array * subArray; - - subArray = lep_address_list_from_lep_mailbox(addr->ad_data.ad_group->grp_mb_list); - result->addObjectsFromArray(subArray); - } - break; - } - } - } - - return result; -} - -static struct mailimf_mailbox_list * lep_mailbox_list_from_array(Array * addresses) -{ - struct mailimf_mailbox_list * mb_list; - - if (addresses == NULL) - return NULL; - - if (addresses->count() == 0) - return NULL; - - mb_list = mailimf_mailbox_list_new_empty(); - - for(unsigned i = 0 ; i < addresses->count() ; i ++) { - Address * address = (Address *) addresses->objectAtIndex(i); - struct mailimf_mailbox * mailbox = address->createIMFMailbox(); - mailimf_mailbox_list_add(mb_list, mailbox); - } - - return mb_list; -} - -static struct mailimf_address_list * lep_address_list_from_array(Array * addresses) -{ - struct mailimf_address_list * addr_list; - - if (addresses == NULL) - return NULL; - - if (addresses->count() == 0) - return NULL; - - addr_list = mailimf_address_list_new_empty(); - - for(unsigned i = 0 ; i < addresses->count() ; i ++) { - Address * address = (Address *) addresses->objectAtIndex(i); - struct mailimf_address * addr = address->createIMFAddress(); - mailimf_address_list_add(addr_list, addr); - } - - return addr_list; -} - -#pragma mark Message-ID conversion - -static Array * msg_id_to_string_array(clist * msgids) -{ - clistiter * cur; - Array * result; - - result = Array::array(); - - for(cur = clist_begin(msgids) ; cur != NULL ; cur = clist_next(cur)) { - char * msgid; - String * str; - - msgid = (char *) clist_content(cur); - str = String::stringWithUTF8Characters(msgid); - result->addObject(str); - } - - return result; -} - -static clist * msg_id_from_string_array(Array * msgids) -{ - clist * result; - - if (msgids == NULL) - return NULL; - - if (msgids->count() == 0) - return NULL; - - result = clist_new(); - for(unsigned int i = 0 ; i < msgids->count() ; i ++) { - String * msgid = (String *) msgids->objectAtIndex(i); - clist_append(result, strdup(msgid->UTF8Characters())); - } - - return result; -} - -struct mailimf_fields * MessageHeader::createIMFFieldsAndFilterBcc(bool filterBcc) -{ - struct mailimf_date_time * imfDate; - char * imfMsgid; - char * imfSubject; - struct mailimf_mailbox_list * imfFrom; - struct mailimf_address_list * imfReplyTo; - struct mailimf_address_list * imfTo; - struct mailimf_address_list * imfCc; - struct mailimf_address_list * imfBcc; - clist * imfInReplyTo; - clist * imfReferences; - struct mailimf_fields * fields; - - imfDate = NULL; - if (date() != (time_t) -1) { - //MCLog("%lu", date()); - imfDate = dateFromTimestamp(date()); - } - imfFrom = NULL; - if (from() != NULL) { - imfFrom = lep_mailbox_list_from_array(Array::arrayWithObject(from())); - } - imfReplyTo = lep_address_list_from_array(replyTo()); - imfTo = lep_address_list_from_array(to()); - imfCc = lep_address_list_from_array(cc()); - imfBcc = NULL; - if (!filterBcc) { - imfBcc = lep_address_list_from_array(bcc()); - } - imfMsgid = NULL; - if (messageID() != NULL) { - imfMsgid = strdup(messageID()->UTF8Characters()); - } - imfInReplyTo = msg_id_from_string_array(inReplyTo()); - imfReferences = msg_id_from_string_array(references()); - imfSubject = NULL; - if ((subject() != NULL) && (subject()->length() > 0)) { - Data * data; - - data = subject()->encodedMIMEHeaderValueForSubject(); - if (data->bytes() != NULL) { - imfSubject = strdup(data->bytes()); - } - } - - if ((imfTo == NULL) && (imfCc == NULL) && (imfBcc == NULL)) { - imfTo = mailimf_address_list_new_empty(); - mailimf_address_list_add_parse(imfTo, (char *) "Undisclosed recipients:;"); - } - - fields = mailimf_fields_new_with_data_all(imfDate, - imfFrom, - NULL /* sender */, - imfReplyTo, - imfTo, - imfCc, - imfBcc, - imfMsgid, - imfInReplyTo, - imfReferences, - imfSubject); - - if (mExtraHeaders != NULL) { - mc_foreachhashmapKeyAndValue(String, header, String, value, mExtraHeaders) { - struct mailimf_field * field; - - field = mailimf_field_new_custom(strdup(header->UTF8Characters()), strdup(value->UTF8Characters())); - mailimf_fields_add(fields, field); - } - } - - return fields; -} - -extern "C" { - extern int mailimap_hack_date_time_parse(char * str, - struct mailimap_date_time ** result, - size_t progr_rate, - progress_function * progr_fun); -} - -#pragma mark IMAP mailbox conversion - -static Array * imap_mailbox_list_to_address_array(clist * imap_mailbox_list) -{ - clistiter * cur; - Array * result; - - result = Array::array(); - - for(cur = clist_begin(imap_mailbox_list) ; cur != NULL ; - cur = clist_next(cur)) { - struct mailimap_address * imap_addr; - Address * address; - - imap_addr = (struct mailimap_address *) clist_content(cur); - address = Address::addressWithIMAPAddress(imap_addr); - result->addObject(address); - } - - return result; -} - -void MessageHeader::importIMAPEnvelope(struct mailimap_envelope * env) -{ - if (env->env_date != NULL) { - size_t cur_token; - struct mailimf_date_time * date_time; - int r; - - cur_token = 0; - r = mailimf_date_time_parse(env->env_date, strlen(env->env_date), - &cur_token, &date_time); - if (r == MAILIMF_NO_ERROR) { - time_t timestamp; - - // date - timestamp = timestampFromDate(date_time); - setDate(timestamp); - setReceivedDate(timestamp); - mailimf_date_time_free(date_time); - } - else { - struct mailimap_date_time * imap_date; - - r = mailimap_hack_date_time_parse(env->env_date, &imap_date, 0, NULL); - if (r == MAILIMAP_NO_ERROR) { - time_t timestamp; - - timestamp = timestampFromIMAPDate(imap_date); - setDate(timestamp); - setReceivedDate(timestamp); - mailimap_date_time_free(imap_date); - } - } - } - - if (env->env_subject != NULL) { - char * subject; - - // subject - subject = env->env_subject; - setSubject(String::stringByDecodingMIMEHeaderValue(subject)); - } - - if (env->env_sender != NULL) { - if (env->env_sender->snd_list != NULL) { - Array * addresses; - - addresses = imap_mailbox_list_to_address_array(env->env_sender->snd_list); - if (addresses->count() > 0) { - setSender((Address *) addresses->objectAtIndex(0)); - } - } - } - - if (env->env_from != NULL) { - if (env->env_from->frm_list != NULL) { - Array * addresses; - - addresses = imap_mailbox_list_to_address_array(env->env_from->frm_list); - if (addresses->count() > 0) { - setFrom((Address *) addresses->objectAtIndex(0)); - } - } - } - - // skip Sender header - - if (env->env_reply_to != NULL) { - if (env->env_reply_to->rt_list != NULL) { - Array * addresses; - - addresses = imap_mailbox_list_to_address_array(env->env_reply_to->rt_list); - setReplyTo(addresses); - } - } - - if (env->env_to != NULL) { - if (env->env_to->to_list != NULL) { - Array * addresses; - - addresses = imap_mailbox_list_to_address_array(env->env_to->to_list); - setTo(addresses); - } - } - - if (env->env_cc != NULL) { - if (env->env_cc->cc_list != NULL) { - Array * addresses; - - addresses = imap_mailbox_list_to_address_array(env->env_cc->cc_list); - setCc(addresses); - } - } - - if (env->env_bcc != NULL) { - if (env->env_bcc->bcc_list != NULL) { - Array * addresses; - - addresses = imap_mailbox_list_to_address_array(env->env_bcc->bcc_list); - setBcc(addresses); - } - } - - if (env->env_in_reply_to != NULL) { - size_t cur_token; - clist * msg_id_list; - int r; - - cur_token = 0; - r = mailimf_msg_id_list_parse(env->env_in_reply_to, - strlen(env->env_in_reply_to), &cur_token, &msg_id_list); - if (r == MAILIMF_NO_ERROR) { - Array * msgids; - - msgids = msg_id_to_string_array(msg_id_list); - setInReplyTo(msgids); - // in-reply-to - clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL); - clist_free(msg_id_list); - } - } - - if (env->env_message_id != NULL) { - char * msgid; - size_t cur_token; - int r; - - cur_token = 0; - r = mailimf_msg_id_parse(env->env_message_id, strlen(env->env_message_id), - &cur_token, &msgid); - if (r == MAILIMF_NO_ERROR) { - // msg id - String * str; - - str = String::stringWithUTF8Characters(msgid); - setMessageID(str); - mailimf_msg_id_free(msgid); - } - } -} - -void MessageHeader::importIMAPReferences(Data * data) -{ - size_t cur_token; - struct mailimf_fields * fields; - int r; - struct mailimf_single_fields single_fields; - - cur_token = 0; - r = mailimf_fields_parse(data->bytes(), data->length(), &cur_token, &fields); - if (r != MAILIMF_NO_ERROR) { - return; - } - - mailimf_single_fields_init(&single_fields, fields); - if (single_fields.fld_references != NULL) { - Array * msgids; - - msgids = msg_id_to_string_array(single_fields.fld_references->mid_list); - setReferences(msgids); - } - if (single_fields.fld_subject != NULL) { - if (single_fields.fld_subject->sbj_value != NULL) { - bool broken; - char * value; - bool isASCII; - - broken = false; - value = single_fields.fld_subject->sbj_value; - - isASCII = true; - for(char * p = value ; * p != 0 ; p ++) { - if ((unsigned char) * p >= 128) { - isASCII = false; - } - } - if (strstr(value, "windows-1251") == NULL) { - if (isASCII) { - broken = true; - } - } - - //MCLog("charset: %s %s", value, MCUTF8(charset)); - - if (!broken) { - setSubject(String::stringByDecodingMIMEHeaderValue(single_fields.fld_subject->sbj_value)); - } - } - } - - mailimf_fields_free(fields); -} - -void MessageHeader::importIMAPInternalDate(struct mailimap_date_time * date) -{ - setReceivedDate(timestampFromIMAPDate(date)); -} - -Array * MessageHeader::recipientWithReplyAll(bool replyAll, bool includeTo, bool includeCc, Array * senderEmails) -{ - bool hasCc; - bool hasTo; - Set * addedAddresses; - Array * toField; - Array * ccField; - bool containsSender; - - toField = NULL; - ccField = NULL; - - hasTo = false; - hasCc = false; - addedAddresses = new Set(); - - containsSender = false; - if (senderEmails != NULL) { - if (from() != NULL) { - if (senderEmails->containsObject(from()->mailbox()->lowercaseString())) { - containsSender = true; - } - } - if (sender() != NULL) { - if (senderEmails->containsObject(sender()->mailbox()->lowercaseString())) { - containsSender = true; - } - } - } - - if (containsSender) { - Array * recipient; - - recipient = new Array(); - if (to() != NULL) { - for(unsigned int i = 0 ; i < to()->count() ; i ++) { - Address * address = (Address *) to()->objectAtIndex(i); - if (addedAddresses->containsObject(address->mailbox()->lowercaseString())) { - continue; - } - if ((from() != NULL) && address->mailbox()->isEqualCaseInsensitive(from()->mailbox())) { - recipient->addObjectsFromArray(replyTo()); - for(unsigned int j = 0 ; j < replyTo()->count() ; j ++) { - Address * rtAddress = (Address *) replyTo()->objectAtIndex(j); - if (addedAddresses->containsObject(rtAddress->mailbox()->lowercaseString())) { - continue; - } - addedAddresses->addObject(rtAddress->mailbox()->lowercaseString()); - } - } - else { - if (address->mailbox() != NULL) { - recipient->addObject(address); - addedAddresses->addObject(address->mailbox()->lowercaseString()); - } - } - hasTo = true; - } - } - toField = recipient; - toField->retain()->autorelease(); - recipient->release(); - - if (replyAll) { - recipient = new Array(); - if (cc() != NULL) { - for(unsigned int i = 0 ; i < cc()->count() ; i ++) { - Address * address = (Address *) cc()->objectAtIndex(i); - if (addedAddresses->containsObject(address->mailbox()->lowercaseString())) { - continue; - } - if (address->mailbox() == NULL) - continue; - recipient->addObject(address); - addedAddresses->addObject(address->mailbox()->lowercaseString()); - hasCc = true; - } - } - ccField = recipient; - ccField->retain()->autorelease(); - recipient->release(); - } - - if (!hasTo && !hasCc) { - hasTo = true; - toField = Array::arrayWithObject(from()); - } - } - else { - addedAddresses->addObjectsFromArray(senderEmails); - - if (replyTo() != NULL && replyTo()->count() > 0) { - hasTo = true; - toField = replyTo(); - for(unsigned int i = 0 ; i < replyTo()->count() ; i ++) { - Address * address = (Address *) replyTo()->objectAtIndex(i); - if (address->mailbox() == NULL) - continue; - addedAddresses->addObject(address->mailbox()->lowercaseString()); - } - } - else { - if (from() != NULL && from()->mailbox() != NULL) { - hasTo = true; - toField = Array::arrayWithObject(from()); - addedAddresses->addObject(from()->mailbox()->lowercaseString()); - } - } - - if (replyAll) { - Array * recipient; - - recipient = new Array(); - if (to() != NULL) { - for(unsigned int i = 0 ; i < to()->count() ; i ++) { - Address * address = (Address *) to()->objectAtIndex(i); - if (addedAddresses->containsObject(address->mailbox()->lowercaseString())) { - continue; - } - if (address->mailbox() == NULL) - continue; - recipient->addObject(address); - addedAddresses->addObject(address->mailbox()->lowercaseString()); - } - } - if (cc() != NULL) { - for(unsigned int i = 0 ; i < cc()->count() ; i ++) { - Address * address = (Address *) cc()->objectAtIndex(i); - if (addedAddresses->containsObject(address->mailbox()->lowercaseString())) { - continue; - } - if (address->mailbox() == NULL) - continue; - recipient->addObject(address); - addedAddresses->addObject(address->mailbox()->lowercaseString()); - } - } - if (recipient->count() > 0) { - hasCc = true; - } - ccField = recipient; - ccField->retain()->autorelease(); - recipient->release(); - } - } - - addedAddresses->release(); - - Array * result; - result = Array::array(); - if (hasTo && includeTo) - result->addObjectsFromArray(toField); - if (hasCc && includeCc) - result->addObjectsFromArray(ccField); - - return result; -} - -MessageHeader * MessageHeader::replyHeader(bool replyAll, Array * addressesExcludedFromRecipient) -{ - MessageHeader * result; - String * subjectValue; - Array * referencesValue; - Array * inReplyTo; - Array * toValue; - Array * ccValue; - - referencesValue = NULL; - inReplyTo = NULL; - - result = new MessageHeader(); - if (subject() == NULL) { - subjectValue = MCSTR("Re: "); - } - else { - subjectValue = MCSTR("Re: ")->stringByAppendingString(subject()); - } - if (references() != NULL) { - referencesValue = (Array *) (references()->copy()); - referencesValue->autorelease(); - if (messageID() != NULL ) { - referencesValue->addObject(messageID()); - } - } - if (messageID()) { - inReplyTo = Array::array(); - inReplyTo->addObject(messageID()); - } - toValue = recipientWithReplyAll(replyAll, true, false, addressesExcludedFromRecipient); - ccValue = recipientWithReplyAll(replyAll, false, true, addressesExcludedFromRecipient);; - - result->setSubject(subjectValue); - result->setReferences(referencesValue); - result->setInReplyTo(inReplyTo); - result->setTo(toValue); - result->setCc(ccValue); - - result->autorelease(); - return result; -} - -MessageHeader * MessageHeader::forwardHeader() -{ - MessageHeader * result; - String * subjectValue; - Array * referencesValue; - Array * inReplyTo; - - referencesValue = NULL; - inReplyTo = NULL; - - result = new MessageHeader(); - if (subject() == NULL) { - subjectValue = MCSTR("Fw: "); - } - else { - subjectValue = MCSTR("Fw: ")->stringByAppendingString(subject()); - } - if (references() != NULL) { - referencesValue = (Array *) (references()->copy()); - referencesValue->autorelease(); - if (messageID() != NULL ) { - referencesValue->addObject(messageID()); - } - } - if (messageID() != NULL) { - inReplyTo = Array::array(); - inReplyTo->addObject(messageID()); - } - result->setSubject(subjectValue); - result->setReferences(referencesValue); - result->setInReplyTo(inReplyTo); - - result->autorelease(); - return result; -} - -HashMap * MessageHeader::serializable() -{ - HashMap * result = Object::serializable(); - - if (messageID() != NULL) { - result->setObjectForKey(MCSTR("messageID"), messageID()); - } - if (mMessageIDAutoGenerated) { - result->setObjectForKey(MCSTR("messageIDAutoGenerated"), Value::valueWithBoolValue(true)); - } - if (references() != NULL) { - result->setObjectForKey(MCSTR("references"), references()); - } - if (inReplyTo() != NULL) { - result->setObjectForKey(MCSTR("inReplyTo"), inReplyTo()); - } - if (sender() != NULL) { - result->setObjectForKey(MCSTR("sender"), sender()->serializable()); - } - if (from() != NULL) { - result->setObjectForKey(MCSTR("from"), from()->serializable()); - } - if (to() != NULL) { - result->setObjectForKey(MCSTR("to"), to()->serializable()); - } - if (cc() != NULL) { - result->setObjectForKey(MCSTR("cc"), cc()->serializable()); - } - if (bcc() != NULL) { - result->setObjectForKey(MCSTR("bcc"), bcc()->serializable()); - } - if (replyTo() != NULL) { - result->setObjectForKey(MCSTR("replyTo"), replyTo()->serializable()); - } - if (subject() != NULL) { - result->setObjectForKey(MCSTR("subject"), subject()); - } - result->setObjectForKey(MCSTR("date"), String::stringWithUTF8Format("%lld", (unsigned long long) date())); - result->setObjectForKey(MCSTR("receivedDate"), String::stringWithUTF8Format("%lld", (unsigned long long) receivedDate())); - if (mExtraHeaders != NULL) { - result->setObjectForKey(MCSTR("extraHeaders"), mExtraHeaders); - } - - return result; -} - -void MessageHeader::importSerializable(HashMap * hashmap) -{ - setMessageID((String *) hashmap->objectForKey(MCSTR("messageID"))); - - Value * value = (Value *)hashmap->objectForKey(MCSTR("messageIDAutoGenerated")); - mMessageIDAutoGenerated = value != NULL && value->boolValue(); - - setReferences((Array *) hashmap->objectForKey(MCSTR("references"))); - setInReplyTo((Array *) hashmap->objectForKey(MCSTR("inReplyTo"))); - setSender((Address *) Object::objectWithSerializable((HashMap *) hashmap->objectForKey(MCSTR("sender")))); - setFrom((Address *) Object::objectWithSerializable((HashMap *) hashmap->objectForKey(MCSTR("from")))); - setTo((Array *) Object::objectWithSerializable((HashMap *) hashmap->objectForKey(MCSTR("to")))); - setCc((Array *)Object::objectWithSerializable((HashMap *) hashmap->objectForKey(MCSTR("cc")))); - setBcc((Array *)Object::objectWithSerializable((HashMap *) hashmap->objectForKey(MCSTR("bcc")))); - setReplyTo((Array *)Object::objectWithSerializable((HashMap *) hashmap->objectForKey(MCSTR("replyTo")))); - setSubject((String *) hashmap->objectForKey(MCSTR("subject"))); - setDate((time_t) ((String *) hashmap->objectForKey(MCSTR("date")))->unsignedLongLongValue()); - setReceivedDate((time_t) ((String *) hashmap->objectForKey(MCSTR("receivedDate")))->unsignedLongLongValue()); - setExtraHeaders((HashMap *) hashmap->objectForKey(MCSTR("extraHeaders"))); -} - -static void * createObject() -{ - return new MessageHeader(); -} - -INITIALIZE(MessageHeader) -{ - Object::registerObjectConstructor("mailcore::MessageHeader", &createObject); -} diff --git a/src/core/abstract/MCMessageHeader.cpp b/src/core/abstract/MCMessageHeader.cpp new file mode 100644 index 00000000..bc141424 --- /dev/null +++ b/src/core/abstract/MCMessageHeader.cpp @@ -0,0 +1,1291 @@ +#include "MCWin32.h" // should be first include. + +#include "MCMessageHeader.h" + +#include "MCDefines.h" +#include "MCAddress.h" +#include "MCIterator.h" +#include "MCLibetpan.h" + +#include +#ifndef _MSC_VER +#include +#endif +#include + +using namespace mailcore; + +static struct mailimf_address_list * lep_address_list_from_array(Array * addresses); +static struct mailimf_mailbox_list * lep_mailbox_list_from_array(Array * addresses); +static Array * lep_address_list_from_lep_addr(struct mailimf_address_list * addr_list); +static Array * lep_address_list_from_lep_mailbox(struct mailimf_mailbox_list * mb_list); + +static Array * msg_id_to_string_array(clist * msgids); +static clist * msg_id_from_string_array(Array * msgids); + +#define MAX_HOSTNAME 512 + +MessageHeader::MessageHeader() +{ + init(true, true); +} + +MessageHeader::MessageHeader(MessageHeader * other) +{ + init(false, other->mMessageID == NULL); + if (other->mMessageID != NULL) { + setMessageID(other->mMessageID); + mMessageIDAutoGenerated = other->isMessageIDAutoGenerated(); + } + setReferences(other->mReferences); + setInReplyTo(other->mInReplyTo); + setSender(other->mSender); + setFrom(other->mFrom); + setTo(other->mTo); + setCc(other->mCc); + setBcc(other->mBcc); + setReplyTo(other->mReplyTo); + setSubject(other->mSubject); + setDate(other->date()); + setReceivedDate(other->receivedDate()); + setExtraHeaders(other->mExtraHeaders); +} + +void MessageHeader::init(bool generateDate, bool generateMessageID) +{ + mMessageID = NULL; + mMessageIDAutoGenerated = false; + mReferences = NULL; + mInReplyTo = NULL; + mSender = NULL; + mFrom = NULL; + mTo = NULL; + mCc = NULL; + mBcc = NULL; + mReplyTo = NULL; + mSubject = NULL; + mDate = (time_t) -1; + mReceivedDate = (time_t) -1; + mExtraHeaders = NULL; + + if (generateDate) { + time_t date; + date = time(NULL); + setDate(date); + setReceivedDate(date); + } + if (generateMessageID) { + static String * hostname = NULL; + static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + + pthread_mutex_lock(&lock); + if (hostname == NULL) { + char name[MAX_HOSTNAME]; + int r; + + r = gethostname(name, MAX_HOSTNAME); + if (r < 0) { + hostname = NULL; + } + else { + hostname = new String(name); + } + if (hostname == NULL) { + hostname = new String("localhost"); + } + } + pthread_mutex_unlock(&lock); + + String * messageID = new String(); + messageID->appendString(String::uuidString()); + messageID->appendUTF8Characters("@"); + messageID->appendString(hostname); + setMessageID(messageID); + messageID->release(); + + mMessageIDAutoGenerated = true; + } +} + +MessageHeader::~MessageHeader() +{ + MC_SAFE_RELEASE(mMessageID); + MC_SAFE_RELEASE(mReferences); + MC_SAFE_RELEASE(mInReplyTo); + MC_SAFE_RELEASE(mSender); + MC_SAFE_RELEASE(mFrom); + MC_SAFE_RELEASE(mTo); + MC_SAFE_RELEASE(mCc); + MC_SAFE_RELEASE(mBcc); + MC_SAFE_RELEASE(mReplyTo); + MC_SAFE_RELEASE(mSubject); + MC_SAFE_RELEASE(mExtraHeaders); +} + +String * MessageHeader::description() +{ + String * result = String::string(); + result->appendUTF8Format("<%s:%p\n", className()->UTF8Characters(), this); + if (mMessageID != NULL) { + result->appendUTF8Format("Message-ID: %s\n", mMessageID->UTF8Characters()); + } + if (mReferences != NULL) { + result->appendUTF8Format("References: %s\n", mReferences->description()->UTF8Characters()); + } + if (mInReplyTo != NULL) { + result->appendUTF8Format("In-Reply-To: %s\n", mInReplyTo->description()->UTF8Characters()); + } + if (mSender != NULL) { + result->appendUTF8Format("Sender: %s\n", mSender->description()->UTF8Characters()); + } + if (mFrom != NULL) { + result->appendUTF8Format("From: %s\n", mFrom->description()->UTF8Characters()); + } + if (mTo != NULL) { + result->appendUTF8Format("To: %s\n", mTo->description()->UTF8Characters()); + } + if (mCc != NULL) { + result->appendUTF8Format("Cc: %s\n", mCc->description()->UTF8Characters()); + } + if (mBcc != NULL) { + result->appendUTF8Format("Bcc: %s\n", mBcc->description()->UTF8Characters()); + } + if (mReplyTo != NULL) { + result->appendUTF8Format("Reply-To: %s\n", mReplyTo->description()->UTF8Characters()); + } + if (mSubject != NULL) { + result->appendUTF8Format("Subject: %s\n", mSubject->UTF8Characters()); + } + if (mExtraHeaders != NULL) { + mc_foreachhashmapKeyAndValue(String, header, String, value, mExtraHeaders) { + result->appendUTF8Format("%s: %s\n", header->UTF8Characters(), value->UTF8Characters()); + } + } + result->appendUTF8Format(">"); + + return result; +} + +Object * MessageHeader::copy() +{ + return new MessageHeader(this); +} + +void MessageHeader::setMessageID(String * messageID) +{ + MC_SAFE_REPLACE_COPY(String, mMessageID, messageID); + mMessageIDAutoGenerated = false; +} + +String * MessageHeader::messageID() +{ + return mMessageID; +} + +bool MessageHeader::isMessageIDAutoGenerated() +{ + return mMessageIDAutoGenerated; +} + +void MessageHeader::setReferences(Array * references) +{ + MC_SAFE_REPLACE_COPY(Array, mReferences, references); +} + +Array * MessageHeader::references() +{ + return mReferences; +} + +void MessageHeader::setInReplyTo(Array * inReplyTo) +{ + MC_SAFE_REPLACE_COPY(Array, mInReplyTo, inReplyTo); +} + +Array * MessageHeader::inReplyTo() +{ + return mInReplyTo; +} + +void MessageHeader::setDate(time_t date) +{ + mDate = date; +} + +time_t MessageHeader::date() +{ + return mDate; +} + +void MessageHeader::setReceivedDate(time_t date) +{ + mReceivedDate = date; +} + +time_t MessageHeader::receivedDate() +{ + return mReceivedDate; +} + +void MessageHeader::setSender(Address * sender) +{ + MC_SAFE_REPLACE_RETAIN(Address, mSender, sender); +} + +Address * MessageHeader::sender() +{ + return mSender; +} + +void MessageHeader::setFrom(Address * from) +{ + MC_SAFE_REPLACE_RETAIN(Address, mFrom, from); +} + +Address * MessageHeader::from() +{ + return mFrom; +} + +void MessageHeader::setTo(Array * to) +{ + MC_SAFE_REPLACE_COPY(Array, mTo, to); +} + +Array * MessageHeader::to() +{ + return mTo; +} + +void MessageHeader::setCc(Array * cc) +{ + MC_SAFE_REPLACE_COPY(Array, mCc, cc); +} + +Array * MessageHeader::cc() +{ + return mCc; +} + +void MessageHeader::setBcc(Array * bcc) +{ + MC_SAFE_REPLACE_COPY(Array, mBcc, bcc); +} + +Array * MessageHeader::bcc() +{ + return mBcc; +} + +void MessageHeader::setReplyTo(Array * replyTo) +{ + MC_SAFE_REPLACE_COPY(Array, mReplyTo, replyTo); +} + +Array * MessageHeader::replyTo() +{ + return mReplyTo; +} + +void MessageHeader::setSubject(String * subject) +{ + MC_SAFE_REPLACE_COPY(String, mSubject, subject); +} + +String * MessageHeader::subject() +{ + return mSubject; +} + +void MessageHeader::setUserAgent(String * userAgent) +{ + setExtraHeader(MCSTR("X-Mailer"), userAgent); +} + +String * MessageHeader::userAgent() +{ + return extraHeaderValueForName(MCSTR("X-Mailer")); +} + +void MessageHeader::setExtraHeaders(HashMap * headers) +{ + MC_SAFE_REPLACE_COPY(HashMap, mExtraHeaders, headers); +} + +Array * MessageHeader::allExtraHeadersNames() +{ + if (mExtraHeaders == NULL) + return Array::array(); + return mExtraHeaders->allKeys(); +} + +void MessageHeader::setExtraHeader(String * name, String * object) +{ + if (mExtraHeaders == NULL) { + mExtraHeaders = new HashMap(); + } + removeExtraHeader(name); + mExtraHeaders->setObjectForKey(name, object); +} + +void MessageHeader::removeExtraHeader(String * name) +{ + if (mExtraHeaders == NULL) + return; + mc_foreachhashmapKey(String, key, mExtraHeaders) { + if (key->isEqualCaseInsensitive(name)) { + mExtraHeaders->removeObjectForKey(key); + break; + } + } +} + +String * MessageHeader::extraHeaderValueForName(String * name) +{ + String * result = NULL; + mc_foreachhashmapKey(String, key, mExtraHeaders) { + if (key->isEqualCaseInsensitive(name)) { + result = (String *) mExtraHeaders->objectForKey(key); + } + } + return result; +} + +String * MessageHeader::extractedSubject() +{ + if (subject() == NULL) + return NULL; + return subject()->extractedSubject(); +} + +String * MessageHeader::partialExtractedSubject() +{ + if (subject() == NULL) + return NULL; + return subject()->extractedSubjectAndKeepBracket(true); +} + +void MessageHeader::importHeadersData(Data * data) +{ + size_t cur_token; + struct mailimf_fields * fields; + int r; + + cur_token = 0; + r = mailimf_envelope_and_optional_fields_parse(data->bytes(), data->length(), &cur_token, &fields); + if (r != MAILIMF_NO_ERROR) { + return; + } + + importIMFFields(fields); + + mailimf_fields_free(fields); +} + +void MessageHeader::importIMFFields(struct mailimf_fields * fields) +{ + struct mailimf_single_fields single_fields; + + mailimf_single_fields_init(&single_fields, fields); + + /* date */ + + if (single_fields.fld_orig_date != NULL) { + time_t timestamp; + timestamp = timestampFromDate(single_fields.fld_orig_date->dt_date_time); + setDate(timestamp); + setReceivedDate(timestamp); + //MCLog("%lu %lu", (unsigned long) timestamp, date()); + } + + /* subject */ + if (single_fields.fld_subject != NULL) { + char * subject; + + subject = single_fields.fld_subject->sbj_value; + setSubject(String::stringByDecodingMIMEHeaderValue(subject)); + } + + /* sender */ + if (single_fields.fld_sender != NULL) { + struct mailimf_mailbox * mb; + Address * address; + + mb = single_fields.fld_sender->snd_mb; + if (mb != NULL) { + address = Address::addressWithIMFMailbox(mb); + setSender(address); + } + } + + /* from */ + if (single_fields.fld_from != NULL) { + struct mailimf_mailbox_list * mb_list; + Array * addresses; + + mb_list = single_fields.fld_from->frm_mb_list; + addresses = lep_address_list_from_lep_mailbox(mb_list); + if (addresses->count() > 0) { + setFrom((Address *) (addresses->objectAtIndex(0))); + } + } + + /* replyto */ + if (single_fields.fld_reply_to != NULL) { + struct mailimf_address_list * addr_list; + Array * addresses; + + addr_list = single_fields.fld_reply_to->rt_addr_list; + addresses = lep_address_list_from_lep_addr(addr_list); + setReplyTo(addresses); + } + + /* to */ + if (single_fields.fld_to != NULL) { + struct mailimf_address_list * addr_list; + Array * addresses; + + addr_list = single_fields.fld_to->to_addr_list; + addresses = lep_address_list_from_lep_addr(addr_list); + setTo(addresses); + } + + /* cc */ + if (single_fields.fld_cc != NULL) { + struct mailimf_address_list * addr_list; + Array * addresses; + + addr_list = single_fields.fld_cc->cc_addr_list; + addresses = lep_address_list_from_lep_addr(addr_list); + setCc(addresses); + } + + /* bcc */ + if (single_fields.fld_bcc != NULL) { + struct mailimf_address_list * addr_list; + Array * addresses; + + addr_list = single_fields.fld_bcc->bcc_addr_list; + addresses = lep_address_list_from_lep_addr(addr_list); + setBcc(addresses); + } + + /* msgid */ + if (single_fields.fld_message_id != NULL) { + char * msgid; + String * str; + + msgid = single_fields.fld_message_id->mid_value; + str = String::stringWithUTF8Characters(msgid); + setMessageID(str); + } + + /* references */ + if (single_fields.fld_references != NULL) { + clist * msg_id_list; + Array * msgids; + + msg_id_list = single_fields.fld_references->mid_list; + msgids = msg_id_to_string_array(msg_id_list); + setReferences(msgids); + } + + /* inreplyto */ + if (single_fields.fld_in_reply_to != NULL) { + clist * msg_id_list; + Array * msgids; + + msg_id_list = single_fields.fld_in_reply_to->mid_list; + msgids = msg_id_to_string_array(msg_id_list); + setInReplyTo(msgids); + } + + // Take care of other headers. + for(clistiter * cur = clist_begin(fields->fld_list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimf_field * field; + + field = (mailimf_field *)clist_content(cur); + + if (field->fld_type != MAILIMF_FIELD_OPTIONAL_FIELD) { + continue; + } + + char * fieldName; + String * fieldNameStr; + + fieldName = field->fld_data.fld_optional_field->fld_name; + fieldNameStr = String::stringWithUTF8Characters(fieldName); + // Set only if this optional-field is not set + if (extraHeaderValueForName(fieldNameStr) == NULL) { + char * fieldValue; + String * fieldValueStr; + + fieldValue = field->fld_data.fld_optional_field->fld_value; + fieldValueStr = String::stringByDecodingMIMEHeaderValue(fieldValue); + setExtraHeader(fieldNameStr, fieldValueStr); + } + } +} + +#pragma mark RFC 2822 mailbox conversion + +static Array * lep_address_list_from_lep_mailbox(struct mailimf_mailbox_list * mb_list) +{ + Array * result; + clistiter * cur; + + result = Array::array(); + for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + Address * address; + + mb = (struct mailimf_mailbox *) clist_content(cur); + address = Address::addressWithIMFMailbox(mb); + result->addObject(address); + } + + return result; +} + +static Array * lep_address_list_from_lep_addr(struct mailimf_address_list * addr_list) +{ + Array * result; + clistiter * cur; + + result = Array::array(); + + if (addr_list == NULL) { + return result; + } + + if (addr_list->ad_list == NULL) { + return result; + } + + for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_address * addr; + + addr = (struct mailimf_address *) clist_content(cur); + switch (addr->ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + { + Address * address; + + address = Address::addressWithIMFMailbox(addr->ad_data.ad_mailbox); + result->addObject(address); + break; + } + + case MAILIMF_ADDRESS_GROUP: + { + if (addr->ad_data.ad_group->grp_mb_list != NULL) { + Array * subArray; + + subArray = lep_address_list_from_lep_mailbox(addr->ad_data.ad_group->grp_mb_list); + result->addObjectsFromArray(subArray); + } + break; + } + } + } + + return result; +} + +static struct mailimf_mailbox_list * lep_mailbox_list_from_array(Array * addresses) +{ + struct mailimf_mailbox_list * mb_list; + + if (addresses == NULL) + return NULL; + + if (addresses->count() == 0) + return NULL; + + mb_list = mailimf_mailbox_list_new_empty(); + + for(unsigned i = 0 ; i < addresses->count() ; i ++) { + Address * address = (Address *) addresses->objectAtIndex(i); + struct mailimf_mailbox * mailbox = address->createIMFMailbox(); + mailimf_mailbox_list_add(mb_list, mailbox); + } + + return mb_list; +} + +static struct mailimf_address_list * lep_address_list_from_array(Array * addresses) +{ + struct mailimf_address_list * addr_list; + + if (addresses == NULL) + return NULL; + + if (addresses->count() == 0) + return NULL; + + addr_list = mailimf_address_list_new_empty(); + + for(unsigned i = 0 ; i < addresses->count() ; i ++) { + Address * address = (Address *) addresses->objectAtIndex(i); + struct mailimf_address * addr = address->createIMFAddress(); + mailimf_address_list_add(addr_list, addr); + } + + return addr_list; +} + +#pragma mark Message-ID conversion + +static Array * msg_id_to_string_array(clist * msgids) +{ + clistiter * cur; + Array * result; + + result = Array::array(); + + for(cur = clist_begin(msgids) ; cur != NULL ; cur = clist_next(cur)) { + char * msgid; + String * str; + + msgid = (char *) clist_content(cur); + str = String::stringWithUTF8Characters(msgid); + result->addObject(str); + } + + return result; +} + +static clist * msg_id_from_string_array(Array * msgids) +{ + clist * result; + + if (msgids == NULL) + return NULL; + + if (msgids->count() == 0) + return NULL; + + result = clist_new(); + for(unsigned int i = 0 ; i < msgids->count() ; i ++) { + String * msgid = (String *) msgids->objectAtIndex(i); + clist_append(result, strdup(msgid->UTF8Characters())); + } + + return result; +} + +struct mailimf_fields * MessageHeader::createIMFFieldsAndFilterBcc(bool filterBcc) +{ + struct mailimf_date_time * imfDate; + char * imfMsgid; + char * imfSubject; + struct mailimf_mailbox_list * imfFrom; + struct mailimf_address_list * imfReplyTo; + struct mailimf_address_list * imfTo; + struct mailimf_address_list * imfCc; + struct mailimf_address_list * imfBcc; + clist * imfInReplyTo; + clist * imfReferences; + struct mailimf_fields * fields; + + imfDate = NULL; + if (date() != (time_t) -1) { + //MCLog("%lu", date()); + imfDate = dateFromTimestamp(date()); + } + imfFrom = NULL; + if (from() != NULL) { + imfFrom = lep_mailbox_list_from_array(Array::arrayWithObject(from())); + } + imfReplyTo = lep_address_list_from_array(replyTo()); + imfTo = lep_address_list_from_array(to()); + imfCc = lep_address_list_from_array(cc()); + imfBcc = NULL; + if (!filterBcc) { + imfBcc = lep_address_list_from_array(bcc()); + } + imfMsgid = NULL; + if (messageID() != NULL) { + imfMsgid = strdup(messageID()->UTF8Characters()); + } + imfInReplyTo = msg_id_from_string_array(inReplyTo()); + imfReferences = msg_id_from_string_array(references()); + imfSubject = NULL; + if ((subject() != NULL) && (subject()->length() > 0)) { + Data * data; + + data = subject()->encodedMIMEHeaderValueForSubject(); + if (data->bytes() != NULL) { + imfSubject = strdup(data->bytes()); + } + } + + if ((imfTo == NULL) && (imfCc == NULL) && (imfBcc == NULL)) { + imfTo = mailimf_address_list_new_empty(); + mailimf_address_list_add_parse(imfTo, (char *) "Undisclosed recipients:;"); + } + + fields = mailimf_fields_new_with_data_all(imfDate, + imfFrom, + NULL /* sender */, + imfReplyTo, + imfTo, + imfCc, + imfBcc, + imfMsgid, + imfInReplyTo, + imfReferences, + imfSubject); + + if (mExtraHeaders != NULL) { + mc_foreachhashmapKeyAndValue(String, header, String, value, mExtraHeaders) { + struct mailimf_field * field; + + field = mailimf_field_new_custom(strdup(header->UTF8Characters()), strdup(value->UTF8Characters())); + mailimf_fields_add(fields, field); + } + } + + return fields; +} + +extern "C" { + extern int mailimap_hack_date_time_parse(char * str, + struct mailimap_date_time ** result, + size_t progr_rate, + progress_function * progr_fun); +} + +#pragma mark IMAP mailbox conversion + +static Array * imap_mailbox_list_to_address_array(clist * imap_mailbox_list) +{ + clistiter * cur; + Array * result; + + result = Array::array(); + + for(cur = clist_begin(imap_mailbox_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_address * imap_addr; + Address * address; + + imap_addr = (struct mailimap_address *) clist_content(cur); + address = Address::addressWithIMAPAddress(imap_addr); + result->addObject(address); + } + + return result; +} + +void MessageHeader::importIMAPEnvelope(struct mailimap_envelope * env) +{ + if (env->env_date != NULL) { + size_t cur_token; + struct mailimf_date_time * date_time; + int r; + + cur_token = 0; + r = mailimf_date_time_parse(env->env_date, strlen(env->env_date), + &cur_token, &date_time); + if (r == MAILIMF_NO_ERROR) { + time_t timestamp; + + // date + timestamp = timestampFromDate(date_time); + setDate(timestamp); + setReceivedDate(timestamp); + mailimf_date_time_free(date_time); + } + else { + struct mailimap_date_time * imap_date; + + r = mailimap_hack_date_time_parse(env->env_date, &imap_date, 0, NULL); + if (r == MAILIMAP_NO_ERROR) { + time_t timestamp; + + timestamp = timestampFromIMAPDate(imap_date); + setDate(timestamp); + setReceivedDate(timestamp); + mailimap_date_time_free(imap_date); + } + } + } + + if (env->env_subject != NULL) { + char * subject; + + // subject + subject = env->env_subject; + setSubject(String::stringByDecodingMIMEHeaderValue(subject)); + } + + if (env->env_sender != NULL) { + if (env->env_sender->snd_list != NULL) { + Array * addresses; + + addresses = imap_mailbox_list_to_address_array(env->env_sender->snd_list); + if (addresses->count() > 0) { + setSender((Address *) addresses->objectAtIndex(0)); + } + } + } + + if (env->env_from != NULL) { + if (env->env_from->frm_list != NULL) { + Array * addresses; + + addresses = imap_mailbox_list_to_address_array(env->env_from->frm_list); + if (addresses->count() > 0) { + setFrom((Address *) addresses->objectAtIndex(0)); + } + } + } + + // skip Sender header + + if (env->env_reply_to != NULL) { + if (env->env_reply_to->rt_list != NULL) { + Array * addresses; + + addresses = imap_mailbox_list_to_address_array(env->env_reply_to->rt_list); + setReplyTo(addresses); + } + } + + if (env->env_to != NULL) { + if (env->env_to->to_list != NULL) { + Array * addresses; + + addresses = imap_mailbox_list_to_address_array(env->env_to->to_list); + setTo(addresses); + } + } + + if (env->env_cc != NULL) { + if (env->env_cc->cc_list != NULL) { + Array * addresses; + + addresses = imap_mailbox_list_to_address_array(env->env_cc->cc_list); + setCc(addresses); + } + } + + if (env->env_bcc != NULL) { + if (env->env_bcc->bcc_list != NULL) { + Array * addresses; + + addresses = imap_mailbox_list_to_address_array(env->env_bcc->bcc_list); + setBcc(addresses); + } + } + + if (env->env_in_reply_to != NULL) { + size_t cur_token; + clist * msg_id_list; + int r; + + cur_token = 0; + r = mailimf_msg_id_list_parse(env->env_in_reply_to, + strlen(env->env_in_reply_to), &cur_token, &msg_id_list); + if (r == MAILIMF_NO_ERROR) { + Array * msgids; + + msgids = msg_id_to_string_array(msg_id_list); + setInReplyTo(msgids); + // in-reply-to + clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL); + clist_free(msg_id_list); + } + } + + if (env->env_message_id != NULL) { + char * msgid; + size_t cur_token; + int r; + + cur_token = 0; + r = mailimf_msg_id_parse(env->env_message_id, strlen(env->env_message_id), + &cur_token, &msgid); + if (r == MAILIMF_NO_ERROR) { + // msg id + String * str; + + str = String::stringWithUTF8Characters(msgid); + setMessageID(str); + mailimf_msg_id_free(msgid); + } + } +} + +void MessageHeader::importIMAPReferences(Data * data) +{ + size_t cur_token; + struct mailimf_fields * fields; + int r; + struct mailimf_single_fields single_fields; + + cur_token = 0; + r = mailimf_fields_parse(data->bytes(), data->length(), &cur_token, &fields); + if (r != MAILIMF_NO_ERROR) { + return; + } + + mailimf_single_fields_init(&single_fields, fields); + if (single_fields.fld_references != NULL) { + Array * msgids; + + msgids = msg_id_to_string_array(single_fields.fld_references->mid_list); + setReferences(msgids); + } + if (single_fields.fld_subject != NULL) { + if (single_fields.fld_subject->sbj_value != NULL) { + bool broken; + char * value; + bool isASCII; + + broken = false; + value = single_fields.fld_subject->sbj_value; + + isASCII = true; + for(char * p = value ; * p != 0 ; p ++) { + if ((unsigned char) * p >= 128) { + isASCII = false; + } + } + if (strstr(value, "windows-1251") == NULL) { + if (isASCII) { + broken = true; + } + } + + //MCLog("charset: %s %s", value, MCUTF8(charset)); + + if (!broken) { + setSubject(String::stringByDecodingMIMEHeaderValue(single_fields.fld_subject->sbj_value)); + } + } + } + + mailimf_fields_free(fields); +} + +void MessageHeader::importIMAPInternalDate(struct mailimap_date_time * date) +{ + setReceivedDate(timestampFromIMAPDate(date)); +} + +Array * MessageHeader::recipientWithReplyAll(bool replyAll, bool includeTo, bool includeCc, Array * senderEmails) +{ + bool hasCc; + bool hasTo; + Set * addedAddresses; + Array * toField; + Array * ccField; + bool containsSender; + + toField = NULL; + ccField = NULL; + + hasTo = false; + hasCc = false; + addedAddresses = new Set(); + + containsSender = false; + if (senderEmails != NULL) { + if (from() != NULL) { + if (senderEmails->containsObject(from()->mailbox()->lowercaseString())) { + containsSender = true; + } + } + if (sender() != NULL) { + if (senderEmails->containsObject(sender()->mailbox()->lowercaseString())) { + containsSender = true; + } + } + } + + if (containsSender) { + Array * recipient; + + recipient = new Array(); + if (to() != NULL) { + for(unsigned int i = 0 ; i < to()->count() ; i ++) { + Address * address = (Address *) to()->objectAtIndex(i); + if (addedAddresses->containsObject(address->mailbox()->lowercaseString())) { + continue; + } + if ((from() != NULL) && address->mailbox()->isEqualCaseInsensitive(from()->mailbox())) { + recipient->addObjectsFromArray(replyTo()); + for(unsigned int j = 0 ; j < replyTo()->count() ; j ++) { + Address * rtAddress = (Address *) replyTo()->objectAtIndex(j); + if (addedAddresses->containsObject(rtAddress->mailbox()->lowercaseString())) { + continue; + } + addedAddresses->addObject(rtAddress->mailbox()->lowercaseString()); + } + } + else { + if (address->mailbox() != NULL) { + recipient->addObject(address); + addedAddresses->addObject(address->mailbox()->lowercaseString()); + } + } + hasTo = true; + } + } + toField = recipient; + toField->retain()->autorelease(); + recipient->release(); + + if (replyAll) { + recipient = new Array(); + if (cc() != NULL) { + for(unsigned int i = 0 ; i < cc()->count() ; i ++) { + Address * address = (Address *) cc()->objectAtIndex(i); + if (addedAddresses->containsObject(address->mailbox()->lowercaseString())) { + continue; + } + if (address->mailbox() == NULL) + continue; + recipient->addObject(address); + addedAddresses->addObject(address->mailbox()->lowercaseString()); + hasCc = true; + } + } + ccField = recipient; + ccField->retain()->autorelease(); + recipient->release(); + } + + if (!hasTo && !hasCc) { + hasTo = true; + toField = Array::arrayWithObject(from()); + } + } + else { + addedAddresses->addObjectsFromArray(senderEmails); + + if (replyTo() != NULL && replyTo()->count() > 0) { + hasTo = true; + toField = replyTo(); + for(unsigned int i = 0 ; i < replyTo()->count() ; i ++) { + Address * address = (Address *) replyTo()->objectAtIndex(i); + if (address->mailbox() == NULL) + continue; + addedAddresses->addObject(address->mailbox()->lowercaseString()); + } + } + else { + if (from() != NULL && from()->mailbox() != NULL) { + hasTo = true; + toField = Array::arrayWithObject(from()); + addedAddresses->addObject(from()->mailbox()->lowercaseString()); + } + } + + if (replyAll) { + Array * recipient; + + recipient = new Array(); + if (to() != NULL) { + for(unsigned int i = 0 ; i < to()->count() ; i ++) { + Address * address = (Address *) to()->objectAtIndex(i); + if (addedAddresses->containsObject(address->mailbox()->lowercaseString())) { + continue; + } + if (address->mailbox() == NULL) + continue; + recipient->addObject(address); + addedAddresses->addObject(address->mailbox()->lowercaseString()); + } + } + if (cc() != NULL) { + for(unsigned int i = 0 ; i < cc()->count() ; i ++) { + Address * address = (Address *) cc()->objectAtIndex(i); + if (addedAddresses->containsObject(address->mailbox()->lowercaseString())) { + continue; + } + if (address->mailbox() == NULL) + continue; + recipient->addObject(address); + addedAddresses->addObject(address->mailbox()->lowercaseString()); + } + } + if (recipient->count() > 0) { + hasCc = true; + } + ccField = recipient; + ccField->retain()->autorelease(); + recipient->release(); + } + } + + addedAddresses->release(); + + Array * result; + result = Array::array(); + if (hasTo && includeTo) + result->addObjectsFromArray(toField); + if (hasCc && includeCc) + result->addObjectsFromArray(ccField); + + return result; +} + +MessageHeader * MessageHeader::replyHeader(bool replyAll, Array * addressesExcludedFromRecipient) +{ + MessageHeader * result; + String * subjectValue; + Array * referencesValue; + Array * inReplyTo; + Array * toValue; + Array * ccValue; + + referencesValue = NULL; + inReplyTo = NULL; + + result = new MessageHeader(); + if (subject() == NULL) { + subjectValue = MCSTR("Re: "); + } + else { + subjectValue = MCSTR("Re: ")->stringByAppendingString(subject()); + } + if (references() != NULL) { + referencesValue = (Array *) (references()->copy()); + referencesValue->autorelease(); + if (messageID() != NULL ) { + referencesValue->addObject(messageID()); + } + } + if (messageID()) { + inReplyTo = Array::array(); + inReplyTo->addObject(messageID()); + } + toValue = recipientWithReplyAll(replyAll, true, false, addressesExcludedFromRecipient); + ccValue = recipientWithReplyAll(replyAll, false, true, addressesExcludedFromRecipient);; + + result->setSubject(subjectValue); + result->setReferences(referencesValue); + result->setInReplyTo(inReplyTo); + result->setTo(toValue); + result->setCc(ccValue); + + result->autorelease(); + return result; +} + +MessageHeader * MessageHeader::forwardHeader() +{ + MessageHeader * result; + String * subjectValue; + Array * referencesValue; + Array * inReplyTo; + + referencesValue = NULL; + inReplyTo = NULL; + + result = new MessageHeader(); + if (subject() == NULL) { + subjectValue = MCSTR("Fw: "); + } + else { + subjectValue = MCSTR("Fw: ")->stringByAppendingString(subject()); + } + if (references() != NULL) { + referencesValue = (Array *) (references()->copy()); + referencesValue->autorelease(); + if (messageID() != NULL ) { + referencesValue->addObject(messageID()); + } + } + if (messageID() != NULL) { + inReplyTo = Array::array(); + inReplyTo->addObject(messageID()); + } + result->setSubject(subjectValue); + result->setReferences(referencesValue); + result->setInReplyTo(inReplyTo); + + result->autorelease(); + return result; +} + +HashMap * MessageHeader::serializable() +{ + HashMap * result = Object::serializable(); + + if (messageID() != NULL) { + result->setObjectForKey(MCSTR("messageID"), messageID()); + } + if (mMessageIDAutoGenerated) { + result->setObjectForKey(MCSTR("messageIDAutoGenerated"), Value::valueWithBoolValue(true)); + } + if (references() != NULL) { + result->setObjectForKey(MCSTR("references"), references()); + } + if (inReplyTo() != NULL) { + result->setObjectForKey(MCSTR("inReplyTo"), inReplyTo()); + } + if (sender() != NULL) { + result->setObjectForKey(MCSTR("sender"), sender()->serializable()); + } + if (from() != NULL) { + result->setObjectForKey(MCSTR("from"), from()->serializable()); + } + if (to() != NULL) { + result->setObjectForKey(MCSTR("to"), to()->serializable()); + } + if (cc() != NULL) { + result->setObjectForKey(MCSTR("cc"), cc()->serializable()); + } + if (bcc() != NULL) { + result->setObjectForKey(MCSTR("bcc"), bcc()->serializable()); + } + if (replyTo() != NULL) { + result->setObjectForKey(MCSTR("replyTo"), replyTo()->serializable()); + } + if (subject() != NULL) { + result->setObjectForKey(MCSTR("subject"), subject()); + } + result->setObjectForKey(MCSTR("date"), String::stringWithUTF8Format("%lld", (unsigned long long) date())); + result->setObjectForKey(MCSTR("receivedDate"), String::stringWithUTF8Format("%lld", (unsigned long long) receivedDate())); + if (mExtraHeaders != NULL) { + result->setObjectForKey(MCSTR("extraHeaders"), mExtraHeaders); + } + + return result; +} + +void MessageHeader::importSerializable(HashMap * hashmap) +{ + setMessageID((String *) hashmap->objectForKey(MCSTR("messageID"))); + + Value * value = (Value *)hashmap->objectForKey(MCSTR("messageIDAutoGenerated")); + mMessageIDAutoGenerated = value != NULL && value->boolValue(); + + setReferences((Array *) hashmap->objectForKey(MCSTR("references"))); + setInReplyTo((Array *) hashmap->objectForKey(MCSTR("inReplyTo"))); + setSender((Address *) Object::objectWithSerializable((HashMap *) hashmap->objectForKey(MCSTR("sender")))); + setFrom((Address *) Object::objectWithSerializable((HashMap *) hashmap->objectForKey(MCSTR("from")))); + setTo((Array *) Object::objectWithSerializable((HashMap *) hashmap->objectForKey(MCSTR("to")))); + setCc((Array *)Object::objectWithSerializable((HashMap *) hashmap->objectForKey(MCSTR("cc")))); + setBcc((Array *)Object::objectWithSerializable((HashMap *) hashmap->objectForKey(MCSTR("bcc")))); + setReplyTo((Array *)Object::objectWithSerializable((HashMap *) hashmap->objectForKey(MCSTR("replyTo")))); + setSubject((String *) hashmap->objectForKey(MCSTR("subject"))); + setDate((time_t) ((String *) hashmap->objectForKey(MCSTR("date")))->unsignedLongLongValue()); + setReceivedDate((time_t) ((String *) hashmap->objectForKey(MCSTR("receivedDate")))->unsignedLongLongValue()); + setExtraHeaders((HashMap *) hashmap->objectForKey(MCSTR("extraHeaders"))); +} + +static void * createObject() +{ + return new MessageHeader(); +} + +INITIALIZE(MessageHeader) +{ + Object::registerObjectConstructor("mailcore::MessageHeader", &createObject); +} diff --git a/src/core/basetypes/MCArray.cc b/src/core/basetypes/MCArray.cc deleted file mode 100644 index 787dd0ba..00000000 --- a/src/core/basetypes/MCArray.cc +++ /dev/null @@ -1,283 +0,0 @@ -#include "MCArray.h" - -#include -#include -#include - -#include "MCDefines.h" -#include "MCAssert.h" -#include "MCString.h" -#include "MCLog.h" -#include "MCUtils.h" -#include "MCIterator.h" - -using namespace mailcore; - -Array::Array() -{ - init(); -} - -Array::Array(Array * other) : Object() -{ - init(); - for(unsigned int i = 0 ; i < other->count() ; i ++) { - Object * obj = other->objectAtIndex(i); - addObject(obj); - } -} - -void Array::init() -{ - mArray = carray_new(4); -} - -Array::~Array() -{ - removeAllObjects(); - carray_free(mArray); -} - -Array * Array::array() -{ - Array * result = new Array(); - return (Array *) result->autorelease(); -} - -Array * Array::arrayWithObject(Object * obj) -{ - Array * result = new Array(); - result->addObject(obj); - return (Array *) result->autorelease(); -} - -String * Array::description() -{ - String * result = String::string(); - - result->appendUTF8Characters("["); - for(unsigned int i = 0 ; i < count() ; i ++) { - if (i != 0) { - result->appendUTF8Characters(","); - } - Object * obj = objectAtIndex(i); - result->appendString(obj->description()); - } - result->appendUTF8Characters("]"); - - return result; -} - -Object * Array::copy() -{ - return new Array(this); -} - -unsigned int Array::count() -{ - return carray_count(mArray); -} - -void Array::addObject(Object * obj) -{ - unsigned int idx; - obj->retain(); - carray_add(mArray, obj, &idx); -} - -void Array::removeObjectAtIndex(unsigned int idx) -{ - Object * obj = (Object *) carray_get(mArray, idx); - obj->release(); - carray_delete_slow(mArray, idx); -} - -void Array::removeObject(Object * obj) -{ - int idx = indexOfObject(obj); - if (idx == -1) - return; - - removeObjectAtIndex(idx); -} - -int Array::indexOfObject(Object * obj) -{ - for(unsigned int i = 0 ; i < count() ; i ++) { - Object * currentObj = objectAtIndex(i); - if (currentObj->isEqual(obj)) { - return i; - } - } - - return -1; -} - -Object * Array::objectAtIndex(unsigned int idx) -{ - Object * obj = (Object *) carray_get(mArray, idx); - return obj; -} - -void Array::replaceObject(unsigned int idx, Object * obj) -{ - if (idx < count()) { - Object * previousObject = (Object *) carray_get(mArray, idx); - previousObject->release(); - obj->retain(); - carray_set(mArray, idx, obj); - } - else if (idx == count()) { - addObject(obj); - } - else { - MCAssert(0); - } -} - -void Array::insertObject(unsigned int idx, Object * obj) -{ - if (idx < count()) { - int count = carray_count(mArray) - idx; - carray_set_size(mArray, count + 1); - void ** p = carray_data(mArray); - memmove(p + idx + 1, p + idx, count * sizeof(* p)); - obj->retain(); - carray_set(mArray, idx, obj); - } - else if (idx == count()) { - addObject(obj); - } - else { - MCAssert(0); - } -} - -void Array::removeAllObjects() -{ - for(unsigned int i = 0 ; i < count() ; i ++) { - Object * obj = objectAtIndex(i); - obj->release(); - } - carray_set_size(mArray, 0); -} - -void Array::addObjectsFromArray(Array * array) -{ - if (array == NULL) - return; - - for(unsigned int i = 0 ; i < array->count() ; i ++) { - Object * obj = array->objectAtIndex(i); - addObject(obj); - } -} - -Object * Array::lastObject() -{ - if (count() == 0) - return NULL; - - return objectAtIndex(count() - 1); -} - -void Array::removeLastObject() -{ - removeObjectAtIndex(count() - 1); -} - -bool Array::containsObject(Object * obj) -{ - return (indexOfObject(obj) != -1); -} - -struct sortData { - int (* compare)(void *, void *, void *); - void * context; -}; - -#if defined(__MACH__) || defined(_MSC_VER) -static int sortCompare(struct sortData * data, Object ** pa, Object ** pb) -#else -static int sortCompare(Object ** pa, Object ** pb, struct sortData * data) -#endif -{ - Object * a; - Object * b; - - a = * pa; - b = * pb; - - return data->compare(a, b, data->context); -} - -Array * Array::sortedArray(int (* compare)(void * a, void * b, void * context), void * context) -{ - Array * result = (Array *) this->copy()->autorelease(); - result->sortArray(compare, context); - return result; -} - -void Array::sortArray(int (* compare)(void * a, void * b, void * context), void * context) -{ - struct sortData data; - data.compare = compare; - data.context = context; -#ifdef __MACH__ - qsort_r(carray_data(mArray), carray_count(mArray), - sizeof(* carray_data(mArray)), &data, - (int (*)(void *, const void *, const void *)) sortCompare); -#elif defined(_MSC_VER) - qsort_s(carray_data(mArray), carray_count(mArray), - sizeof(*carray_data(mArray)), - (int(*)(void *, const void *, const void *)) sortCompare, - &data); -#else - qsort_r(carray_data(mArray), carray_count(mArray), - sizeof(* carray_data(mArray)), - (int (*)(const void *, const void *, void *)) sortCompare, - &data); -#endif -} - -String * Array::componentsJoinedByString(String * delimiter) -{ - String * result = String::string(); - for(unsigned int i = 0 ; i < count() ; i ++) { - Object * obj = objectAtIndex(i); - if (i != 0) { - result->appendString(delimiter); - } - result->appendString(obj->description()); - } - return result; -} - -HashMap * Array::serializable() -{ - HashMap * result = Object::serializable(); - Array * array = Array::array(); - mc_foreacharray(Object, item, this) { - array->addObject(item->serializable()); - } - result->setObjectForKey(MCSTR("items"), array); - return result; -} - -void Array::importSerializable(HashMap * serializable) -{ - Array * array = (Array *) serializable->objectForKey(MCSTR("items")); - mc_foreacharray(HashMap, item, array) { - addObject(Object::objectWithSerializable(item)); - } -} - -static void * createObject() -{ - return new Array(); -} - -INITIALIZE(Array) -{ - Object::registerObjectConstructor("mailcore::Array", &createObject); -} diff --git a/src/core/basetypes/MCArray.cpp b/src/core/basetypes/MCArray.cpp new file mode 100644 index 00000000..787dd0ba --- /dev/null +++ b/src/core/basetypes/MCArray.cpp @@ -0,0 +1,283 @@ +#include "MCArray.h" + +#include +#include +#include + +#include "MCDefines.h" +#include "MCAssert.h" +#include "MCString.h" +#include "MCLog.h" +#include "MCUtils.h" +#include "MCIterator.h" + +using namespace mailcore; + +Array::Array() +{ + init(); +} + +Array::Array(Array * other) : Object() +{ + init(); + for(unsigned int i = 0 ; i < other->count() ; i ++) { + Object * obj = other->objectAtIndex(i); + addObject(obj); + } +} + +void Array::init() +{ + mArray = carray_new(4); +} + +Array::~Array() +{ + removeAllObjects(); + carray_free(mArray); +} + +Array * Array::array() +{ + Array * result = new Array(); + return (Array *) result->autorelease(); +} + +Array * Array::arrayWithObject(Object * obj) +{ + Array * result = new Array(); + result->addObject(obj); + return (Array *) result->autorelease(); +} + +String * Array::description() +{ + String * result = String::string(); + + result->appendUTF8Characters("["); + for(unsigned int i = 0 ; i < count() ; i ++) { + if (i != 0) { + result->appendUTF8Characters(","); + } + Object * obj = objectAtIndex(i); + result->appendString(obj->description()); + } + result->appendUTF8Characters("]"); + + return result; +} + +Object * Array::copy() +{ + return new Array(this); +} + +unsigned int Array::count() +{ + return carray_count(mArray); +} + +void Array::addObject(Object * obj) +{ + unsigned int idx; + obj->retain(); + carray_add(mArray, obj, &idx); +} + +void Array::removeObjectAtIndex(unsigned int idx) +{ + Object * obj = (Object *) carray_get(mArray, idx); + obj->release(); + carray_delete_slow(mArray, idx); +} + +void Array::removeObject(Object * obj) +{ + int idx = indexOfObject(obj); + if (idx == -1) + return; + + removeObjectAtIndex(idx); +} + +int Array::indexOfObject(Object * obj) +{ + for(unsigned int i = 0 ; i < count() ; i ++) { + Object * currentObj = objectAtIndex(i); + if (currentObj->isEqual(obj)) { + return i; + } + } + + return -1; +} + +Object * Array::objectAtIndex(unsigned int idx) +{ + Object * obj = (Object *) carray_get(mArray, idx); + return obj; +} + +void Array::replaceObject(unsigned int idx, Object * obj) +{ + if (idx < count()) { + Object * previousObject = (Object *) carray_get(mArray, idx); + previousObject->release(); + obj->retain(); + carray_set(mArray, idx, obj); + } + else if (idx == count()) { + addObject(obj); + } + else { + MCAssert(0); + } +} + +void Array::insertObject(unsigned int idx, Object * obj) +{ + if (idx < count()) { + int count = carray_count(mArray) - idx; + carray_set_size(mArray, count + 1); + void ** p = carray_data(mArray); + memmove(p + idx + 1, p + idx, count * sizeof(* p)); + obj->retain(); + carray_set(mArray, idx, obj); + } + else if (idx == count()) { + addObject(obj); + } + else { + MCAssert(0); + } +} + +void Array::removeAllObjects() +{ + for(unsigned int i = 0 ; i < count() ; i ++) { + Object * obj = objectAtIndex(i); + obj->release(); + } + carray_set_size(mArray, 0); +} + +void Array::addObjectsFromArray(Array * array) +{ + if (array == NULL) + return; + + for(unsigned int i = 0 ; i < array->count() ; i ++) { + Object * obj = array->objectAtIndex(i); + addObject(obj); + } +} + +Object * Array::lastObject() +{ + if (count() == 0) + return NULL; + + return objectAtIndex(count() - 1); +} + +void Array::removeLastObject() +{ + removeObjectAtIndex(count() - 1); +} + +bool Array::containsObject(Object * obj) +{ + return (indexOfObject(obj) != -1); +} + +struct sortData { + int (* compare)(void *, void *, void *); + void * context; +}; + +#if defined(__MACH__) || defined(_MSC_VER) +static int sortCompare(struct sortData * data, Object ** pa, Object ** pb) +#else +static int sortCompare(Object ** pa, Object ** pb, struct sortData * data) +#endif +{ + Object * a; + Object * b; + + a = * pa; + b = * pb; + + return data->compare(a, b, data->context); +} + +Array * Array::sortedArray(int (* compare)(void * a, void * b, void * context), void * context) +{ + Array * result = (Array *) this->copy()->autorelease(); + result->sortArray(compare, context); + return result; +} + +void Array::sortArray(int (* compare)(void * a, void * b, void * context), void * context) +{ + struct sortData data; + data.compare = compare; + data.context = context; +#ifdef __MACH__ + qsort_r(carray_data(mArray), carray_count(mArray), + sizeof(* carray_data(mArray)), &data, + (int (*)(void *, const void *, const void *)) sortCompare); +#elif defined(_MSC_VER) + qsort_s(carray_data(mArray), carray_count(mArray), + sizeof(*carray_data(mArray)), + (int(*)(void *, const void *, const void *)) sortCompare, + &data); +#else + qsort_r(carray_data(mArray), carray_count(mArray), + sizeof(* carray_data(mArray)), + (int (*)(const void *, const void *, void *)) sortCompare, + &data); +#endif +} + +String * Array::componentsJoinedByString(String * delimiter) +{ + String * result = String::string(); + for(unsigned int i = 0 ; i < count() ; i ++) { + Object * obj = objectAtIndex(i); + if (i != 0) { + result->appendString(delimiter); + } + result->appendString(obj->description()); + } + return result; +} + +HashMap * Array::serializable() +{ + HashMap * result = Object::serializable(); + Array * array = Array::array(); + mc_foreacharray(Object, item, this) { + array->addObject(item->serializable()); + } + result->setObjectForKey(MCSTR("items"), array); + return result; +} + +void Array::importSerializable(HashMap * serializable) +{ + Array * array = (Array *) serializable->objectForKey(MCSTR("items")); + mc_foreacharray(HashMap, item, array) { + addObject(Object::objectWithSerializable(item)); + } +} + +static void * createObject() +{ + return new Array(); +} + +INITIALIZE(Array) +{ + Object::registerObjectConstructor("mailcore::Array", &createObject); +} diff --git a/src/core/basetypes/MCAutoreleasePool.cc b/src/core/basetypes/MCAutoreleasePool.cc deleted file mode 100644 index 67e58a78..00000000 --- a/src/core/basetypes/MCAutoreleasePool.cc +++ /dev/null @@ -1,123 +0,0 @@ -#include "MCAutoreleasePool.h" - -#include - -#include "MCString.h" -#include "MCLog.h" -#include "MCUtils.h" - -using namespace mailcore; - -pthread_key_t AutoreleasePool::autoreleasePoolStackKey; - -void AutoreleasePool::init() -{ - static pthread_once_t once = PTHREAD_ONCE_INIT; - pthread_once(&once, initAutoreleasePoolStackKey); -} - -AutoreleasePool::AutoreleasePool() -{ - mPoolObjects = carray_new(4); - -#if __APPLE__ - mAppleAutoreleasePool = createAppleAutoreleasePool(); -#endif - - unsigned int idx; - carray * stack = createAutoreleasePoolStackIfNeeded(); - carray_add(stack, this, &idx); -} - -AutoreleasePool::~AutoreleasePool() -{ -#if __APPLE__ - releaseAppleAutoreleasePool(mAppleAutoreleasePool); -#endif - - carray * stack = createAutoreleasePoolStackIfNeeded(); - carray_delete_slow(stack, carray_count(stack) - 1); - - unsigned int count = carray_count(mPoolObjects); - for(unsigned int i = 0 ; i < count ; i ++) { - Object * obj = (Object *) carray_get(mPoolObjects, i); - obj->release(); - } - carray_free(mPoolObjects); -} - -carray * AutoreleasePool::createAutoreleasePoolStackIfNeeded() -{ - init(); - carray * stack = (carray *) pthread_getspecific(autoreleasePoolStackKey); - if (stack != NULL) { - return stack; - } - - stack = carray_new(4); - pthread_setspecific(autoreleasePoolStackKey, stack); - - return stack; -} - -void AutoreleasePool::destroyAutoreleasePoolStack(void * value) -{ - carray * stack = (carray *) value; - if (carray_count(stack) != 0) { - MCLog("some autoreleasepool have not been released\n"); - } - carray_free(stack); -} - -void AutoreleasePool::initAutoreleasePoolStackKey() -{ - pthread_key_create(&autoreleasePoolStackKey, destroyAutoreleasePoolStack); -} - -AutoreleasePool * AutoreleasePool::currentAutoreleasePool() -{ - init(); - carray * stack; - stack = createAutoreleasePoolStackIfNeeded(); - if (carray_count(stack) == 0) { - //fprintf(stderr, "no current autoreleasepool\n"); - return NULL; - } - - AutoreleasePool * pool; - pool = (AutoreleasePool *) carray_get(stack, carray_count(stack) - 1); - return pool; -} - -void AutoreleasePool::add(Object * obj) -{ - unsigned int idx; - carray_add(mPoolObjects, obj, &idx); -} - -void AutoreleasePool::autorelease(Object * obj) -{ - AutoreleasePool * pool = AutoreleasePool::currentAutoreleasePool(); - if (pool == NULL) { - MCLog("-autorelease called with no current autoreleasepool\n"); - return; - } - pool->add(obj); -} - -String * AutoreleasePool::description() -{ - String * result = String::string(); - result->appendUTF8Format("<%p:%p ", className(), this); - unsigned int count = carray_count(mPoolObjects); - for(unsigned int i = 0 ; i < count ; i ++) { - Object * obj = (Object *) carray_get(mPoolObjects, i); - if (i != 0) { - result->appendUTF8Characters(" "); - } - result->appendString(obj->description()); - } - result->appendUTF8Characters(">"); - - return result; -} diff --git a/src/core/basetypes/MCAutoreleasePool.cpp b/src/core/basetypes/MCAutoreleasePool.cpp new file mode 100644 index 00000000..67e58a78 --- /dev/null +++ b/src/core/basetypes/MCAutoreleasePool.cpp @@ -0,0 +1,123 @@ +#include "MCAutoreleasePool.h" + +#include + +#include "MCString.h" +#include "MCLog.h" +#include "MCUtils.h" + +using namespace mailcore; + +pthread_key_t AutoreleasePool::autoreleasePoolStackKey; + +void AutoreleasePool::init() +{ + static pthread_once_t once = PTHREAD_ONCE_INIT; + pthread_once(&once, initAutoreleasePoolStackKey); +} + +AutoreleasePool::AutoreleasePool() +{ + mPoolObjects = carray_new(4); + +#if __APPLE__ + mAppleAutoreleasePool = createAppleAutoreleasePool(); +#endif + + unsigned int idx; + carray * stack = createAutoreleasePoolStackIfNeeded(); + carray_add(stack, this, &idx); +} + +AutoreleasePool::~AutoreleasePool() +{ +#if __APPLE__ + releaseAppleAutoreleasePool(mAppleAutoreleasePool); +#endif + + carray * stack = createAutoreleasePoolStackIfNeeded(); + carray_delete_slow(stack, carray_count(stack) - 1); + + unsigned int count = carray_count(mPoolObjects); + for(unsigned int i = 0 ; i < count ; i ++) { + Object * obj = (Object *) carray_get(mPoolObjects, i); + obj->release(); + } + carray_free(mPoolObjects); +} + +carray * AutoreleasePool::createAutoreleasePoolStackIfNeeded() +{ + init(); + carray * stack = (carray *) pthread_getspecific(autoreleasePoolStackKey); + if (stack != NULL) { + return stack; + } + + stack = carray_new(4); + pthread_setspecific(autoreleasePoolStackKey, stack); + + return stack; +} + +void AutoreleasePool::destroyAutoreleasePoolStack(void * value) +{ + carray * stack = (carray *) value; + if (carray_count(stack) != 0) { + MCLog("some autoreleasepool have not been released\n"); + } + carray_free(stack); +} + +void AutoreleasePool::initAutoreleasePoolStackKey() +{ + pthread_key_create(&autoreleasePoolStackKey, destroyAutoreleasePoolStack); +} + +AutoreleasePool * AutoreleasePool::currentAutoreleasePool() +{ + init(); + carray * stack; + stack = createAutoreleasePoolStackIfNeeded(); + if (carray_count(stack) == 0) { + //fprintf(stderr, "no current autoreleasepool\n"); + return NULL; + } + + AutoreleasePool * pool; + pool = (AutoreleasePool *) carray_get(stack, carray_count(stack) - 1); + return pool; +} + +void AutoreleasePool::add(Object * obj) +{ + unsigned int idx; + carray_add(mPoolObjects, obj, &idx); +} + +void AutoreleasePool::autorelease(Object * obj) +{ + AutoreleasePool * pool = AutoreleasePool::currentAutoreleasePool(); + if (pool == NULL) { + MCLog("-autorelease called with no current autoreleasepool\n"); + return; + } + pool->add(obj); +} + +String * AutoreleasePool::description() +{ + String * result = String::string(); + result->appendUTF8Format("<%p:%p ", className(), this); + unsigned int count = carray_count(mPoolObjects); + for(unsigned int i = 0 ; i < count ; i ++) { + Object * obj = (Object *) carray_get(mPoolObjects, i); + if (i != 0) { + result->appendUTF8Characters(" "); + } + result->appendString(obj->description()); + } + result->appendUTF8Characters(">"); + + return result; +} diff --git a/src/core/basetypes/MCConnectionLoggerUtils.cc b/src/core/basetypes/MCConnectionLoggerUtils.cc deleted file mode 100644 index 08ba2334..00000000 --- a/src/core/basetypes/MCConnectionLoggerUtils.cc +++ /dev/null @@ -1,55 +0,0 @@ -// -// MCConnectionLoggerUtils.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 6/24/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCConnectionLoggerUtils.h" - -#include - -#include "MCConnectionLogger.h" - -mailcore::ConnectionLogType mailcore::getConnectionType(int log_type) -{ - ConnectionLogType type = (ConnectionLogType) -1; - - switch (log_type) { - case MAILSTREAM_LOG_TYPE_ERROR_PARSE: - type = ConnectionLogTypeErrorParse; - break; - case MAILSTREAM_LOG_TYPE_ERROR_RECEIVED: - type = ConnectionLogTypeErrorReceived; - break; - case MAILSTREAM_LOG_TYPE_ERROR_SENT: - type = ConnectionLogTypeErrorSent; - break; - case MAILSTREAM_LOG_TYPE_DATA_RECEIVED: - type = ConnectionLogTypeReceived; - break; - case MAILSTREAM_LOG_TYPE_DATA_SENT: - type = ConnectionLogTypeSent; - break; - case MAILSTREAM_LOG_TYPE_DATA_SENT_PRIVATE: - type = ConnectionLogTypeSentPrivate; - break; - } - return type; -} - -bool mailcore::isBufferFromLogType(int log_type) -{ - bool isBuffer = false; - - switch (log_type) { - 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: - isBuffer = true; - break; - } - return isBuffer; -} diff --git a/src/core/basetypes/MCConnectionLoggerUtils.cpp b/src/core/basetypes/MCConnectionLoggerUtils.cpp new file mode 100644 index 00000000..08ba2334 --- /dev/null +++ b/src/core/basetypes/MCConnectionLoggerUtils.cpp @@ -0,0 +1,55 @@ +// +// MCConnectionLoggerUtils.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 6/24/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCConnectionLoggerUtils.h" + +#include + +#include "MCConnectionLogger.h" + +mailcore::ConnectionLogType mailcore::getConnectionType(int log_type) +{ + ConnectionLogType type = (ConnectionLogType) -1; + + switch (log_type) { + case MAILSTREAM_LOG_TYPE_ERROR_PARSE: + type = ConnectionLogTypeErrorParse; + break; + case MAILSTREAM_LOG_TYPE_ERROR_RECEIVED: + type = ConnectionLogTypeErrorReceived; + break; + case MAILSTREAM_LOG_TYPE_ERROR_SENT: + type = ConnectionLogTypeErrorSent; + break; + case MAILSTREAM_LOG_TYPE_DATA_RECEIVED: + type = ConnectionLogTypeReceived; + break; + case MAILSTREAM_LOG_TYPE_DATA_SENT: + type = ConnectionLogTypeSent; + break; + case MAILSTREAM_LOG_TYPE_DATA_SENT_PRIVATE: + type = ConnectionLogTypeSentPrivate; + break; + } + return type; +} + +bool mailcore::isBufferFromLogType(int log_type) +{ + bool isBuffer = false; + + switch (log_type) { + 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: + isBuffer = true; + break; + } + return isBuffer; +} diff --git a/src/core/basetypes/MCData.cc b/src/core/basetypes/MCData.cc deleted file mode 100644 index 0f792d1f..00000000 --- a/src/core/basetypes/MCData.cc +++ /dev/null @@ -1,908 +0,0 @@ -#include "MCWin32.h" // should be first include. - -#include "MCData.h" - -#define USE_UCHARDET 1 - -#include -#include -#include -#include -#if USE_UCHARDET -#include -#else -#include -#endif -#include -#include -#if __APPLE__ -#include -#endif - -#include "MCDefines.h" -#include "MCString.h" -#include "MCHash.h" -#include "MCUtils.h" -#include "MCHashMap.h" -#include "MCBase64.h" -#include "MCSet.h" - -#define MCDATA_DEFAULT_CHARSET "iso-8859-1" - -using namespace mailcore; - -static int isPowerOfTwo (unsigned int x) -{ - return ((x != 0) && !(x & (x - 1))); -} - -void Data::allocate(unsigned int length, bool force) -{ - if (length <= mAllocated) - return; - - if (force) { - mAllocated = length; - } - else { - if (!isPowerOfTwo(mAllocated)) { - mAllocated = 0; - } - if (mAllocated == 0) { - mAllocated = 4; - } - while (length > mAllocated) { - mAllocated *= 2; - } - } - - mBytes = (char *) realloc(mBytes, mAllocated); -} - -void Data::reset() -{ - free(mBytes); - mAllocated = 0; - mLength = 0; - mBytes = NULL; -} - -Data::Data() -{ - mBytes = NULL; - reset(); -} - -Data::Data(Data * otherData) : Object() -{ - mBytes = NULL; - reset(); - appendData(otherData); -} - -Data::Data(const char * bytes, unsigned int length) -{ - mBytes = NULL; - reset(); - allocate(length, true); - appendBytes(bytes, length); -} - -Data::Data(int capacity) -{ - mBytes = NULL; - reset(); - allocate(capacity, true); -} - -Data::~Data() -{ - reset(); -} - -Data * Data::dataWithBytes(const char * bytes, unsigned int length) -{ - Data * result = new Data(bytes, length); - return (Data *) result->autorelease(); -} - -char * Data::bytes() -{ - return mBytes; -} - -unsigned int Data::length() -{ - return mLength; -} - -void Data::appendData(Data * otherData) -{ - appendBytes(otherData->bytes(), otherData->length()); -} - -void Data::appendBytes(const char * bytes, unsigned int length) -{ - allocate(mLength + length); - memcpy(&mBytes[mLength], bytes, length); - mLength += length; -} - -void Data::setBytes(const char * bytes, unsigned int length) -{ - reset(); - appendBytes(bytes, length); -} - -void Data::setData(Data * otherData) -{ - reset(); - appendData(otherData); -} - -String * Data::description() -{ - return String::stringWithUTF8Format("<%s:%p %i bytes>", MCUTF8(className()), this, length()); -} - -Object * Data::copy() -{ - return new Data(this); -} - -bool Data::isEqual(Object * otherObject) -{ - Data * otherData = (Data *) otherObject; - if (length() != otherData->length()) - return false; - if (memcmp(bytes(), otherData->bytes(), mLength) != 0) - return false; - return true; -} - -unsigned int Data::hash() -{ - return hashCompute(mBytes, mLength); -} - -String * Data::stringWithDetectedCharset() -{ - String * result; - result = stringWithDetectedCharset(NULL, false); - return result; -} - -static String * normalizeCharset(String * charset) -{ - if ((charset->caseInsensitiveCompare(MCSTR("iso-2022-jp")) == 0) || - (charset->caseInsensitiveCompare(MCSTR("iso-2022-jp-2")) == 0)) { - charset = MCSTR("iso-2022-jp-2"); - } - else if (charset->caseInsensitiveCompare(MCSTR("ks_c_5601-1987")) == 0) { - charset = MCSTR("euckr"); - } - else if ((charset->caseInsensitiveCompare(MCSTR("iso-8859-8-i")) == 0) || - (charset->caseInsensitiveCompare(MCSTR("iso-8859-8-e")) == 0)) { - charset = MCSTR("iso-8859-8"); - } - else if ((charset->caseInsensitiveCompare(MCSTR("GB2312")) == 0) || - (charset->caseInsensitiveCompare(MCSTR("GB_2312-80")) == 0)) { - charset = MCSTR("GBK"); - } - - return charset->lowercaseString(); -} - -String * Data::stringWithCharset(const char * charset) -{ - String * result = new String(this, charset); - if ((length() != 0) && (result->length() == 0)) { - result->release(); - return NULL; - } - return (String *) result->autorelease(); -} - -static bool isHintCharsetValid(String * hintCharset) -{ - static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; - static Set * knownCharset = NULL; - - pthread_mutex_lock(&lock); - if (knownCharset == NULL) { - knownCharset = new Set(); - -#if !USE_UCHARDET - UCharsetDetector * detector; - UEnumeration * iterator; - UErrorCode err = U_ZERO_ERROR; - - detector = ucsdet_open(&err); - iterator = ucsdet_getAllDetectableCharsets(detector, &err); - while (1) { - const char * validCharset = uenum_next(iterator, NULL, &err); - if (err != U_ZERO_ERROR) - break; - if (validCharset == NULL) - break; - knownCharset->addObject(String::stringWithUTF8Characters(validCharset)); - } - uenum_close(iterator); - ucsdet_close(detector); -#else - const char * charset_list[] = { - "Big5", - "EUC-JP", - "EUC-KR", - "x-euc-tw", - "gb18030", - "ISO-8859-8", - "windows-1255", - "windows-1252", - "Shift_JIS", - "UTF-8", - "UTF-16", - "HZ-GB-2312", - "ISO-2022-CN", - "ISO-2022-JP", - "ISO-2022-KR", - "ISO-8859-5", - "windows-1251", - "KOI8-R", - "x-mac-cyrillic", - "IBM866", - "IBM855", - "ISO-8859-7", - "windows-1253", - "ISO-8859-2", - "windows-1250", - "TIS-620", - }; - for(unsigned int i = 0 ; i < sizeof(charset_list) / sizeof(charset_list[0]) ; i ++) { - String * str = String::stringWithUTF8Characters(charset_list[i]); - str = str->lowercaseString(); - knownCharset->addObject(str); - } -#endif - } - pthread_mutex_unlock(&lock); - - if (hintCharset != NULL) { - hintCharset = normalizeCharset(hintCharset); - - if (hintCharset->isEqual(MCSTR("tis-620"))) { - return true; - } - else if (hintCharset->isEqual(MCSTR("koi8-r"))) { - return true; - } - else if (hintCharset->isEqual(MCSTR("euc-kr"))) { - return true; - } - else if (hintCharset->isEqual(MCSTR("windows-1256"))) { - return true; - } - - if (!knownCharset->containsObject(hintCharset)) { - return true; - } - } - - return false; -} - -String * Data::stringWithDetectedCharset(String * hintCharset, bool isHTML) -{ - String * result; - String * charset; - - if (hintCharset != NULL) { - hintCharset = normalizeCharset(hintCharset); - } - if (isHintCharsetValid(hintCharset)) { - charset = hintCharset; - } - else { - if (hintCharset == NULL) { - charset = charsetWithFilteredHTML(isHTML); - } - else { - charset = charsetWithFilteredHTML(isHTML, hintCharset); - } - } - - if (charset == NULL) { - charset = MCSTR(MCDATA_DEFAULT_CHARSET); - } - - charset = normalizeCharset(charset); - - // Remove whitespace at the end of the string to fix conversion. - if (charset->isEqual(MCSTR("iso-2022-jp-2"))) { - Data * data = this; - result = data->stringWithCharset("iso-2022-jp-2"); - if (result == NULL) { - result = data->stringWithCharset("iso-2022-jp"); - } - if (result == NULL) { - result = MCSTR(""); - } - - return result; - } - - result = stringWithCharset(charset->UTF8Characters()); - if (result == NULL) { - result = stringWithCharset("iso-8859-1"); - } - if (result == NULL) { - result = stringWithCharset("windows-1252"); - } - if (result == NULL) { - result = stringWithCharset("utf-8"); - } - if (result == NULL) { - result = MCSTR(""); - } - - return result; -} - -String * Data::charsetWithFilteredHTMLWithoutHint(bool filterHTML) -{ -#if !USE_UCHARDET - UCharsetDetector * detector; - const UCharsetMatch * match; - UErrorCode err = U_ZERO_ERROR; - const char * cName; - String * result; - - detector = ucsdet_open(&err); - ucsdet_setText(detector, bytes(), length(), &err); - ucsdet_enableInputFilter(detector, filterHTML); - match = ucsdet_detect(detector, &err); - if (match == NULL) { - ucsdet_close(detector); - return NULL; - } - - cName = ucsdet_getName(match, &err); - - result = String::stringWithUTF8Characters(cName); - ucsdet_close(detector); - - return result; -#else - String * result = NULL; - uchardet_t ud = uchardet_new(); - int r = uchardet_handle_data(ud, bytes(), length()); - if (r == 0) { - uchardet_data_end(ud); - const char * charset = uchardet_get_charset(ud); - if (charset[0] != 0) { - result = String::stringWithUTF8Characters(charset); - } - } - uchardet_delete(ud); - - return result; -#endif -} - -String * Data::charsetWithFilteredHTML(bool filterHTML, String * hintCharset) -{ - if (hintCharset == NULL) - return charsetWithFilteredHTMLWithoutHint(filterHTML); - -#if !USE_UCHARDET - const UCharsetMatch ** matches; - int32_t matchesCount; - UCharsetDetector * detector; - UErrorCode err = U_ZERO_ERROR; - String * result; - - hintCharset = hintCharset->lowercaseString(); - - detector = ucsdet_open(&err); - ucsdet_setText(detector, bytes(), length(), &err); - ucsdet_enableInputFilter(detector, filterHTML); - matches = ucsdet_detectAll(detector, &matchesCount, &err); - if (matches == NULL) { - ucsdet_close(detector); - return hintCharset; - } - if (matchesCount == 0) { - ucsdet_close(detector); - return hintCharset; - } - - result = NULL; - - for(int32_t i = 0 ; i < matchesCount ; i ++) { - const char * cName; - String * name; - int32_t confidence; - - cName = ucsdet_getName(matches[i], &err); - name = String::stringWithUTF8Characters(cName); - name = name->lowercaseString(); - confidence = ucsdet_getConfidence(matches[i], &err); - if ((confidence >= 50) && name->isEqual(hintCharset)) { - result = name; - break; - } - } - - if (result == NULL) { - int32_t maxConfidence; - - maxConfidence = 49; - - for(int32_t i = 0 ; i < matchesCount ; i ++) { - const char * cName; - String * name; - int32_t confidence; - - cName = ucsdet_getName(matches[i], &err); - confidence = ucsdet_getConfidence(matches[i], &err); - name = String::stringWithUTF8Characters(cName); - if (confidence > maxConfidence) { - result = name; - maxConfidence = confidence; - } - } - } - ucsdet_close(detector); - - if (result == NULL) - result = hintCharset; - - return result; -#else - String * result; - uchardet_t ud = uchardet_new(); - int r = uchardet_handle_data(ud, bytes(), length()); - if (r == 0) { - uchardet_data_end(ud); - const char * charset = uchardet_get_charset(ud); - if (charset[0] == 0) { - result = hintCharset; - } - else { - result = String::stringWithUTF8Characters(charset); - } - } - else { - result = hintCharset; - } - uchardet_delete(ud); - - return result; -#endif -} - -void Data::takeBytesOwnership(char * bytes, unsigned int length) -{ - free(mBytes); - mBytes = (char *) bytes; - mLength = length; -} - -Data * Data::dataWithContentsOfFile(String * filename) -{ - int r; - size_t read_items; - struct stat stat_buf; - FILE * f; - char * buf; - Data * data; - - f = fopen(filename->fileSystemRepresentation(), "rb"); - if (f == NULL) { - return NULL; - } - - r = fstat(fileno(f), &stat_buf); - if (r < 0) { - fclose(f); - return NULL; - } - - buf = (char *) malloc((size_t) stat_buf.st_size); - - read_items = fread(buf, 1, (size_t) stat_buf.st_size, f); - if ((off_t) read_items != stat_buf.st_size) { - free(buf); - fclose(f); - return NULL; - } - - data = Data::data(); - data->takeBytesOwnership(buf, (unsigned int) stat_buf.st_size); - - fclose(f); - - return data; -} - -static size_t uudecode(char * text, size_t size) -{ - unsigned int count = 0; - char *b = text; /* beg */ - char *s = b; /* src */ - char *d = b; /* dst */ - char *e = b+size; /* end */ - int out = (*s++ & 0x7f) - 0x20; - - /* don't process lines without leading count character */ - if (out < 0) - return size; - - /* don't process begin and end lines */ - if ((strncasecmp((const char *)b, "begin ", 6) == 0) || - (strncasecmp((const char *)b, "end", 3) == 0)) - return size; - - //while (s < e - 4) - while (s < e) - { - int v = 0; - int i; - for (i = 0; i < 4; i += 1) { - char c = *s++; - v = v << 6 | ((c - 0x20) & 0x3F); - } - for (i = 2; i >= 0; i -= 1) { - char c = (char) (v & 0xFF); - d[i] = c; - v = v >> 8; - } - d += 3; - count += 3; - } - *d = (char) '\0'; - return count; -} - -Data * Data::decodedDataUsingEncoding(Encoding encoding) -{ - const char * text; - size_t text_length; - - text = bytes(); - text_length = length(); - - switch (encoding) { - case Encoding7Bit: - case Encoding8Bit: - case EncodingBinary: - case EncodingOther: - default: - { - return this; - } - case EncodingBase64: - case EncodingQuotedPrintable: - { - char * decoded; - size_t decoded_length; - size_t cur_token; - int mime_encoding; - Data * data; - - switch (encoding) { - default: //disable warning - case EncodingBase64: - mime_encoding = MAILMIME_MECHANISM_BASE64; - break; - case EncodingQuotedPrintable: - mime_encoding = MAILMIME_MECHANISM_QUOTED_PRINTABLE; - break; - } - - cur_token = 0; - mailmime_part_parse(text, text_length, &cur_token, - mime_encoding, &decoded, &decoded_length); - data = Data::dataWithBytes(decoded, (unsigned int) decoded_length); - mailmime_decoded_part_free(decoded); - return data; - } - case EncodingUUEncode: - { - char * dup_data; - size_t decoded_length; - Data * data; - char * current_p; - - data = Data::dataWithCapacity((unsigned int) text_length); - - dup_data = (char *) malloc(text_length); - memcpy(dup_data, text, text_length); - - current_p = dup_data; - while (1) { - size_t length; - char * p; - char * p1; - char * p2; - char * end_line; - - p1 = strchr(current_p, '\n'); - p2 = strchr(current_p, '\r'); - if (p1 == NULL) { - p = p2; - } - else if (p2 == NULL) { - p = p1; - } - else { - if (p1 - current_p < p2 - current_p) { - p = p1; - } - else { - p = p2; - } - } - end_line = p; - if (p != NULL) { - while ((size_t) (p - dup_data) < text_length) { - if ((* p != '\r') && (* p != '\n')) { - break; - } - p ++; - } - } - if (p == NULL) { - length = text_length - (current_p - dup_data); - } - else { - length = end_line - current_p; - } - if (length == 0) { - break; - } - decoded_length = uudecode(current_p, length); - if (decoded_length != 0 && decoded_length < length) { - data->appendBytes(current_p, (unsigned int) decoded_length); - } - - if (p == NULL) - break; - - current_p = p; - while ((size_t) (current_p - dup_data) < text_length) { - if ((* current_p != '\r') && (* current_p != '\n')) { - break; - } - current_p ++; - } - } - free(dup_data); - - return data; - } - } -} - -Data * Data::data() -{ - return dataWithCapacity(0); -} - -Data * Data::dataWithCapacity(int capacity) -{ - Data * result = new Data(capacity); - return (Data *) result->autorelease(); -} - -String * Data::base64String() -{ - char * encoded = MCEncodeBase64(bytes(), length()); - String * result = String::stringWithUTF8Characters(encoded); - free(encoded); - return result; -} - -HashMap * Data::serializable() -{ - HashMap * result = Object::serializable(); - result->setObjectForKey(MCSTR("data"), base64String()); - return result; -} - -void Data::importSerializable(HashMap * serializable) -{ - setData(((String *) (serializable->objectForKey(MCSTR("data"))))->decodedBase64Data()); -} - -#if __APPLE__ -static CFStringEncoding encodingFromCString(const char * charset) -{ - CFStringEncoding encoding; - CFStringRef charsetString; - CFDataRef charsetData; - - charsetData = CFDataCreate(NULL, (const UInt8 *) charset, strlen(charset)); - charsetString = CFStringCreateFromExternalRepresentation(NULL, charsetData, kCFStringEncodingUTF8); - encoding = CFStringConvertIANACharSetNameToEncoding(charsetString); - CFRelease(charsetString); - CFRelease(charsetData); - - return encoding; -} - -static size_t lepIConvInternal(iconv_t cd, - const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft, - char **inrepls, const char *outrepl) -{ - size_t ret = 0, ret1; - char *ib = (char *) *inbuf; - size_t ibl = *inbytesleft; - char *ob = *outbuf; - size_t obl = *outbytesleft; - - for (;;) - { - ret1 = iconv (cd, &ib, &ibl, &ob, &obl); - if (ret1 != (size_t)-1) - ret += ret1; - if (ibl && obl && errno == EILSEQ) - { - if (inrepls) - { - /* Try replacing the input */ - char **t; - for (t = inrepls; *t; t++) - { - char *ib1 = *t; - size_t ibl1 = strlen (*t); - char *ob1 = ob; - size_t obl1 = obl; - iconv (cd, &ib1, &ibl1, &ob1, &obl1); - if (!ibl1) - { - ++ib, --ibl; - ob = ob1, obl = obl1; - ++ret; - break; - } - } - if (*t) - continue; - } - if (outrepl) - { - /* Try replacing the output */ - size_t n = strlen (outrepl); - if (n <= obl) - { - memcpy (ob, outrepl, n); - ++ib, --ibl; - ob += n, obl -= n; - ++ret; - continue; - } - } - } - *inbuf = ib, *inbytesleft = ibl; - *outbuf = ob, *outbytesleft = obl; - return ret; - } -} - -static int lepIConv(const char * tocode, const char * fromcode, - const char * str, size_t length, - char * result, size_t * result_len) - -{ - size_t out_size; - size_t old_out_size; - iconv_t conv; - char * p_result; - int res; - size_t r; - - conv = iconv_open(tocode, fromcode); - if (conv == (iconv_t) -1) { - res = MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET; - goto err; - } - - out_size = length * 6; - old_out_size = out_size; - p_result = result; - - r = lepIConvInternal(conv, &str, &length, - &p_result, &out_size, NULL, "?"); - if (r == (size_t) -1) { - res = MAIL_CHARCONV_ERROR_CONV; - goto close_iconv; - } - - iconv_close(conv); - - * result_len = old_out_size - out_size; - * p_result = '\0'; - - return MAIL_CHARCONV_NO_ERROR; - -close_iconv: - iconv_close(conv); -err: - return res; -} - -static int lepCFConv(const char * tocode, const char * fromcode, - const char * str, size_t length, - char * result, size_t * result_len) -{ - CFDataRef data; - CFStringRef resultString; - CFStringEncoding fromEncoding; - CFStringEncoding toEncoding; - CFDataRef resultData; - - fromEncoding = encodingFromCString(fromcode); - toEncoding = encodingFromCString(tocode); - if (fromEncoding == kCFStringEncodingInvalidId) - return MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET; - if (toEncoding == kCFStringEncodingInvalidId) - return MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET; - - data = CFDataCreate(NULL, (const UInt8 *) str, length); - resultString = CFStringCreateFromExternalRepresentation(NULL, data, fromEncoding); - if (resultString == NULL) { - CFRelease(data); - return MAIL_CHARCONV_ERROR_CONV; - } - - resultData = CFStringCreateExternalRepresentation(NULL, resultString, toEncoding, (UInt8) '?'); - - unsigned int len; - len = (unsigned int) CFDataGetLength(resultData); - CFDataGetBytes(resultData, CFRangeMake(0, len), (UInt8 *) result); - * result_len = len; - result[len] = 0; - - CFRelease(resultData); - CFRelease(resultString); - CFRelease(data); - - return MAIL_CHARCONV_NO_ERROR; -} - -static int lepMixedConv(const char * tocode, const char * fromcode, - const char * str, size_t length, - char * result, size_t * result_len) -{ - int r; - - if (strcasecmp(fromcode, "iso-2022-jp-2") == 0) { - r = lepCFConv(tocode, fromcode, str, length, - result, result_len); - if (r == MAIL_CHARCONV_NO_ERROR) - return r; - } - - r = lepIConv(tocode, fromcode, str, length, - result, result_len); - if (r == MAIL_CHARCONV_NO_ERROR) - return r; - - return r; -} -#endif - -static void * createObject() -{ - return new Data(); -} - -INITIALIZE(Data) -{ - Object::registerObjectConstructor("mailcore::Data", &createObject); -#if __APPLE__ - extended_charconv = lepMixedConv; -#endif -} diff --git a/src/core/basetypes/MCData.cpp b/src/core/basetypes/MCData.cpp new file mode 100644 index 00000000..0f792d1f --- /dev/null +++ b/src/core/basetypes/MCData.cpp @@ -0,0 +1,908 @@ +#include "MCWin32.h" // should be first include. + +#include "MCData.h" + +#define USE_UCHARDET 1 + +#include +#include +#include +#include +#if USE_UCHARDET +#include +#else +#include +#endif +#include +#include +#if __APPLE__ +#include +#endif + +#include "MCDefines.h" +#include "MCString.h" +#include "MCHash.h" +#include "MCUtils.h" +#include "MCHashMap.h" +#include "MCBase64.h" +#include "MCSet.h" + +#define MCDATA_DEFAULT_CHARSET "iso-8859-1" + +using namespace mailcore; + +static int isPowerOfTwo (unsigned int x) +{ + return ((x != 0) && !(x & (x - 1))); +} + +void Data::allocate(unsigned int length, bool force) +{ + if (length <= mAllocated) + return; + + if (force) { + mAllocated = length; + } + else { + if (!isPowerOfTwo(mAllocated)) { + mAllocated = 0; + } + if (mAllocated == 0) { + mAllocated = 4; + } + while (length > mAllocated) { + mAllocated *= 2; + } + } + + mBytes = (char *) realloc(mBytes, mAllocated); +} + +void Data::reset() +{ + free(mBytes); + mAllocated = 0; + mLength = 0; + mBytes = NULL; +} + +Data::Data() +{ + mBytes = NULL; + reset(); +} + +Data::Data(Data * otherData) : Object() +{ + mBytes = NULL; + reset(); + appendData(otherData); +} + +Data::Data(const char * bytes, unsigned int length) +{ + mBytes = NULL; + reset(); + allocate(length, true); + appendBytes(bytes, length); +} + +Data::Data(int capacity) +{ + mBytes = NULL; + reset(); + allocate(capacity, true); +} + +Data::~Data() +{ + reset(); +} + +Data * Data::dataWithBytes(const char * bytes, unsigned int length) +{ + Data * result = new Data(bytes, length); + return (Data *) result->autorelease(); +} + +char * Data::bytes() +{ + return mBytes; +} + +unsigned int Data::length() +{ + return mLength; +} + +void Data::appendData(Data * otherData) +{ + appendBytes(otherData->bytes(), otherData->length()); +} + +void Data::appendBytes(const char * bytes, unsigned int length) +{ + allocate(mLength + length); + memcpy(&mBytes[mLength], bytes, length); + mLength += length; +} + +void Data::setBytes(const char * bytes, unsigned int length) +{ + reset(); + appendBytes(bytes, length); +} + +void Data::setData(Data * otherData) +{ + reset(); + appendData(otherData); +} + +String * Data::description() +{ + return String::stringWithUTF8Format("<%s:%p %i bytes>", MCUTF8(className()), this, length()); +} + +Object * Data::copy() +{ + return new Data(this); +} + +bool Data::isEqual(Object * otherObject) +{ + Data * otherData = (Data *) otherObject; + if (length() != otherData->length()) + return false; + if (memcmp(bytes(), otherData->bytes(), mLength) != 0) + return false; + return true; +} + +unsigned int Data::hash() +{ + return hashCompute(mBytes, mLength); +} + +String * Data::stringWithDetectedCharset() +{ + String * result; + result = stringWithDetectedCharset(NULL, false); + return result; +} + +static String * normalizeCharset(String * charset) +{ + if ((charset->caseInsensitiveCompare(MCSTR("iso-2022-jp")) == 0) || + (charset->caseInsensitiveCompare(MCSTR("iso-2022-jp-2")) == 0)) { + charset = MCSTR("iso-2022-jp-2"); + } + else if (charset->caseInsensitiveCompare(MCSTR("ks_c_5601-1987")) == 0) { + charset = MCSTR("euckr"); + } + else if ((charset->caseInsensitiveCompare(MCSTR("iso-8859-8-i")) == 0) || + (charset->caseInsensitiveCompare(MCSTR("iso-8859-8-e")) == 0)) { + charset = MCSTR("iso-8859-8"); + } + else if ((charset->caseInsensitiveCompare(MCSTR("GB2312")) == 0) || + (charset->caseInsensitiveCompare(MCSTR("GB_2312-80")) == 0)) { + charset = MCSTR("GBK"); + } + + return charset->lowercaseString(); +} + +String * Data::stringWithCharset(const char * charset) +{ + String * result = new String(this, charset); + if ((length() != 0) && (result->length() == 0)) { + result->release(); + return NULL; + } + return (String *) result->autorelease(); +} + +static bool isHintCharsetValid(String * hintCharset) +{ + static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + static Set * knownCharset = NULL; + + pthread_mutex_lock(&lock); + if (knownCharset == NULL) { + knownCharset = new Set(); + +#if !USE_UCHARDET + UCharsetDetector * detector; + UEnumeration * iterator; + UErrorCode err = U_ZERO_ERROR; + + detector = ucsdet_open(&err); + iterator = ucsdet_getAllDetectableCharsets(detector, &err); + while (1) { + const char * validCharset = uenum_next(iterator, NULL, &err); + if (err != U_ZERO_ERROR) + break; + if (validCharset == NULL) + break; + knownCharset->addObject(String::stringWithUTF8Characters(validCharset)); + } + uenum_close(iterator); + ucsdet_close(detector); +#else + const char * charset_list[] = { + "Big5", + "EUC-JP", + "EUC-KR", + "x-euc-tw", + "gb18030", + "ISO-8859-8", + "windows-1255", + "windows-1252", + "Shift_JIS", + "UTF-8", + "UTF-16", + "HZ-GB-2312", + "ISO-2022-CN", + "ISO-2022-JP", + "ISO-2022-KR", + "ISO-8859-5", + "windows-1251", + "KOI8-R", + "x-mac-cyrillic", + "IBM866", + "IBM855", + "ISO-8859-7", + "windows-1253", + "ISO-8859-2", + "windows-1250", + "TIS-620", + }; + for(unsigned int i = 0 ; i < sizeof(charset_list) / sizeof(charset_list[0]) ; i ++) { + String * str = String::stringWithUTF8Characters(charset_list[i]); + str = str->lowercaseString(); + knownCharset->addObject(str); + } +#endif + } + pthread_mutex_unlock(&lock); + + if (hintCharset != NULL) { + hintCharset = normalizeCharset(hintCharset); + + if (hintCharset->isEqual(MCSTR("tis-620"))) { + return true; + } + else if (hintCharset->isEqual(MCSTR("koi8-r"))) { + return true; + } + else if (hintCharset->isEqual(MCSTR("euc-kr"))) { + return true; + } + else if (hintCharset->isEqual(MCSTR("windows-1256"))) { + return true; + } + + if (!knownCharset->containsObject(hintCharset)) { + return true; + } + } + + return false; +} + +String * Data::stringWithDetectedCharset(String * hintCharset, bool isHTML) +{ + String * result; + String * charset; + + if (hintCharset != NULL) { + hintCharset = normalizeCharset(hintCharset); + } + if (isHintCharsetValid(hintCharset)) { + charset = hintCharset; + } + else { + if (hintCharset == NULL) { + charset = charsetWithFilteredHTML(isHTML); + } + else { + charset = charsetWithFilteredHTML(isHTML, hintCharset); + } + } + + if (charset == NULL) { + charset = MCSTR(MCDATA_DEFAULT_CHARSET); + } + + charset = normalizeCharset(charset); + + // Remove whitespace at the end of the string to fix conversion. + if (charset->isEqual(MCSTR("iso-2022-jp-2"))) { + Data * data = this; + result = data->stringWithCharset("iso-2022-jp-2"); + if (result == NULL) { + result = data->stringWithCharset("iso-2022-jp"); + } + if (result == NULL) { + result = MCSTR(""); + } + + return result; + } + + result = stringWithCharset(charset->UTF8Characters()); + if (result == NULL) { + result = stringWithCharset("iso-8859-1"); + } + if (result == NULL) { + result = stringWithCharset("windows-1252"); + } + if (result == NULL) { + result = stringWithCharset("utf-8"); + } + if (result == NULL) { + result = MCSTR(""); + } + + return result; +} + +String * Data::charsetWithFilteredHTMLWithoutHint(bool filterHTML) +{ +#if !USE_UCHARDET + UCharsetDetector * detector; + const UCharsetMatch * match; + UErrorCode err = U_ZERO_ERROR; + const char * cName; + String * result; + + detector = ucsdet_open(&err); + ucsdet_setText(detector, bytes(), length(), &err); + ucsdet_enableInputFilter(detector, filterHTML); + match = ucsdet_detect(detector, &err); + if (match == NULL) { + ucsdet_close(detector); + return NULL; + } + + cName = ucsdet_getName(match, &err); + + result = String::stringWithUTF8Characters(cName); + ucsdet_close(detector); + + return result; +#else + String * result = NULL; + uchardet_t ud = uchardet_new(); + int r = uchardet_handle_data(ud, bytes(), length()); + if (r == 0) { + uchardet_data_end(ud); + const char * charset = uchardet_get_charset(ud); + if (charset[0] != 0) { + result = String::stringWithUTF8Characters(charset); + } + } + uchardet_delete(ud); + + return result; +#endif +} + +String * Data::charsetWithFilteredHTML(bool filterHTML, String * hintCharset) +{ + if (hintCharset == NULL) + return charsetWithFilteredHTMLWithoutHint(filterHTML); + +#if !USE_UCHARDET + const UCharsetMatch ** matches; + int32_t matchesCount; + UCharsetDetector * detector; + UErrorCode err = U_ZERO_ERROR; + String * result; + + hintCharset = hintCharset->lowercaseString(); + + detector = ucsdet_open(&err); + ucsdet_setText(detector, bytes(), length(), &err); + ucsdet_enableInputFilter(detector, filterHTML); + matches = ucsdet_detectAll(detector, &matchesCount, &err); + if (matches == NULL) { + ucsdet_close(detector); + return hintCharset; + } + if (matchesCount == 0) { + ucsdet_close(detector); + return hintCharset; + } + + result = NULL; + + for(int32_t i = 0 ; i < matchesCount ; i ++) { + const char * cName; + String * name; + int32_t confidence; + + cName = ucsdet_getName(matches[i], &err); + name = String::stringWithUTF8Characters(cName); + name = name->lowercaseString(); + confidence = ucsdet_getConfidence(matches[i], &err); + if ((confidence >= 50) && name->isEqual(hintCharset)) { + result = name; + break; + } + } + + if (result == NULL) { + int32_t maxConfidence; + + maxConfidence = 49; + + for(int32_t i = 0 ; i < matchesCount ; i ++) { + const char * cName; + String * name; + int32_t confidence; + + cName = ucsdet_getName(matches[i], &err); + confidence = ucsdet_getConfidence(matches[i], &err); + name = String::stringWithUTF8Characters(cName); + if (confidence > maxConfidence) { + result = name; + maxConfidence = confidence; + } + } + } + ucsdet_close(detector); + + if (result == NULL) + result = hintCharset; + + return result; +#else + String * result; + uchardet_t ud = uchardet_new(); + int r = uchardet_handle_data(ud, bytes(), length()); + if (r == 0) { + uchardet_data_end(ud); + const char * charset = uchardet_get_charset(ud); + if (charset[0] == 0) { + result = hintCharset; + } + else { + result = String::stringWithUTF8Characters(charset); + } + } + else { + result = hintCharset; + } + uchardet_delete(ud); + + return result; +#endif +} + +void Data::takeBytesOwnership(char * bytes, unsigned int length) +{ + free(mBytes); + mBytes = (char *) bytes; + mLength = length; +} + +Data * Data::dataWithContentsOfFile(String * filename) +{ + int r; + size_t read_items; + struct stat stat_buf; + FILE * f; + char * buf; + Data * data; + + f = fopen(filename->fileSystemRepresentation(), "rb"); + if (f == NULL) { + return NULL; + } + + r = fstat(fileno(f), &stat_buf); + if (r < 0) { + fclose(f); + return NULL; + } + + buf = (char *) malloc((size_t) stat_buf.st_size); + + read_items = fread(buf, 1, (size_t) stat_buf.st_size, f); + if ((off_t) read_items != stat_buf.st_size) { + free(buf); + fclose(f); + return NULL; + } + + data = Data::data(); + data->takeBytesOwnership(buf, (unsigned int) stat_buf.st_size); + + fclose(f); + + return data; +} + +static size_t uudecode(char * text, size_t size) +{ + unsigned int count = 0; + char *b = text; /* beg */ + char *s = b; /* src */ + char *d = b; /* dst */ + char *e = b+size; /* end */ + int out = (*s++ & 0x7f) - 0x20; + + /* don't process lines without leading count character */ + if (out < 0) + return size; + + /* don't process begin and end lines */ + if ((strncasecmp((const char *)b, "begin ", 6) == 0) || + (strncasecmp((const char *)b, "end", 3) == 0)) + return size; + + //while (s < e - 4) + while (s < e) + { + int v = 0; + int i; + for (i = 0; i < 4; i += 1) { + char c = *s++; + v = v << 6 | ((c - 0x20) & 0x3F); + } + for (i = 2; i >= 0; i -= 1) { + char c = (char) (v & 0xFF); + d[i] = c; + v = v >> 8; + } + d += 3; + count += 3; + } + *d = (char) '\0'; + return count; +} + +Data * Data::decodedDataUsingEncoding(Encoding encoding) +{ + const char * text; + size_t text_length; + + text = bytes(); + text_length = length(); + + switch (encoding) { + case Encoding7Bit: + case Encoding8Bit: + case EncodingBinary: + case EncodingOther: + default: + { + return this; + } + case EncodingBase64: + case EncodingQuotedPrintable: + { + char * decoded; + size_t decoded_length; + size_t cur_token; + int mime_encoding; + Data * data; + + switch (encoding) { + default: //disable warning + case EncodingBase64: + mime_encoding = MAILMIME_MECHANISM_BASE64; + break; + case EncodingQuotedPrintable: + mime_encoding = MAILMIME_MECHANISM_QUOTED_PRINTABLE; + break; + } + + cur_token = 0; + mailmime_part_parse(text, text_length, &cur_token, + mime_encoding, &decoded, &decoded_length); + data = Data::dataWithBytes(decoded, (unsigned int) decoded_length); + mailmime_decoded_part_free(decoded); + return data; + } + case EncodingUUEncode: + { + char * dup_data; + size_t decoded_length; + Data * data; + char * current_p; + + data = Data::dataWithCapacity((unsigned int) text_length); + + dup_data = (char *) malloc(text_length); + memcpy(dup_data, text, text_length); + + current_p = dup_data; + while (1) { + size_t length; + char * p; + char * p1; + char * p2; + char * end_line; + + p1 = strchr(current_p, '\n'); + p2 = strchr(current_p, '\r'); + if (p1 == NULL) { + p = p2; + } + else if (p2 == NULL) { + p = p1; + } + else { + if (p1 - current_p < p2 - current_p) { + p = p1; + } + else { + p = p2; + } + } + end_line = p; + if (p != NULL) { + while ((size_t) (p - dup_data) < text_length) { + if ((* p != '\r') && (* p != '\n')) { + break; + } + p ++; + } + } + if (p == NULL) { + length = text_length - (current_p - dup_data); + } + else { + length = end_line - current_p; + } + if (length == 0) { + break; + } + decoded_length = uudecode(current_p, length); + if (decoded_length != 0 && decoded_length < length) { + data->appendBytes(current_p, (unsigned int) decoded_length); + } + + if (p == NULL) + break; + + current_p = p; + while ((size_t) (current_p - dup_data) < text_length) { + if ((* current_p != '\r') && (* current_p != '\n')) { + break; + } + current_p ++; + } + } + free(dup_data); + + return data; + } + } +} + +Data * Data::data() +{ + return dataWithCapacity(0); +} + +Data * Data::dataWithCapacity(int capacity) +{ + Data * result = new Data(capacity); + return (Data *) result->autorelease(); +} + +String * Data::base64String() +{ + char * encoded = MCEncodeBase64(bytes(), length()); + String * result = String::stringWithUTF8Characters(encoded); + free(encoded); + return result; +} + +HashMap * Data::serializable() +{ + HashMap * result = Object::serializable(); + result->setObjectForKey(MCSTR("data"), base64String()); + return result; +} + +void Data::importSerializable(HashMap * serializable) +{ + setData(((String *) (serializable->objectForKey(MCSTR("data"))))->decodedBase64Data()); +} + +#if __APPLE__ +static CFStringEncoding encodingFromCString(const char * charset) +{ + CFStringEncoding encoding; + CFStringRef charsetString; + CFDataRef charsetData; + + charsetData = CFDataCreate(NULL, (const UInt8 *) charset, strlen(charset)); + charsetString = CFStringCreateFromExternalRepresentation(NULL, charsetData, kCFStringEncodingUTF8); + encoding = CFStringConvertIANACharSetNameToEncoding(charsetString); + CFRelease(charsetString); + CFRelease(charsetData); + + return encoding; +} + +static size_t lepIConvInternal(iconv_t cd, + const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft, + char **inrepls, const char *outrepl) +{ + size_t ret = 0, ret1; + char *ib = (char *) *inbuf; + size_t ibl = *inbytesleft; + char *ob = *outbuf; + size_t obl = *outbytesleft; + + for (;;) + { + ret1 = iconv (cd, &ib, &ibl, &ob, &obl); + if (ret1 != (size_t)-1) + ret += ret1; + if (ibl && obl && errno == EILSEQ) + { + if (inrepls) + { + /* Try replacing the input */ + char **t; + for (t = inrepls; *t; t++) + { + char *ib1 = *t; + size_t ibl1 = strlen (*t); + char *ob1 = ob; + size_t obl1 = obl; + iconv (cd, &ib1, &ibl1, &ob1, &obl1); + if (!ibl1) + { + ++ib, --ibl; + ob = ob1, obl = obl1; + ++ret; + break; + } + } + if (*t) + continue; + } + if (outrepl) + { + /* Try replacing the output */ + size_t n = strlen (outrepl); + if (n <= obl) + { + memcpy (ob, outrepl, n); + ++ib, --ibl; + ob += n, obl -= n; + ++ret; + continue; + } + } + } + *inbuf = ib, *inbytesleft = ibl; + *outbuf = ob, *outbytesleft = obl; + return ret; + } +} + +static int lepIConv(const char * tocode, const char * fromcode, + const char * str, size_t length, + char * result, size_t * result_len) + +{ + size_t out_size; + size_t old_out_size; + iconv_t conv; + char * p_result; + int res; + size_t r; + + conv = iconv_open(tocode, fromcode); + if (conv == (iconv_t) -1) { + res = MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET; + goto err; + } + + out_size = length * 6; + old_out_size = out_size; + p_result = result; + + r = lepIConvInternal(conv, &str, &length, + &p_result, &out_size, NULL, "?"); + if (r == (size_t) -1) { + res = MAIL_CHARCONV_ERROR_CONV; + goto close_iconv; + } + + iconv_close(conv); + + * result_len = old_out_size - out_size; + * p_result = '\0'; + + return MAIL_CHARCONV_NO_ERROR; + +close_iconv: + iconv_close(conv); +err: + return res; +} + +static int lepCFConv(const char * tocode, const char * fromcode, + const char * str, size_t length, + char * result, size_t * result_len) +{ + CFDataRef data; + CFStringRef resultString; + CFStringEncoding fromEncoding; + CFStringEncoding toEncoding; + CFDataRef resultData; + + fromEncoding = encodingFromCString(fromcode); + toEncoding = encodingFromCString(tocode); + if (fromEncoding == kCFStringEncodingInvalidId) + return MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET; + if (toEncoding == kCFStringEncodingInvalidId) + return MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET; + + data = CFDataCreate(NULL, (const UInt8 *) str, length); + resultString = CFStringCreateFromExternalRepresentation(NULL, data, fromEncoding); + if (resultString == NULL) { + CFRelease(data); + return MAIL_CHARCONV_ERROR_CONV; + } + + resultData = CFStringCreateExternalRepresentation(NULL, resultString, toEncoding, (UInt8) '?'); + + unsigned int len; + len = (unsigned int) CFDataGetLength(resultData); + CFDataGetBytes(resultData, CFRangeMake(0, len), (UInt8 *) result); + * result_len = len; + result[len] = 0; + + CFRelease(resultData); + CFRelease(resultString); + CFRelease(data); + + return MAIL_CHARCONV_NO_ERROR; +} + +static int lepMixedConv(const char * tocode, const char * fromcode, + const char * str, size_t length, + char * result, size_t * result_len) +{ + int r; + + if (strcasecmp(fromcode, "iso-2022-jp-2") == 0) { + r = lepCFConv(tocode, fromcode, str, length, + result, result_len); + if (r == MAIL_CHARCONV_NO_ERROR) + return r; + } + + r = lepIConv(tocode, fromcode, str, length, + result, result_len); + if (r == MAIL_CHARCONV_NO_ERROR) + return r; + + return r; +} +#endif + +static void * createObject() +{ + return new Data(); +} + +INITIALIZE(Data) +{ + Object::registerObjectConstructor("mailcore::Data", &createObject); +#if __APPLE__ + extended_charconv = lepMixedConv; +#endif +} diff --git a/src/core/basetypes/MCHTMLCleaner.cc b/src/core/basetypes/MCHTMLCleaner.cc deleted file mode 100644 index 81145c9e..00000000 --- a/src/core/basetypes/MCHTMLCleaner.cc +++ /dev/null @@ -1,125 +0,0 @@ -// -// HTMLCleaner.cpp -// mailcore2 -// -// Created by DINH Viêt Hoà on 2/3/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCHTMLCleaner.h" - -#include "MCString.h" -#include "MCData.h" - -#include -#include - -#include "MCUtils.h" -#include "MCLog.h" - -#if __APPLE__ -#include -#endif - -using namespace mailcore; - -String * HTMLCleaner::cleanHTML(String * input) -{ - TidyBuffer output; - TidyBuffer errbuf; - TidyBuffer docbuf; - int rc; - - TidyDoc tdoc = tidyCreate(); - tidyBufInit(&output); - tidyBufInit(&errbuf); - tidyBufInit(&docbuf); - - Data * data = input->dataUsingEncoding("utf-8"); - tidyBufAppend(&docbuf, data->bytes(), data->length()); - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - // This option is not available on the Mac. - tidyOptSetBool(tdoc, TidyDropEmptyElems, no); -#endif - tidyOptSetBool(tdoc, TidyXhtmlOut, yes); - tidyOptSetInt(tdoc, TidyDoctypeMode, TidyDoctypeUser); - - tidyOptSetBool(tdoc, TidyMark, no); - tidySetCharEncoding(tdoc, "utf8"); - tidyOptSetBool(tdoc, TidyForceOutput, yes); - //tidyOptSetValue(tdoc, TidyErrFile, "/dev/null"); - //tidyOptSetValue(tdoc, TidyOutFile, "/dev/null"); - tidyOptSetBool(tdoc, TidyShowWarnings, no); - tidyOptSetInt(tdoc, TidyShowErrors, 0); - rc = tidySetErrorBuffer(tdoc, &errbuf); - if ((rc > 1) || (rc < 0)) { - //fprintf(stderr, "error tidySetErrorBuffer: %i\n", rc); - //fprintf(stderr, "1:%s", errbuf.bp); - //return NULL; - } - rc = tidyParseBuffer(tdoc, &docbuf); - //MCLog("%s", MCUTF8(input)); - if ((rc > 1) || (rc < 0)) { - //fprintf(stderr, "error tidyParseBuffer: %i\n", rc); - //fprintf(stderr, "1:%s", errbuf.bp); - //return NULL; - } - rc = tidyCleanAndRepair(tdoc); - if ((rc > 1) || (rc < 0)) { - //fprintf(stderr, "error tidyCleanAndRepair: %i\n", rc); - //fprintf(stderr, "1:%s", errbuf.bp); - //return NULL; - } - rc = tidySaveBuffer(tdoc, &output); - if ((rc > 1) || (rc < 0)) { - //fprintf(stderr, "error tidySaveBuffer: %i\n", rc); - //fprintf(stderr, "1:%s", errbuf.bp); - } - - String * result = String::stringWithUTF8Characters((const char *) output.bp); - - tidyBufFree(&docbuf); - tidyBufFree(&output); - tidyBufFree(&errbuf); - tidyRelease(tdoc); - - return result; - - /* - if ( ok ) { - rc = tidySetErrorBuffer( tdoc, &errbuf ); // Capture diagnostics - } - if ( rc >= 0 ) { - rc = tidyParseString( tdoc, input ); // Parse the input - } - if ( rc >= 0 ) { - rc = tidyCleanAndRepair( tdoc ); // Tidy it up! - } - if ( rc >= 0 ) { - rc = tidyRunDiagnostics( tdoc ); // Kvetch - } - if ( rc > 1 ) { // If error, force output. - rc = ( tidyOptSetBool(tdoc, TidyForceOutput, yes) ? rc : -1 ); - } - if ( rc >= 0 ) { - rc = tidySaveBuffer( tdoc, &output ); // Pretty Print - } - */ - - /* - if ( rc >= 0 ) - { - if ( rc > 0 ) - printf( "\\nDiagnostics:\\n\\n\%s", errbuf.bp ); - printf( "\\nAnd here is the result:\\n\\n\%s", output.bp ); - } - else - printf( "A severe error (\%d) occurred.\\n", rc ); - - tidyBufFree( &output ); - tidyBufFree( &errbuf ); - tidyRelease( tdoc ); - return rc; - */ -} diff --git a/src/core/basetypes/MCHTMLCleaner.cpp b/src/core/basetypes/MCHTMLCleaner.cpp new file mode 100644 index 00000000..81145c9e --- /dev/null +++ b/src/core/basetypes/MCHTMLCleaner.cpp @@ -0,0 +1,125 @@ +// +// HTMLCleaner.cpp +// mailcore2 +// +// Created by DINH Viêt Hoà on 2/3/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCHTMLCleaner.h" + +#include "MCString.h" +#include "MCData.h" + +#include +#include + +#include "MCUtils.h" +#include "MCLog.h" + +#if __APPLE__ +#include +#endif + +using namespace mailcore; + +String * HTMLCleaner::cleanHTML(String * input) +{ + TidyBuffer output; + TidyBuffer errbuf; + TidyBuffer docbuf; + int rc; + + TidyDoc tdoc = tidyCreate(); + tidyBufInit(&output); + tidyBufInit(&errbuf); + tidyBufInit(&docbuf); + + Data * data = input->dataUsingEncoding("utf-8"); + tidyBufAppend(&docbuf, data->bytes(), data->length()); + +#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE + // This option is not available on the Mac. + tidyOptSetBool(tdoc, TidyDropEmptyElems, no); +#endif + tidyOptSetBool(tdoc, TidyXhtmlOut, yes); + tidyOptSetInt(tdoc, TidyDoctypeMode, TidyDoctypeUser); + + tidyOptSetBool(tdoc, TidyMark, no); + tidySetCharEncoding(tdoc, "utf8"); + tidyOptSetBool(tdoc, TidyForceOutput, yes); + //tidyOptSetValue(tdoc, TidyErrFile, "/dev/null"); + //tidyOptSetValue(tdoc, TidyOutFile, "/dev/null"); + tidyOptSetBool(tdoc, TidyShowWarnings, no); + tidyOptSetInt(tdoc, TidyShowErrors, 0); + rc = tidySetErrorBuffer(tdoc, &errbuf); + if ((rc > 1) || (rc < 0)) { + //fprintf(stderr, "error tidySetErrorBuffer: %i\n", rc); + //fprintf(stderr, "1:%s", errbuf.bp); + //return NULL; + } + rc = tidyParseBuffer(tdoc, &docbuf); + //MCLog("%s", MCUTF8(input)); + if ((rc > 1) || (rc < 0)) { + //fprintf(stderr, "error tidyParseBuffer: %i\n", rc); + //fprintf(stderr, "1:%s", errbuf.bp); + //return NULL; + } + rc = tidyCleanAndRepair(tdoc); + if ((rc > 1) || (rc < 0)) { + //fprintf(stderr, "error tidyCleanAndRepair: %i\n", rc); + //fprintf(stderr, "1:%s", errbuf.bp); + //return NULL; + } + rc = tidySaveBuffer(tdoc, &output); + if ((rc > 1) || (rc < 0)) { + //fprintf(stderr, "error tidySaveBuffer: %i\n", rc); + //fprintf(stderr, "1:%s", errbuf.bp); + } + + String * result = String::stringWithUTF8Characters((const char *) output.bp); + + tidyBufFree(&docbuf); + tidyBufFree(&output); + tidyBufFree(&errbuf); + tidyRelease(tdoc); + + return result; + + /* + if ( ok ) { + rc = tidySetErrorBuffer( tdoc, &errbuf ); // Capture diagnostics + } + if ( rc >= 0 ) { + rc = tidyParseString( tdoc, input ); // Parse the input + } + if ( rc >= 0 ) { + rc = tidyCleanAndRepair( tdoc ); // Tidy it up! + } + if ( rc >= 0 ) { + rc = tidyRunDiagnostics( tdoc ); // Kvetch + } + if ( rc > 1 ) { // If error, force output. + rc = ( tidyOptSetBool(tdoc, TidyForceOutput, yes) ? rc : -1 ); + } + if ( rc >= 0 ) { + rc = tidySaveBuffer( tdoc, &output ); // Pretty Print + } + */ + + /* + if ( rc >= 0 ) + { + if ( rc > 0 ) + printf( "\\nDiagnostics:\\n\\n\%s", errbuf.bp ); + printf( "\\nAnd here is the result:\\n\\n\%s", output.bp ); + } + else + printf( "A severe error (\%d) occurred.\\n", rc ); + + tidyBufFree( &output ); + tidyBufFree( &errbuf ); + tidyRelease( tdoc ); + return rc; + */ +} diff --git a/src/core/basetypes/MCHash.cc b/src/core/basetypes/MCHash.cc deleted file mode 100644 index 62875d89..00000000 --- a/src/core/basetypes/MCHash.cc +++ /dev/null @@ -1,12 +0,0 @@ -#include "MCHash.h" - -unsigned int mailcore::hashCompute(const char * key, unsigned int len) { - unsigned int c = 5381; - const char * k = key; - - while (len--) { - c = ((c << 5) + c) + *k++; - } - - return c; -} diff --git a/src/core/basetypes/MCHash.cpp b/src/core/basetypes/MCHash.cpp new file mode 100644 index 00000000..62875d89 --- /dev/null +++ b/src/core/basetypes/MCHash.cpp @@ -0,0 +1,12 @@ +#include "MCHash.h" + +unsigned int mailcore::hashCompute(const char * key, unsigned int len) { + unsigned int c = 5381; + const char * k = key; + + while (len--) { + c = ((c << 5) + c) + *k++; + } + + return c; +} diff --git a/src/core/basetypes/MCHashMap.cc b/src/core/basetypes/MCHashMap.cc deleted file mode 100644 index 046aad90..00000000 --- a/src/core/basetypes/MCHashMap.cc +++ /dev/null @@ -1,331 +0,0 @@ -#include "MCWin32.h" // should be first include. - -#include "MCHashMap.h" - -#include -#include - -#include "MCDefines.h" -#include "MCArray.h" -#include "MCString.h" -#include "MCUtils.h" -#include "MCLog.h" -#include "MCIterator.h" -#include "MCAssert.h" - -using namespace mailcore; - -namespace mailcore { - struct HashMapCell { - unsigned int func; - Object * key; - Object * value; - HashMapCell * next; - }; - -} - -#define CHASH_DEFAULTSIZE 13 -#define CHASH_MAXDEPTH 3 - -void HashMap::init() -{ - mCount = 0; - mCells = (void **) (HashMapCell **) calloc(CHASH_DEFAULTSIZE, sizeof(HashMapCell *)); - mAllocated = CHASH_DEFAULTSIZE; -} - -HashMap::HashMap() -{ - init(); -} - -HashMap::HashMap(HashMap * other) -{ - init(); - Array * keys = other->allKeys(); - for(unsigned int i = 0 ; i < keys->count() ; i ++) { - Object * key = keys->objectAtIndex(i); - Object * value = other->objectForKey(key); - setObjectForKey(key, value); - } -} - -HashMap::~HashMap() -{ - for(unsigned int indx = 0; indx < mAllocated; indx++) { - HashMapIter * iter, * next; - iter = (HashMapIter *) mCells[indx]; - while (iter) { - next = iter->next; - iter->key->release(); - iter->value->release(); - free(iter); - iter = next; - } - } - free(mCells); -} - -void HashMap::allocate(unsigned int size) -{ - HashMapCell ** cells; - unsigned int indx, nindx; - HashMapIter * iter, * next; - - if (mAllocated == size) - return; - - cells = (HashMapCell **) calloc(size, sizeof(HashMapCell *)); - /* iterate over initial hash and copy items in second hash */ - for(indx = 0 ; indx < mAllocated ; indx ++) { - iter = (HashMapIter *) mCells[indx]; - while (iter) { - next = iter->next; - nindx = iter->func % size; - iter->next = cells[nindx]; - cells[nindx] = iter; - iter = next; - } - } - free(mCells); - mAllocated = size; - mCells = (void **) cells; -} - -HashMap * HashMap::hashMap() -{ - HashMap * result = new HashMap(); - return (HashMap *) result->autorelease(); -} - -String * HashMap::description() -{ - String * result = String::string(); - Array * keys = allKeys(); - result->appendUTF8Characters("{"); - for(unsigned int i = 0 ; i < keys->count() ; i ++) { - Object * key = keys->objectAtIndex(i); - if (i != 0) { - result->appendUTF8Characters(","); - } - result->appendString(key->description()); - result->appendUTF8Characters(":"); - Object * value = objectForKey(key); - result->appendString(value->description()); - } - result->appendUTF8Characters("}"); - - return result; -} - -Object * HashMap::copy() -{ - return new HashMap(this); -} - -unsigned int HashMap::count() -{ - return mCount; -} - -void HashMap::setObjectForKey(Object * key, Object * value) -{ - unsigned int func, indx; - HashMapIter * iter, * cell; - - if (mCount > mAllocated * CHASH_MAXDEPTH) { - allocate((mCount / CHASH_MAXDEPTH) * 2 + 1); - } - - func = key->hash(); - indx = func % mAllocated; - - /* look for the key in existing cells */ - iter = (HashMapIter *) mCells[indx]; - while (iter) { - if (iter->func == func && iter->key->isEqual(key)) { - /* found, replacing entry */ - value->retain(); - iter->value->release(); - iter->value = value; - return; - } - iter = iter->next; - } - - /* not found, adding entry */ - cell = (HashMapCell *) malloc(sizeof(HashMapCell)); - cell->key = key->copy(); - cell->value = value->retain(); - cell->func = func; - cell->next = (HashMapCell *) mCells[indx]; - mCells[indx] = cell; - mCount ++; -} - -void HashMap::removeObjectForKey(Object * key) -{ - unsigned int func, indx; - HashMapIter * iter, * old; - - func = key->hash();; - indx = func % mAllocated; - - /* look for the key in existing cells */ - old = NULL; - iter = (HashMapIter *) mCells[indx]; - while (iter) { - if (iter->func == func && iter->key->isEqual(key)) { - /* found, deleting */ - if (old) - old->next = iter->next; - else - mCells[indx] = iter->next; - iter->key->release(); - iter->value->release(); - free(iter); - mCount --; - return; - } - old = iter; - iter = iter->next; - } - // Not found. -} - -Object * HashMap::objectForKey(Object * key) -{ - unsigned int func; - HashMapIter * iter; - - func = key->hash(); - - /* look for the key in existing cells */ - iter = (HashMapIter *) mCells[func % mAllocated]; - while (iter) { - if (iter->func == func && key->isEqual(iter->key)) { - return iter->value; /* found */ - } - iter = iter->next; - } - return NULL; -} - -HashMapIter * HashMap::iteratorBegin() -{ - HashMapIter * iter; - unsigned int indx = 0; - - iter = (HashMapIter *) mCells[0]; - while (!iter) { - indx ++; - if (indx >= mAllocated) - return NULL; - iter = (HashMapIter *) mCells[indx]; - } - return iter; -} - -HashMapIter * HashMap::iteratorNext(HashMapIter * iter) -{ - unsigned int indx; - - if (!iter) - return NULL; - - indx = iter->func % mAllocated; - iter = iter->next; - - while(!iter) { - indx++; - if (indx >= mAllocated) - return NULL; - iter = (HashMapIter *) mCells[indx]; - } - return iter; -} - -Array * HashMap::allKeys() -{ - Array * keys = Array::array(); - for(HashMapIter * iter = iteratorBegin() ; iter != NULL ; iter = iteratorNext(iter)) { - keys->addObject(iter->key); - } - return keys; -} - -Array * HashMap::allValues() -{ - Array * values = Array::array(); - for(HashMapIter * iter = iteratorBegin() ; iter != NULL ; iter = iteratorNext(iter)) { - values->addObject(iter->value); - } - return values; -} - -void HashMap::removeAllObjects() -{ - for(unsigned int indx = 0 ; indx < mAllocated ; indx++) { - HashMapIter * iter, * next; - iter = (HashMapIter *) mCells[indx]; - while (iter) { - next = iter->next; - iter->key->release(); - iter->value->release(); - free(iter); - iter = next; - } - } - memset(mCells, 0, mAllocated * sizeof(* mCells)); - mCount = 0; -} - -HashMap * HashMap::serializable() -{ - HashMap * result = Object::serializable(); - Array * keys = Array::array(); - Array * values = Array::array(); - mc_foreachhashmapKeyAndValue(Object, key, Object, value, this) { - if (MCISKINDOFCLASS(key, String)) { - keys->addObject(key); - } - else { - keys->addObject(key->serializable()); - } - values->addObject(value->serializable()); - } - result->setObjectForKey(MCSTR("keys"), keys); - result->setObjectForKey(MCSTR("values"), values); - return result; -} - -void HashMap::importSerializable(HashMap * serializable) -{ - Array * keys = (Array *) serializable->objectForKey(MCSTR("keys")); - Array * values = (Array *) serializable->objectForKey(MCSTR("values")); - unsigned int count = keys->count(); - MCAssert(count == values->count()); - for(unsigned int i = 0 ; i < count ; i ++) { - Object * serializedKey = keys->objectAtIndex(i); - Object * key; - if (MCISKINDOFCLASS(serializedKey, String)) { - key = serializedKey; - } - else { - key = Object::objectWithSerializable((HashMap *) serializedKey); - } - Object * value = Object::objectWithSerializable((HashMap *) values->objectAtIndex(i)); - setObjectForKey(key, value); - } -} - -static void * createObject() -{ - return new HashMap(); -} - -INITIALIZE(HashMap) -{ - Object::registerObjectConstructor("mailcore::HashMap", &createObject); -} diff --git a/src/core/basetypes/MCHashMap.cpp b/src/core/basetypes/MCHashMap.cpp new file mode 100644 index 00000000..046aad90 --- /dev/null +++ b/src/core/basetypes/MCHashMap.cpp @@ -0,0 +1,331 @@ +#include "MCWin32.h" // should be first include. + +#include "MCHashMap.h" + +#include +#include + +#include "MCDefines.h" +#include "MCArray.h" +#include "MCString.h" +#include "MCUtils.h" +#include "MCLog.h" +#include "MCIterator.h" +#include "MCAssert.h" + +using namespace mailcore; + +namespace mailcore { + struct HashMapCell { + unsigned int func; + Object * key; + Object * value; + HashMapCell * next; + }; + +} + +#define CHASH_DEFAULTSIZE 13 +#define CHASH_MAXDEPTH 3 + +void HashMap::init() +{ + mCount = 0; + mCells = (void **) (HashMapCell **) calloc(CHASH_DEFAULTSIZE, sizeof(HashMapCell *)); + mAllocated = CHASH_DEFAULTSIZE; +} + +HashMap::HashMap() +{ + init(); +} + +HashMap::HashMap(HashMap * other) +{ + init(); + Array * keys = other->allKeys(); + for(unsigned int i = 0 ; i < keys->count() ; i ++) { + Object * key = keys->objectAtIndex(i); + Object * value = other->objectForKey(key); + setObjectForKey(key, value); + } +} + +HashMap::~HashMap() +{ + for(unsigned int indx = 0; indx < mAllocated; indx++) { + HashMapIter * iter, * next; + iter = (HashMapIter *) mCells[indx]; + while (iter) { + next = iter->next; + iter->key->release(); + iter->value->release(); + free(iter); + iter = next; + } + } + free(mCells); +} + +void HashMap::allocate(unsigned int size) +{ + HashMapCell ** cells; + unsigned int indx, nindx; + HashMapIter * iter, * next; + + if (mAllocated == size) + return; + + cells = (HashMapCell **) calloc(size, sizeof(HashMapCell *)); + /* iterate over initial hash and copy items in second hash */ + for(indx = 0 ; indx < mAllocated ; indx ++) { + iter = (HashMapIter *) mCells[indx]; + while (iter) { + next = iter->next; + nindx = iter->func % size; + iter->next = cells[nindx]; + cells[nindx] = iter; + iter = next; + } + } + free(mCells); + mAllocated = size; + mCells = (void **) cells; +} + +HashMap * HashMap::hashMap() +{ + HashMap * result = new HashMap(); + return (HashMap *) result->autorelease(); +} + +String * HashMap::description() +{ + String * result = String::string(); + Array * keys = allKeys(); + result->appendUTF8Characters("{"); + for(unsigned int i = 0 ; i < keys->count() ; i ++) { + Object * key = keys->objectAtIndex(i); + if (i != 0) { + result->appendUTF8Characters(","); + } + result->appendString(key->description()); + result->appendUTF8Characters(":"); + Object * value = objectForKey(key); + result->appendString(value->description()); + } + result->appendUTF8Characters("}"); + + return result; +} + +Object * HashMap::copy() +{ + return new HashMap(this); +} + +unsigned int HashMap::count() +{ + return mCount; +} + +void HashMap::setObjectForKey(Object * key, Object * value) +{ + unsigned int func, indx; + HashMapIter * iter, * cell; + + if (mCount > mAllocated * CHASH_MAXDEPTH) { + allocate((mCount / CHASH_MAXDEPTH) * 2 + 1); + } + + func = key->hash(); + indx = func % mAllocated; + + /* look for the key in existing cells */ + iter = (HashMapIter *) mCells[indx]; + while (iter) { + if (iter->func == func && iter->key->isEqual(key)) { + /* found, replacing entry */ + value->retain(); + iter->value->release(); + iter->value = value; + return; + } + iter = iter->next; + } + + /* not found, adding entry */ + cell = (HashMapCell *) malloc(sizeof(HashMapCell)); + cell->key = key->copy(); + cell->value = value->retain(); + cell->func = func; + cell->next = (HashMapCell *) mCells[indx]; + mCells[indx] = cell; + mCount ++; +} + +void HashMap::removeObjectForKey(Object * key) +{ + unsigned int func, indx; + HashMapIter * iter, * old; + + func = key->hash();; + indx = func % mAllocated; + + /* look for the key in existing cells */ + old = NULL; + iter = (HashMapIter *) mCells[indx]; + while (iter) { + if (iter->func == func && iter->key->isEqual(key)) { + /* found, deleting */ + if (old) + old->next = iter->next; + else + mCells[indx] = iter->next; + iter->key->release(); + iter->value->release(); + free(iter); + mCount --; + return; + } + old = iter; + iter = iter->next; + } + // Not found. +} + +Object * HashMap::objectForKey(Object * key) +{ + unsigned int func; + HashMapIter * iter; + + func = key->hash(); + + /* look for the key in existing cells */ + iter = (HashMapIter *) mCells[func % mAllocated]; + while (iter) { + if (iter->func == func && key->isEqual(iter->key)) { + return iter->value; /* found */ + } + iter = iter->next; + } + return NULL; +} + +HashMapIter * HashMap::iteratorBegin() +{ + HashMapIter * iter; + unsigned int indx = 0; + + iter = (HashMapIter *) mCells[0]; + while (!iter) { + indx ++; + if (indx >= mAllocated) + return NULL; + iter = (HashMapIter *) mCells[indx]; + } + return iter; +} + +HashMapIter * HashMap::iteratorNext(HashMapIter * iter) +{ + unsigned int indx; + + if (!iter) + return NULL; + + indx = iter->func % mAllocated; + iter = iter->next; + + while(!iter) { + indx++; + if (indx >= mAllocated) + return NULL; + iter = (HashMapIter *) mCells[indx]; + } + return iter; +} + +Array * HashMap::allKeys() +{ + Array * keys = Array::array(); + for(HashMapIter * iter = iteratorBegin() ; iter != NULL ; iter = iteratorNext(iter)) { + keys->addObject(iter->key); + } + return keys; +} + +Array * HashMap::allValues() +{ + Array * values = Array::array(); + for(HashMapIter * iter = iteratorBegin() ; iter != NULL ; iter = iteratorNext(iter)) { + values->addObject(iter->value); + } + return values; +} + +void HashMap::removeAllObjects() +{ + for(unsigned int indx = 0 ; indx < mAllocated ; indx++) { + HashMapIter * iter, * next; + iter = (HashMapIter *) mCells[indx]; + while (iter) { + next = iter->next; + iter->key->release(); + iter->value->release(); + free(iter); + iter = next; + } + } + memset(mCells, 0, mAllocated * sizeof(* mCells)); + mCount = 0; +} + +HashMap * HashMap::serializable() +{ + HashMap * result = Object::serializable(); + Array * keys = Array::array(); + Array * values = Array::array(); + mc_foreachhashmapKeyAndValue(Object, key, Object, value, this) { + if (MCISKINDOFCLASS(key, String)) { + keys->addObject(key); + } + else { + keys->addObject(key->serializable()); + } + values->addObject(value->serializable()); + } + result->setObjectForKey(MCSTR("keys"), keys); + result->setObjectForKey(MCSTR("values"), values); + return result; +} + +void HashMap::importSerializable(HashMap * serializable) +{ + Array * keys = (Array *) serializable->objectForKey(MCSTR("keys")); + Array * values = (Array *) serializable->objectForKey(MCSTR("values")); + unsigned int count = keys->count(); + MCAssert(count == values->count()); + for(unsigned int i = 0 ; i < count ; i ++) { + Object * serializedKey = keys->objectAtIndex(i); + Object * key; + if (MCISKINDOFCLASS(serializedKey, String)) { + key = serializedKey; + } + else { + key = Object::objectWithSerializable((HashMap *) serializedKey); + } + Object * value = Object::objectWithSerializable((HashMap *) values->objectAtIndex(i)); + setObjectForKey(key, value); + } +} + +static void * createObject() +{ + return new HashMap(); +} + +INITIALIZE(HashMap) +{ + Object::registerObjectConstructor("mailcore::HashMap", &createObject); +} diff --git a/src/core/basetypes/MCIndexSet.cc b/src/core/basetypes/MCIndexSet.cc deleted file mode 100644 index 7f7e1db3..00000000 --- a/src/core/basetypes/MCIndexSet.cc +++ /dev/null @@ -1,437 +0,0 @@ -// -// MCIndexSet.cpp -// mailcore2 -// -// Created by DINH Viêt Hoà on 3/4/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIndexSet.h" - -#include "MCDefines.h" -#include "MCString.h" -#include "MCAssert.h" -#include "MCRange.h" -#include "MCLog.h" -#include "MCArray.h" -#include "MCHashMap.h" -#include "MCUtils.h" - -using namespace mailcore; - -void IndexSet::init() -{ - mRanges = NULL; - mAllocated = 0; - mCount = 0; -} - -IndexSet::IndexSet() -{ - init(); -} - -IndexSet::IndexSet(IndexSet * o) -{ - init(); - mRanges = new Range[o->mAllocated]; - for(unsigned int i = 0 ; i < o->mCount ; i ++) { - mRanges[i] = o->mRanges[i]; - } - mAllocated = o->mAllocated; - mCount = o->mCount; -} - -IndexSet::~IndexSet() -{ - removeAllIndexes(); -} - -IndexSet * IndexSet::indexSet() -{ - IndexSet * result = new IndexSet(); - result->autorelease(); - return result; -} - -IndexSet * IndexSet::indexSetWithRange(Range range) -{ - IndexSet * result = new IndexSet(); - result->autorelease(); - result->addRange(range); - return result; -} - -IndexSet * IndexSet::indexSetWithIndex(uint64_t idx) -{ - IndexSet * result = new IndexSet(); - result->autorelease(); - result->addIndex(idx); - return result; -} - -unsigned int IndexSet::count() -{ - unsigned int total = 0; - for(unsigned int i = 0 ; i < mCount ; i ++) { - total += mRanges[i].length + 1; - } - return total; -} - -int IndexSet::rangeIndexForIndexWithBounds(uint64_t idx, unsigned int left, unsigned int right) -{ - unsigned int middle = (left + right) / 2; - - Range middleRange = mRanges[middle]; - - if (left == right) { - if ((idx >= RangeLeftBound(middleRange)) && (idx <= RangeRightBound(middleRange))) { - return left; - } - return -1; - } - - if ((idx >= RangeLeftBound(middleRange)) && (idx <= RangeRightBound(middleRange))) { - return middle; - } - if (idx < middleRange.location) { - return rangeIndexForIndexWithBounds(idx, left, middle); - } - else { - return rangeIndexForIndexWithBounds(idx, middle + 1, right); - } -} - -int IndexSet::rangeIndexForIndex(uint64_t idx) -{ - if (mCount == 0) - return -1; - - return rangeIndexForIndexWithBounds(idx, 0, mCount - 1); -} - -int IndexSet::rightRangeIndexForIndexWithBounds(uint64_t idx, unsigned int left, unsigned int right) -{ - unsigned int middle = (left + right) / 2; - - Range middleRange = mRanges[middle]; - - if (left == right) { - if (idx > middleRange.location + middleRange.length) { - return left + 1; - } - else { - return left; - } - } - - if (idx < middleRange.location + middleRange.length) { - return rightRangeIndexForIndexWithBounds(idx, left, middle); - } - else { - return rightRangeIndexForIndexWithBounds(idx, middle + 1, right); - } -} - -int IndexSet::rightRangeIndexForIndex(uint64_t idx) -{ - if (mCount == 0) - return 0; - - return rightRangeIndexForIndexWithBounds(idx, 0, mCount - 1); -} - -int IndexSet::leftRangeIndexForIndexWithBounds(uint64_t idx, unsigned int left, unsigned int right) -{ - unsigned int middle = (left + right) / 2; - - Range middleRange = mRanges[middle]; - - if (left == right) { - if (idx <= RangeRightBound(middleRange)) { - return left; - } - else { - return left + 1; - } - } - - if (idx <= RangeRightBound(middleRange)) { - return leftRangeIndexForIndexWithBounds(idx, left, middle); - } - else { - return leftRangeIndexForIndexWithBounds(idx, middle + 1, right); - } -} - -int IndexSet::leftRangeIndexForIndex(uint64_t idx) -{ - if (mCount == 0) - return 0; - - return leftRangeIndexForIndexWithBounds(idx, 0, mCount - 1); -} - -void IndexSet::addRangeIndex(unsigned int rangeIndex) -{ - if (mAllocated < mCount + 1) { - while (mAllocated < mCount + 1) { - if (mAllocated == 0) { - mAllocated = 4; - } - mAllocated *= 2; - } - - Range * rangesReplacement = new Range[mAllocated]; - for(unsigned int i = 0 ; i < rangeIndex ; i ++) { - rangesReplacement[i] = mRanges[i]; - } - for(unsigned int i = rangeIndex ; i < mCount ; i ++) { - rangesReplacement[i + 1] = mRanges[i]; - } - mCount ++; - rangesReplacement[rangeIndex].location = 0; - rangesReplacement[rangeIndex].length = 0; - delete [] mRanges; - mRanges = rangesReplacement; - } - else { - if (mCount > 0) { - for(int i = mCount - 1 ; i >= (int) rangeIndex ; i --) { - mRanges[i + 1] = mRanges[i]; - } - } - mCount ++; - mRanges[rangeIndex].location = 0; - mRanges[rangeIndex].length = 0; - } -} - -void IndexSet::addRange(Range range) -{ - int rangeIndex = leftRangeIndexForIndex(range.location); - addRangeIndex(rangeIndex); - mRanges[rangeIndex] = range; - - mergeRanges(rangeIndex); - if (rangeIndex > 0) { - tryToMergeAdjacentRanges(rangeIndex - 1); - } - if (rangeIndex < mCount - 1) { - tryToMergeAdjacentRanges(rangeIndex); - } -} - -void IndexSet::tryToMergeAdjacentRanges(unsigned int rangeIndex) -{ - if (RangeRightBound(mRanges[rangeIndex]) == UINT64_MAX) - return; - - if (RangeRightBound(mRanges[rangeIndex]) + 1 != mRanges[rangeIndex + 1].location) { - return; - } - - uint64_t right = RangeRightBound(mRanges[rangeIndex + 1]); - removeRangeIndex(rangeIndex + 1, 1); - mRanges[rangeIndex].length = right - mRanges[rangeIndex].location; -} - -void IndexSet::mergeRanges(unsigned int rangeIndex) -{ - int right = rangeIndex; - - for(int i = rangeIndex ; i < mCount ; i ++) { - if (RangeHasIntersection(mRanges[rangeIndex], mRanges[i])) { - right = i; - } - else { - break; - } - } - - if (right == rangeIndex) - return; - - IndexSet * indexSet = RangeUnion(mRanges[rangeIndex], mRanges[right]); - MCAssert(indexSet->rangesCount() > 0); - Range range = indexSet->allRanges()[0]; - removeRangeIndex(rangeIndex + 1, right - rangeIndex); - mRanges[rangeIndex] = range; -} - -void IndexSet::addIndex(uint64_t idx) -{ - addRange(RangeMake(idx, 0)); -} - -void IndexSet::removeRangeIndex(unsigned int rangeIndex, unsigned int count) -{ - for(unsigned int i = rangeIndex + count ; i < mCount ; i ++) { - mRanges[i - count] = mRanges[i]; - } - mCount -= count; -} - -void IndexSet::removeRange(Range range) -{ - int left = -1; - int right = -1; - int leftRangeIndex = leftRangeIndexForIndex(range.location); - if (leftRangeIndex >= mCount) { - leftRangeIndex = mCount - 1; - } - for(int i = leftRangeIndex ; i < mCount ; i ++) { - if (RangeHasIntersection(mRanges[i], range)) { - IndexSet * indexSet = RangeRemoveRange(mRanges[i], range); - if (indexSet->rangesCount() == 0) { - if (left == -1) { - left = i; - } - right = i; - mRanges[i] = RangeEmpty; - } - else if (indexSet->rangesCount() == 1) { - mRanges[i] = indexSet->allRanges()[0]; - } - else { - MCAssert(indexSet->rangesCount() == 2); - addRangeIndex(i); - mRanges[i] = indexSet->allRanges()[0]; - mRanges[i + 1] = indexSet->allRanges()[1]; - } - } - else { - break; - } - } - - if (left != -1) { - removeRangeIndex(left, right - left + 1); - } -} - -void IndexSet::removeIndex(uint64_t idx) -{ - removeRange(RangeMake(idx, 0)); -} - -bool IndexSet::containsIndex(uint64_t idx) -{ - int rangeIndex = rangeIndexForIndex(idx); - return rangeIndex != -1; -} - -unsigned int IndexSet::rangesCount() -{ - return mCount; -} - -Range * IndexSet::allRanges() -{ - return mRanges; -} - -void IndexSet::removeAllIndexes() -{ - delete[] mRanges; - mRanges = NULL; - mAllocated = 0; - mCount = 0; -} - -String * IndexSet::description() -{ - String * result = String::string(); - for(unsigned int i = 0 ; i < mCount ; i ++) { - if (i != 0) { - result->appendUTF8Format(","); - } - if (mRanges[i].length == 0) { - result->appendUTF8Format("%llu", - (unsigned long long) mRanges[i].location); - } - else { - result->appendUTF8Format("%llu-%llu", - (unsigned long long) mRanges[i].location, - (unsigned long long) (mRanges[i].location + mRanges[i].length)); - } - } - return result; -} - -Object * IndexSet::copy() -{ - return new IndexSet(this); -} - -void IndexSet::intersectsRange(Range range) -{ - uint64_t right = RangeRightBound(range); - if (right == UINT64_MAX) { - removeRange(RangeMake(0, range.location - 1)); - } - else { - removeRange(RangeMake(0, range.location - 1)); - removeRange(RangeMake(right + 1, UINT64_MAX)); - } -} - - -HashMap * IndexSet::serializable() -{ - HashMap * result = Object::serializable(); - Array * ranges = Array::array(); - for(unsigned int i = 0 ; i < mCount ; i ++) { - ranges->addObject(RangeToString(mRanges[i])); - } - result->setObjectForKey(MCSTR("ranges"), ranges); - return result; -} - -void IndexSet::importSerializable(HashMap * serializable) -{ - Array * ranges = (Array *) serializable->objectForKey(MCSTR("ranges")); - for(unsigned int i = 0 ; i < ranges->count() ; i ++) { - String * rangeStr = (String *) ranges->objectAtIndex(i); - addRange(RangeFromString(rangeStr)); - } -} - -void IndexSet::addIndexSet(IndexSet * indexSet) -{ - for(unsigned int i = 0 ; i < indexSet->rangesCount() ; i ++) { - addRange(indexSet->allRanges()[i]); - } -} - -void IndexSet::removeIndexSet(IndexSet * indexSet) -{ - for(unsigned int i = 0 ; i < indexSet->rangesCount() ; i ++) { - removeRange(indexSet->allRanges()[i]); - } -} - -void IndexSet::intersectsIndexSet(IndexSet * indexSet) -{ - IndexSet * result = new IndexSet(); - for(unsigned int i = 0 ; i < indexSet->rangesCount() ; i ++) { - IndexSet * rangeIntersect = (IndexSet *) copy(); - rangeIntersect->intersectsRange(indexSet->allRanges()[i]); - result->addIndexSet(rangeIntersect); - rangeIntersect->release(); - } - removeAllIndexes(); - addIndexSet(result); - result->release(); -} - -static void * createObject() -{ - return new IndexSet(); -} - -INITIALIZE(IndexSet) -{ - Object::registerObjectConstructor("mailcore::IndexSet", &createObject); -} diff --git a/src/core/basetypes/MCIndexSet.cpp b/src/core/basetypes/MCIndexSet.cpp new file mode 100644 index 00000000..7f7e1db3 --- /dev/null +++ b/src/core/basetypes/MCIndexSet.cpp @@ -0,0 +1,437 @@ +// +// MCIndexSet.cpp +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/4/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIndexSet.h" + +#include "MCDefines.h" +#include "MCString.h" +#include "MCAssert.h" +#include "MCRange.h" +#include "MCLog.h" +#include "MCArray.h" +#include "MCHashMap.h" +#include "MCUtils.h" + +using namespace mailcore; + +void IndexSet::init() +{ + mRanges = NULL; + mAllocated = 0; + mCount = 0; +} + +IndexSet::IndexSet() +{ + init(); +} + +IndexSet::IndexSet(IndexSet * o) +{ + init(); + mRanges = new Range[o->mAllocated]; + for(unsigned int i = 0 ; i < o->mCount ; i ++) { + mRanges[i] = o->mRanges[i]; + } + mAllocated = o->mAllocated; + mCount = o->mCount; +} + +IndexSet::~IndexSet() +{ + removeAllIndexes(); +} + +IndexSet * IndexSet::indexSet() +{ + IndexSet * result = new IndexSet(); + result->autorelease(); + return result; +} + +IndexSet * IndexSet::indexSetWithRange(Range range) +{ + IndexSet * result = new IndexSet(); + result->autorelease(); + result->addRange(range); + return result; +} + +IndexSet * IndexSet::indexSetWithIndex(uint64_t idx) +{ + IndexSet * result = new IndexSet(); + result->autorelease(); + result->addIndex(idx); + return result; +} + +unsigned int IndexSet::count() +{ + unsigned int total = 0; + for(unsigned int i = 0 ; i < mCount ; i ++) { + total += mRanges[i].length + 1; + } + return total; +} + +int IndexSet::rangeIndexForIndexWithBounds(uint64_t idx, unsigned int left, unsigned int right) +{ + unsigned int middle = (left + right) / 2; + + Range middleRange = mRanges[middle]; + + if (left == right) { + if ((idx >= RangeLeftBound(middleRange)) && (idx <= RangeRightBound(middleRange))) { + return left; + } + return -1; + } + + if ((idx >= RangeLeftBound(middleRange)) && (idx <= RangeRightBound(middleRange))) { + return middle; + } + if (idx < middleRange.location) { + return rangeIndexForIndexWithBounds(idx, left, middle); + } + else { + return rangeIndexForIndexWithBounds(idx, middle + 1, right); + } +} + +int IndexSet::rangeIndexForIndex(uint64_t idx) +{ + if (mCount == 0) + return -1; + + return rangeIndexForIndexWithBounds(idx, 0, mCount - 1); +} + +int IndexSet::rightRangeIndexForIndexWithBounds(uint64_t idx, unsigned int left, unsigned int right) +{ + unsigned int middle = (left + right) / 2; + + Range middleRange = mRanges[middle]; + + if (left == right) { + if (idx > middleRange.location + middleRange.length) { + return left + 1; + } + else { + return left; + } + } + + if (idx < middleRange.location + middleRange.length) { + return rightRangeIndexForIndexWithBounds(idx, left, middle); + } + else { + return rightRangeIndexForIndexWithBounds(idx, middle + 1, right); + } +} + +int IndexSet::rightRangeIndexForIndex(uint64_t idx) +{ + if (mCount == 0) + return 0; + + return rightRangeIndexForIndexWithBounds(idx, 0, mCount - 1); +} + +int IndexSet::leftRangeIndexForIndexWithBounds(uint64_t idx, unsigned int left, unsigned int right) +{ + unsigned int middle = (left + right) / 2; + + Range middleRange = mRanges[middle]; + + if (left == right) { + if (idx <= RangeRightBound(middleRange)) { + return left; + } + else { + return left + 1; + } + } + + if (idx <= RangeRightBound(middleRange)) { + return leftRangeIndexForIndexWithBounds(idx, left, middle); + } + else { + return leftRangeIndexForIndexWithBounds(idx, middle + 1, right); + } +} + +int IndexSet::leftRangeIndexForIndex(uint64_t idx) +{ + if (mCount == 0) + return 0; + + return leftRangeIndexForIndexWithBounds(idx, 0, mCount - 1); +} + +void IndexSet::addRangeIndex(unsigned int rangeIndex) +{ + if (mAllocated < mCount + 1) { + while (mAllocated < mCount + 1) { + if (mAllocated == 0) { + mAllocated = 4; + } + mAllocated *= 2; + } + + Range * rangesReplacement = new Range[mAllocated]; + for(unsigned int i = 0 ; i < rangeIndex ; i ++) { + rangesReplacement[i] = mRanges[i]; + } + for(unsigned int i = rangeIndex ; i < mCount ; i ++) { + rangesReplacement[i + 1] = mRanges[i]; + } + mCount ++; + rangesReplacement[rangeIndex].location = 0; + rangesReplacement[rangeIndex].length = 0; + delete [] mRanges; + mRanges = rangesReplacement; + } + else { + if (mCount > 0) { + for(int i = mCount - 1 ; i >= (int) rangeIndex ; i --) { + mRanges[i + 1] = mRanges[i]; + } + } + mCount ++; + mRanges[rangeIndex].location = 0; + mRanges[rangeIndex].length = 0; + } +} + +void IndexSet::addRange(Range range) +{ + int rangeIndex = leftRangeIndexForIndex(range.location); + addRangeIndex(rangeIndex); + mRanges[rangeIndex] = range; + + mergeRanges(rangeIndex); + if (rangeIndex > 0) { + tryToMergeAdjacentRanges(rangeIndex - 1); + } + if (rangeIndex < mCount - 1) { + tryToMergeAdjacentRanges(rangeIndex); + } +} + +void IndexSet::tryToMergeAdjacentRanges(unsigned int rangeIndex) +{ + if (RangeRightBound(mRanges[rangeIndex]) == UINT64_MAX) + return; + + if (RangeRightBound(mRanges[rangeIndex]) + 1 != mRanges[rangeIndex + 1].location) { + return; + } + + uint64_t right = RangeRightBound(mRanges[rangeIndex + 1]); + removeRangeIndex(rangeIndex + 1, 1); + mRanges[rangeIndex].length = right - mRanges[rangeIndex].location; +} + +void IndexSet::mergeRanges(unsigned int rangeIndex) +{ + int right = rangeIndex; + + for(int i = rangeIndex ; i < mCount ; i ++) { + if (RangeHasIntersection(mRanges[rangeIndex], mRanges[i])) { + right = i; + } + else { + break; + } + } + + if (right == rangeIndex) + return; + + IndexSet * indexSet = RangeUnion(mRanges[rangeIndex], mRanges[right]); + MCAssert(indexSet->rangesCount() > 0); + Range range = indexSet->allRanges()[0]; + removeRangeIndex(rangeIndex + 1, right - rangeIndex); + mRanges[rangeIndex] = range; +} + +void IndexSet::addIndex(uint64_t idx) +{ + addRange(RangeMake(idx, 0)); +} + +void IndexSet::removeRangeIndex(unsigned int rangeIndex, unsigned int count) +{ + for(unsigned int i = rangeIndex + count ; i < mCount ; i ++) { + mRanges[i - count] = mRanges[i]; + } + mCount -= count; +} + +void IndexSet::removeRange(Range range) +{ + int left = -1; + int right = -1; + int leftRangeIndex = leftRangeIndexForIndex(range.location); + if (leftRangeIndex >= mCount) { + leftRangeIndex = mCount - 1; + } + for(int i = leftRangeIndex ; i < mCount ; i ++) { + if (RangeHasIntersection(mRanges[i], range)) { + IndexSet * indexSet = RangeRemoveRange(mRanges[i], range); + if (indexSet->rangesCount() == 0) { + if (left == -1) { + left = i; + } + right = i; + mRanges[i] = RangeEmpty; + } + else if (indexSet->rangesCount() == 1) { + mRanges[i] = indexSet->allRanges()[0]; + } + else { + MCAssert(indexSet->rangesCount() == 2); + addRangeIndex(i); + mRanges[i] = indexSet->allRanges()[0]; + mRanges[i + 1] = indexSet->allRanges()[1]; + } + } + else { + break; + } + } + + if (left != -1) { + removeRangeIndex(left, right - left + 1); + } +} + +void IndexSet::removeIndex(uint64_t idx) +{ + removeRange(RangeMake(idx, 0)); +} + +bool IndexSet::containsIndex(uint64_t idx) +{ + int rangeIndex = rangeIndexForIndex(idx); + return rangeIndex != -1; +} + +unsigned int IndexSet::rangesCount() +{ + return mCount; +} + +Range * IndexSet::allRanges() +{ + return mRanges; +} + +void IndexSet::removeAllIndexes() +{ + delete[] mRanges; + mRanges = NULL; + mAllocated = 0; + mCount = 0; +} + +String * IndexSet::description() +{ + String * result = String::string(); + for(unsigned int i = 0 ; i < mCount ; i ++) { + if (i != 0) { + result->appendUTF8Format(","); + } + if (mRanges[i].length == 0) { + result->appendUTF8Format("%llu", + (unsigned long long) mRanges[i].location); + } + else { + result->appendUTF8Format("%llu-%llu", + (unsigned long long) mRanges[i].location, + (unsigned long long) (mRanges[i].location + mRanges[i].length)); + } + } + return result; +} + +Object * IndexSet::copy() +{ + return new IndexSet(this); +} + +void IndexSet::intersectsRange(Range range) +{ + uint64_t right = RangeRightBound(range); + if (right == UINT64_MAX) { + removeRange(RangeMake(0, range.location - 1)); + } + else { + removeRange(RangeMake(0, range.location - 1)); + removeRange(RangeMake(right + 1, UINT64_MAX)); + } +} + + +HashMap * IndexSet::serializable() +{ + HashMap * result = Object::serializable(); + Array * ranges = Array::array(); + for(unsigned int i = 0 ; i < mCount ; i ++) { + ranges->addObject(RangeToString(mRanges[i])); + } + result->setObjectForKey(MCSTR("ranges"), ranges); + return result; +} + +void IndexSet::importSerializable(HashMap * serializable) +{ + Array * ranges = (Array *) serializable->objectForKey(MCSTR("ranges")); + for(unsigned int i = 0 ; i < ranges->count() ; i ++) { + String * rangeStr = (String *) ranges->objectAtIndex(i); + addRange(RangeFromString(rangeStr)); + } +} + +void IndexSet::addIndexSet(IndexSet * indexSet) +{ + for(unsigned int i = 0 ; i < indexSet->rangesCount() ; i ++) { + addRange(indexSet->allRanges()[i]); + } +} + +void IndexSet::removeIndexSet(IndexSet * indexSet) +{ + for(unsigned int i = 0 ; i < indexSet->rangesCount() ; i ++) { + removeRange(indexSet->allRanges()[i]); + } +} + +void IndexSet::intersectsIndexSet(IndexSet * indexSet) +{ + IndexSet * result = new IndexSet(); + for(unsigned int i = 0 ; i < indexSet->rangesCount() ; i ++) { + IndexSet * rangeIntersect = (IndexSet *) copy(); + rangeIntersect->intersectsRange(indexSet->allRanges()[i]); + result->addIndexSet(rangeIntersect); + rangeIntersect->release(); + } + removeAllIndexes(); + addIndexSet(result); + result->release(); +} + +static void * createObject() +{ + return new IndexSet(); +} + +INITIALIZE(IndexSet) +{ + Object::registerObjectConstructor("mailcore::IndexSet", &createObject); +} diff --git a/src/core/basetypes/MCJSON.cc b/src/core/basetypes/MCJSON.cc deleted file mode 100644 index 5ce879ee..00000000 --- a/src/core/basetypes/MCJSON.cc +++ /dev/null @@ -1,35 +0,0 @@ -// -// MCJSON.cpp -// hermes -// -// Created by DINH Viêt Hoà on 4/8/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCJSON.h" - -#include - -#include "MCJSONParser.h" - -using namespace mailcore; - -String * JSON::objectToJSONString(Object * object) -{ - return JSONParser::stringFromObject(object); -} - -Data * JSON::objectToJSONData(Object * object) -{ - return JSONParser::dataFromObject(object); -} - -Object * JSON::objectFromJSONString(String * json) -{ - return JSONParser::objectFromString(json); -} - -Object * JSON::objectFromJSONData(Data * json) -{ - return JSONParser::objectFromData(json); -} diff --git a/src/core/basetypes/MCJSON.cpp b/src/core/basetypes/MCJSON.cpp new file mode 100644 index 00000000..5ce879ee --- /dev/null +++ b/src/core/basetypes/MCJSON.cpp @@ -0,0 +1,35 @@ +// +// MCJSON.cpp +// hermes +// +// Created by DINH Viêt Hoà on 4/8/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCJSON.h" + +#include + +#include "MCJSONParser.h" + +using namespace mailcore; + +String * JSON::objectToJSONString(Object * object) +{ + return JSONParser::stringFromObject(object); +} + +Data * JSON::objectToJSONData(Object * object) +{ + return JSONParser::dataFromObject(object); +} + +Object * JSON::objectFromJSONString(String * json) +{ + return JSONParser::objectFromString(json); +} + +Object * JSON::objectFromJSONData(Data * json) +{ + return JSONParser::objectFromData(json); +} diff --git a/src/core/basetypes/MCJSONParser.cc b/src/core/basetypes/MCJSONParser.cc deleted file mode 100644 index d9f68204..00000000 --- a/src/core/basetypes/MCJSONParser.cc +++ /dev/null @@ -1,827 +0,0 @@ -// -// JSONParser.cpp -// mailcore2 -// -// Created by DINH Viêt Hoà on 4/17/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCJSONParser.h" - -#include - -#include "MCUtils.h" -#include "MCString.h" -#include "MCData.h" -#include "MCHashMap.h" -#include "MCArray.h" -#include "MCValue.h" -#include "MCNull.h" -#include "MCAutoreleasePool.h" -#include "MCAssert.h" - -using namespace mailcore; - -void JSONParser::init() -{ - mContent = NULL; - mResult = NULL; - mPosition = 0; -} - -JSONParser::JSONParser() -{ - init(); -} - -JSONParser::~JSONParser() -{ - MC_SAFE_RELEASE(mResult); - MC_SAFE_RELEASE(mContent); -} - -String * JSONParser::content() -{ - return mContent; -} - -void JSONParser::setContent(String * content) -{ - MC_SAFE_REPLACE_RETAIN(String, mContent, content); -} - -unsigned int JSONParser::position() -{ - return mPosition; -} - -void JSONParser::setPosition(unsigned int position) -{ - mPosition = position; -} - -Object * JSONParser::result() -{ - return mResult; -} - -bool JSONParser::parse() -{ - skipBlank(); - if (parseDictionary()) - return true; - if (parseArray()) - return true; - if (parseBoolean()) - return true; - if (parseNull()) - return true; - if (parseFloat()) - return true; - if (parseString()) - return true; - - return false; -} - -bool JSONParser::isEndOfExpression() -{ - if (mPosition == mContent->length()) - return true; - - if (mContent->characterAtIndex(mPosition) == ';') - return true; - - return false; -} - -void JSONParser::skipBlank() -{ - mPosition = skipBlank(mPosition); -} - -unsigned int JSONParser::skipBlank(unsigned int position) -{ - while (1) { - UChar ch; - - if (position >= mContent->length()) - break; - - ch = mContent->characterAtIndex(position); - if ((ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == '\n')) - position ++; - else - break; - } - - return position; -} - -bool JSONParser::parseDictionary() -{ - int position; - HashMap * dict; - - position = mPosition; - - if (!scanCharacter('{', position)) { - return false; - } - position ++; - position = skipBlank(position); - - dict = HashMap::hashMap(); - - if (scanCharacter('}', position)) { - position ++; - } - else { - while (1) { - JSONParser * keyParser; - JSONParser * valueParser; - String * key; - Object * value; - - if (position >= mContent->length()) - return false; - - key = NULL; - keyParser = new JSONParser(); - keyParser->autorelease(); - keyParser->setContent(mContent); - keyParser->setPosition(position); - if (!keyParser->parse()) - return false; - - if (!keyParser->result()->className()->isEqual(MCSTR("mailcore::String"))) - return false; - - key = (String *) keyParser->result(); - position = keyParser->position(); - - position = skipBlank(position); - - if (!scanCharacter(':', position)) - return false; - position ++; - - position = skipBlank(position); - - value = NULL; - valueParser = new JSONParser(); - valueParser->autorelease(); - valueParser->setContent(mContent); - valueParser->setPosition(position); - if (!valueParser->parse()) - return false; - - value = valueParser->result(); - position = valueParser->position(); - - dict->setObjectForKey(key, value); - - position = skipBlank(position); - - if (scanCharacter(',', position)) { - position ++; - position = skipBlank(position); - } - else if (scanCharacter('}', position)) { - position ++; - break; - } - else { - return false; - } - } - } - - mResult = dict->retain(); - mPosition = position; - - return true; -} - -bool JSONParser::scanCharacter(UChar ch, unsigned int position) -{ - if (position >= mContent->length()) - return false; - - if (mContent->characterAtIndex(position) != ch) - return false; - - return true; -} - -bool JSONParser::scanKeyword(String * str, unsigned int position) -{ - bool result; - AutoreleasePool * pool; - - if (position + str->length() >= mContent->length()) - return false; - - pool = new AutoreleasePool(); - - result = false; - if (mContent->substringWithRange(RangeMake(position, str->length()))->isEqual(str)) - result = true; - pool->release(); - - return result; -} - -bool JSONParser::parseArray() -{ - int position; - Array * array; - - position = mPosition; - - if (!scanCharacter('[', position)) { - return false; - } - position ++; - position = skipBlank(position); - - array = Array::array(); - - if (scanCharacter(']', position)) { - position ++; - } - else { - while (1) { - JSONParser * valueParser; - Object * value; - - if (position >= mContent->length()) - return false; - - value = NULL; - valueParser = new JSONParser(); - valueParser->setContent(mContent); - valueParser->setPosition(position); - valueParser->autorelease(); - if (!valueParser->parse()) - return false; - - value = valueParser->result(); - - position = valueParser->position(); - array->addObject(value); - - position = skipBlank(position); - - if (scanCharacter(',', position)) { - position ++; - position = skipBlank(position); - } - else if (scanCharacter(']', position)) { - position ++; - break; - } - else { - return false; - } - } - } - - mResult = array->retain(); - mPosition = position; - - return true; -} - -static inline int hexToInt(UChar inCharacter) -{ - if (inCharacter >= '0' && inCharacter <= '9') { - return inCharacter - '0'; - } - else if (inCharacter >= 'a' && inCharacter <= 'f') { - return inCharacter - 'a' + 10; - } - else if (inCharacter >= 'A' && inCharacter <= 'F') { - return inCharacter - 'A' + 10; - } - else { - return -1; - } -} - -bool JSONParser::parseString() -{ - unsigned int position; - String * str; - bool doubleQuote = false; - bool startString; - bool endOfString; - - position = mPosition; - - startString = false; - if (scanCharacter('\"', position)) { - doubleQuote = true; - startString = true; - } - else if (scanCharacter('\'', position)) { - startString = true; - } - - if (!startString) - return false; - - position ++; - - str = String::string(); - - endOfString = false; - while (1) { - UChar ch; - - if (position >= mContent->length()) - return false; - - ch = mContent->characterAtIndex(position); - switch (ch) { - case '\\': - { - position ++; - - if (position >= mContent->length()) - return false; - - ch = mContent->characterAtIndex(position); - switch (ch) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': { - UChar char_value; - unsigned int count; - - count = 0; - char_value = 0; - while ((ch >= '0') && (ch <= '7')) { - int value; - - value = hexToInt(ch); - if (value == -1) - break; - - char_value = char_value * 8 + value; - count ++; - position ++; - if (count >= 3) - break; - if (position >= mContent->length()) - break; - ch = mContent->characterAtIndex(position); - } - UChar characters[2]; - characters[0] = char_value; - characters[1] = 0; - str->appendCharactersLength(characters, 1); - break; - } - case 'b': - str->appendString(MCSTR("\b")); - position ++; - break; - case 't': - str->appendString(MCSTR("\t")); - position ++; - break; - case 'n': - str->appendString(MCSTR("\n")); - position ++; - break; - case 'r': - str->appendString(MCSTR("\r")); - position ++; - break; - case 'f': - str->appendString(MCSTR("\f")); - position ++; - break; - case 'v': - str->appendString(MCSTR("\v")); - position ++; - break; - case '\"': - str->appendString(MCSTR("\"")); - position ++; - break; - case '\'': - str->appendString(MCSTR("\'")); - position ++; - break; - case '\\': - str->appendString(MCSTR("\\")); - position ++; - break; - case '/': - str->appendString(MCSTR("/")); - position ++; - break; - case 'u': { - unsigned int i; - UChar char_value; - - position ++; - char_value = 0; - for(i = 0 ; i < 4 ; i ++) { - int value; - - if (position >= mContent->length()) - return false; - ch = mContent->characterAtIndex(position); - value = hexToInt(ch); - if (value == -1) - break; - - char_value = char_value * 16 + value; - position ++; - } - - UChar characters[2]; - characters[0] = char_value; - characters[1] = 0; - str->appendCharactersLength(characters, 1); - - break; - } - case 'x': { - unsigned int i; - UChar char_value; - - position ++; - char_value = 0; - for(i = 0 ; i < 2 ; i ++) { - int value; - - if (position >= mContent->length()) - return false; - ch = mContent->characterAtIndex(position); - value = hexToInt(ch); - if (value == -1) - break; - - char_value = char_value * 16 + value; - position ++; - } - - UChar characters[2]; - characters[0] = char_value; - characters[1] = 0; - str->appendCharactersLength(characters, 1); - - break; - } - default: { - UChar characters[3]; - characters[0] = '\\'; - characters[1] = ch; - characters[2] = 0; - str->appendCharactersLength(characters, 2); - - position ++; - break; - } - } - break; - } - - case '\'': - position ++; - if (!doubleQuote) - endOfString = true; - else - str->appendString(MCSTR("\'")); - break; - case '\"': - position ++; - if (doubleQuote) - endOfString = true; - else - str->appendString(MCSTR("\"")); - break; - default: { - position ++; - UChar characters[2]; - characters[0] = ch; - characters[1] = 0; - str->appendCharactersLength(characters, 1); - break; - } - } - - if (endOfString) - break; - } - - mResult = str->retain(); - mPosition = position; - - return true; -} - -bool JSONParser::parseBoolean() -{ - if (scanKeyword(MCSTR("true"), mPosition)) { - mPosition += MCSTR("true")->length(); - mResult = Value::valueWithBoolValue(true)->retain();; - return true; - } - - if (scanKeyword(MCSTR("false"), mPosition)) { - mPosition += MCSTR("false")->length(); - mResult = Value::valueWithBoolValue(false)->retain();; - return true; - } - - return false; -} - -bool JSONParser::parseNull() -{ - if (scanKeyword(MCSTR("null"), mPosition)) { - mPosition += MCSTR("null")->length(); - mResult = Null::null()->retain(); - return true; - } - - return false; -} - -bool JSONParser::parseFloat() -{ - const char * str; - char * endptr; - double value; - char * endptrInt; - long long valueInt; - - AutoreleasePool * pool; - - pool = new AutoreleasePool(); - if (mContent->length() > mPosition + 50) { - str = mContent->substringWithRange(RangeMake(mPosition, 50))->UTF8Characters(); - } - else { - str = mContent->substringFromIndex(mPosition)->UTF8Characters(); - } - value = strtod(str, &endptr); - if (endptr == str) { - pool->release(); - return false; - } - valueInt = strtoll(str, &endptrInt, 0); - if (endptr == endptrInt) { - mPosition += endptrInt - str; - mResult = Value::valueWithLongLongValue(valueInt)->retain(); - } - else { - mPosition += endptr - str; - mResult = Value::valueWithDoubleValue(value); - } - pool->release(); - - return true; -} - -Object * JSONParser::objectFromData(Data * data) -{ - String * str = NULL; - Object * result; - - str = String::stringWithData(data, "utf-8"); - if (str == NULL) - return NULL; - - result = objectFromString(str); - - return result; -} - -Object * JSONParser::objectFromString(String * str) -{ - Object * result; - JSONParser * parser; - - parser = new JSONParser(); - parser->setContent(str); - parser->parse(); - result = parser->result(); - result->retain()->autorelease(); - parser->release(); - - return result; -} - -Data * JSONParser::dataFromObject(Object * object) -{ - return stringFromObject(object)->dataUsingEncoding("utf-8"); -} - -String * JSONParser::stringFromObject(Object * object) -{ - String * result; - - result = String::string(); - appendStringFromObject(object, result); - - return result; -} - - -String * JSONParser::JSStringFromString(String * str) -{ - unsigned int i; - String * result; - - result = String::string(); - for(i = 0 ; i < str->length() ; i ++) { - UChar ch; - - ch = str->characterAtIndex(i); - if ((ch >= '0') && (ch <= '9')) { - UChar characters[2]; - characters[0] = ch; - characters[1] = 0; - result->appendCharactersLength(characters, 1); - } - else if ((ch >= 'a') && (ch <= 'z')) { - UChar characters[2]; - characters[0] = ch; - characters[1] = 0; - result->appendCharactersLength(characters, 1); - } - else if ((ch >= 'A') && (ch <= 'Z')) { - UChar characters[2]; - characters[0] = ch; - characters[1] = 0; - result->appendCharactersLength(characters, 1); - } - else { - switch (ch) { - case ' ': - case '.': - case ',': - case '<': - case '>': - case '(': - case ')': - case '!': - case '@': - case '#': - case '$': - case '%': - case '^': - case '&': - case '*': - case '-': - case '_': - case '+': - case '=': - case '?': - case '{': - case '}': - case '[': - case ']': - case ':': - case ';': - case '|': - case '~': - case '\'': { - UChar characters[2]; - characters[0] = ch; - characters[1] = 0; - result->appendCharactersLength(characters, 1); - break; - } - case '"': - case '/': - case '\\': { - UChar characters[3]; - characters[0] = '\\'; - characters[1] = ch; - characters[2] = 0; - result->appendCharactersLength(characters, 2); - break; - } - default: { - result->appendUTF8Format("\\u%04x", (unsigned int) ch); - break; - } - } - } - } - - return result; -} - -void JSONParser::appendStringFromObject(Object * object, String * string) -{ - if (object->className()->isEqual(MCSTR("mailcore::String"))) { - string->appendString(MCSTR("\"")); - string->appendString(JSStringFromString((String *) object)); - string->appendString(MCSTR("\"")); - } - else if (object->className()->isEqual(MCSTR("mailcore::Value"))) { - Value * value = (Value *) object; - switch (value->type()) { - case ValueTypeBool: - string->appendString(value->boolValue() ? MCSTR("true") : MCSTR("false")); - break; - case ValueTypeChar: - string->appendUTF8Format("%i", (int) value->charValue()); - break; - case ValueTypeUnsignedChar: - string->appendUTF8Format("%i", (int) value->unsignedCharValue()); - break; - case ValueTypeShort: - string->appendUTF8Format("%i", (int) value->shortValue()); - break; - case ValueTypeUnsignedShort: - string->appendUTF8Format("%i", (int) value->unsignedShortValue()); - break; - case ValueTypeInt: - string->appendUTF8Format("%i", (int) value->intValue()); - break; - case ValueTypeUnsignedInt: - string->appendUTF8Format("%u", (int) value->unsignedIntValue()); - break; - case ValueTypeLong: - string->appendUTF8Format("%ld", value->longValue()); - break; - case ValueTypeUnsignedLong: - string->appendUTF8Format("%lu", value->unsignedLongValue()); - break; - case ValueTypeLongLong: - string->appendUTF8Format("%lld", value->longLongValue()); - break; - case ValueTypeUnsignedLongLong: - string->appendUTF8Format("%llu", value->unsignedLongLongValue()); - break; - case ValueTypeFloat: - string->appendUTF8Format("%g", value->floatValue()); - break; - case ValueTypeDouble: - string->appendUTF8Format("%lg", value->doubleValue()); - break; - default: - MCAssert(0); - break; - } - } - else if (object->className()->isEqual(MCSTR("mailcore::Null"))) { - string->appendString(MCSTR("null")); - } - else if (object->className()->isEqual(MCSTR("mailcore::Array"))) { - Array * array; - bool first; - - first = true; - array = (Array *) object; - string->appendString(MCSTR("[")); - for(unsigned int i = 0 ; i < array->count() ; i ++) { - Object * arrayElement = array->objectAtIndex(i); - if (first) { - first = false; - } - else { - string->appendString(MCSTR(",")); - } - appendStringFromObject(arrayElement, string); - } - string->appendString(MCSTR("]")); - } - else if (object->className()->isEqual(MCSTR("mailcore::HashMap"))) { - HashMap * dict; - bool first; - - first = true; - dict = (HashMap *) object; - string->appendString(MCSTR("{")); - Array * keys = dict->allKeys(); - for(unsigned int i = 0 ; i < keys->count() ; i ++) { - String * key = (String *) keys->objectAtIndex(i); - - if (first) { - first = false; - } - else { - string->appendString(MCSTR(",")); - } - appendStringFromObject(key, string); - string->appendString(MCSTR(":")); - appendStringFromObject(dict->objectForKey(key), string); - } - string->appendString(MCSTR("}")); - } -} diff --git a/src/core/basetypes/MCJSONParser.cpp b/src/core/basetypes/MCJSONParser.cpp new file mode 100644 index 00000000..d9f68204 --- /dev/null +++ b/src/core/basetypes/MCJSONParser.cpp @@ -0,0 +1,827 @@ +// +// JSONParser.cpp +// mailcore2 +// +// Created by DINH Viêt Hoà on 4/17/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCJSONParser.h" + +#include + +#include "MCUtils.h" +#include "MCString.h" +#include "MCData.h" +#include "MCHashMap.h" +#include "MCArray.h" +#include "MCValue.h" +#include "MCNull.h" +#include "MCAutoreleasePool.h" +#include "MCAssert.h" + +using namespace mailcore; + +void JSONParser::init() +{ + mContent = NULL; + mResult = NULL; + mPosition = 0; +} + +JSONParser::JSONParser() +{ + init(); +} + +JSONParser::~JSONParser() +{ + MC_SAFE_RELEASE(mResult); + MC_SAFE_RELEASE(mContent); +} + +String * JSONParser::content() +{ + return mContent; +} + +void JSONParser::setContent(String * content) +{ + MC_SAFE_REPLACE_RETAIN(String, mContent, content); +} + +unsigned int JSONParser::position() +{ + return mPosition; +} + +void JSONParser::setPosition(unsigned int position) +{ + mPosition = position; +} + +Object * JSONParser::result() +{ + return mResult; +} + +bool JSONParser::parse() +{ + skipBlank(); + if (parseDictionary()) + return true; + if (parseArray()) + return true; + if (parseBoolean()) + return true; + if (parseNull()) + return true; + if (parseFloat()) + return true; + if (parseString()) + return true; + + return false; +} + +bool JSONParser::isEndOfExpression() +{ + if (mPosition == mContent->length()) + return true; + + if (mContent->characterAtIndex(mPosition) == ';') + return true; + + return false; +} + +void JSONParser::skipBlank() +{ + mPosition = skipBlank(mPosition); +} + +unsigned int JSONParser::skipBlank(unsigned int position) +{ + while (1) { + UChar ch; + + if (position >= mContent->length()) + break; + + ch = mContent->characterAtIndex(position); + if ((ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == '\n')) + position ++; + else + break; + } + + return position; +} + +bool JSONParser::parseDictionary() +{ + int position; + HashMap * dict; + + position = mPosition; + + if (!scanCharacter('{', position)) { + return false; + } + position ++; + position = skipBlank(position); + + dict = HashMap::hashMap(); + + if (scanCharacter('}', position)) { + position ++; + } + else { + while (1) { + JSONParser * keyParser; + JSONParser * valueParser; + String * key; + Object * value; + + if (position >= mContent->length()) + return false; + + key = NULL; + keyParser = new JSONParser(); + keyParser->autorelease(); + keyParser->setContent(mContent); + keyParser->setPosition(position); + if (!keyParser->parse()) + return false; + + if (!keyParser->result()->className()->isEqual(MCSTR("mailcore::String"))) + return false; + + key = (String *) keyParser->result(); + position = keyParser->position(); + + position = skipBlank(position); + + if (!scanCharacter(':', position)) + return false; + position ++; + + position = skipBlank(position); + + value = NULL; + valueParser = new JSONParser(); + valueParser->autorelease(); + valueParser->setContent(mContent); + valueParser->setPosition(position); + if (!valueParser->parse()) + return false; + + value = valueParser->result(); + position = valueParser->position(); + + dict->setObjectForKey(key, value); + + position = skipBlank(position); + + if (scanCharacter(',', position)) { + position ++; + position = skipBlank(position); + } + else if (scanCharacter('}', position)) { + position ++; + break; + } + else { + return false; + } + } + } + + mResult = dict->retain(); + mPosition = position; + + return true; +} + +bool JSONParser::scanCharacter(UChar ch, unsigned int position) +{ + if (position >= mContent->length()) + return false; + + if (mContent->characterAtIndex(position) != ch) + return false; + + return true; +} + +bool JSONParser::scanKeyword(String * str, unsigned int position) +{ + bool result; + AutoreleasePool * pool; + + if (position + str->length() >= mContent->length()) + return false; + + pool = new AutoreleasePool(); + + result = false; + if (mContent->substringWithRange(RangeMake(position, str->length()))->isEqual(str)) + result = true; + pool->release(); + + return result; +} + +bool JSONParser::parseArray() +{ + int position; + Array * array; + + position = mPosition; + + if (!scanCharacter('[', position)) { + return false; + } + position ++; + position = skipBlank(position); + + array = Array::array(); + + if (scanCharacter(']', position)) { + position ++; + } + else { + while (1) { + JSONParser * valueParser; + Object * value; + + if (position >= mContent->length()) + return false; + + value = NULL; + valueParser = new JSONParser(); + valueParser->setContent(mContent); + valueParser->setPosition(position); + valueParser->autorelease(); + if (!valueParser->parse()) + return false; + + value = valueParser->result(); + + position = valueParser->position(); + array->addObject(value); + + position = skipBlank(position); + + if (scanCharacter(',', position)) { + position ++; + position = skipBlank(position); + } + else if (scanCharacter(']', position)) { + position ++; + break; + } + else { + return false; + } + } + } + + mResult = array->retain(); + mPosition = position; + + return true; +} + +static inline int hexToInt(UChar inCharacter) +{ + if (inCharacter >= '0' && inCharacter <= '9') { + return inCharacter - '0'; + } + else if (inCharacter >= 'a' && inCharacter <= 'f') { + return inCharacter - 'a' + 10; + } + else if (inCharacter >= 'A' && inCharacter <= 'F') { + return inCharacter - 'A' + 10; + } + else { + return -1; + } +} + +bool JSONParser::parseString() +{ + unsigned int position; + String * str; + bool doubleQuote = false; + bool startString; + bool endOfString; + + position = mPosition; + + startString = false; + if (scanCharacter('\"', position)) { + doubleQuote = true; + startString = true; + } + else if (scanCharacter('\'', position)) { + startString = true; + } + + if (!startString) + return false; + + position ++; + + str = String::string(); + + endOfString = false; + while (1) { + UChar ch; + + if (position >= mContent->length()) + return false; + + ch = mContent->characterAtIndex(position); + switch (ch) { + case '\\': + { + position ++; + + if (position >= mContent->length()) + return false; + + ch = mContent->characterAtIndex(position); + switch (ch) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': { + UChar char_value; + unsigned int count; + + count = 0; + char_value = 0; + while ((ch >= '0') && (ch <= '7')) { + int value; + + value = hexToInt(ch); + if (value == -1) + break; + + char_value = char_value * 8 + value; + count ++; + position ++; + if (count >= 3) + break; + if (position >= mContent->length()) + break; + ch = mContent->characterAtIndex(position); + } + UChar characters[2]; + characters[0] = char_value; + characters[1] = 0; + str->appendCharactersLength(characters, 1); + break; + } + case 'b': + str->appendString(MCSTR("\b")); + position ++; + break; + case 't': + str->appendString(MCSTR("\t")); + position ++; + break; + case 'n': + str->appendString(MCSTR("\n")); + position ++; + break; + case 'r': + str->appendString(MCSTR("\r")); + position ++; + break; + case 'f': + str->appendString(MCSTR("\f")); + position ++; + break; + case 'v': + str->appendString(MCSTR("\v")); + position ++; + break; + case '\"': + str->appendString(MCSTR("\"")); + position ++; + break; + case '\'': + str->appendString(MCSTR("\'")); + position ++; + break; + case '\\': + str->appendString(MCSTR("\\")); + position ++; + break; + case '/': + str->appendString(MCSTR("/")); + position ++; + break; + case 'u': { + unsigned int i; + UChar char_value; + + position ++; + char_value = 0; + for(i = 0 ; i < 4 ; i ++) { + int value; + + if (position >= mContent->length()) + return false; + ch = mContent->characterAtIndex(position); + value = hexToInt(ch); + if (value == -1) + break; + + char_value = char_value * 16 + value; + position ++; + } + + UChar characters[2]; + characters[0] = char_value; + characters[1] = 0; + str->appendCharactersLength(characters, 1); + + break; + } + case 'x': { + unsigned int i; + UChar char_value; + + position ++; + char_value = 0; + for(i = 0 ; i < 2 ; i ++) { + int value; + + if (position >= mContent->length()) + return false; + ch = mContent->characterAtIndex(position); + value = hexToInt(ch); + if (value == -1) + break; + + char_value = char_value * 16 + value; + position ++; + } + + UChar characters[2]; + characters[0] = char_value; + characters[1] = 0; + str->appendCharactersLength(characters, 1); + + break; + } + default: { + UChar characters[3]; + characters[0] = '\\'; + characters[1] = ch; + characters[2] = 0; + str->appendCharactersLength(characters, 2); + + position ++; + break; + } + } + break; + } + + case '\'': + position ++; + if (!doubleQuote) + endOfString = true; + else + str->appendString(MCSTR("\'")); + break; + case '\"': + position ++; + if (doubleQuote) + endOfString = true; + else + str->appendString(MCSTR("\"")); + break; + default: { + position ++; + UChar characters[2]; + characters[0] = ch; + characters[1] = 0; + str->appendCharactersLength(characters, 1); + break; + } + } + + if (endOfString) + break; + } + + mResult = str->retain(); + mPosition = position; + + return true; +} + +bool JSONParser::parseBoolean() +{ + if (scanKeyword(MCSTR("true"), mPosition)) { + mPosition += MCSTR("true")->length(); + mResult = Value::valueWithBoolValue(true)->retain();; + return true; + } + + if (scanKeyword(MCSTR("false"), mPosition)) { + mPosition += MCSTR("false")->length(); + mResult = Value::valueWithBoolValue(false)->retain();; + return true; + } + + return false; +} + +bool JSONParser::parseNull() +{ + if (scanKeyword(MCSTR("null"), mPosition)) { + mPosition += MCSTR("null")->length(); + mResult = Null::null()->retain(); + return true; + } + + return false; +} + +bool JSONParser::parseFloat() +{ + const char * str; + char * endptr; + double value; + char * endptrInt; + long long valueInt; + + AutoreleasePool * pool; + + pool = new AutoreleasePool(); + if (mContent->length() > mPosition + 50) { + str = mContent->substringWithRange(RangeMake(mPosition, 50))->UTF8Characters(); + } + else { + str = mContent->substringFromIndex(mPosition)->UTF8Characters(); + } + value = strtod(str, &endptr); + if (endptr == str) { + pool->release(); + return false; + } + valueInt = strtoll(str, &endptrInt, 0); + if (endptr == endptrInt) { + mPosition += endptrInt - str; + mResult = Value::valueWithLongLongValue(valueInt)->retain(); + } + else { + mPosition += endptr - str; + mResult = Value::valueWithDoubleValue(value); + } + pool->release(); + + return true; +} + +Object * JSONParser::objectFromData(Data * data) +{ + String * str = NULL; + Object * result; + + str = String::stringWithData(data, "utf-8"); + if (str == NULL) + return NULL; + + result = objectFromString(str); + + return result; +} + +Object * JSONParser::objectFromString(String * str) +{ + Object * result; + JSONParser * parser; + + parser = new JSONParser(); + parser->setContent(str); + parser->parse(); + result = parser->result(); + result->retain()->autorelease(); + parser->release(); + + return result; +} + +Data * JSONParser::dataFromObject(Object * object) +{ + return stringFromObject(object)->dataUsingEncoding("utf-8"); +} + +String * JSONParser::stringFromObject(Object * object) +{ + String * result; + + result = String::string(); + appendStringFromObject(object, result); + + return result; +} + + +String * JSONParser::JSStringFromString(String * str) +{ + unsigned int i; + String * result; + + result = String::string(); + for(i = 0 ; i < str->length() ; i ++) { + UChar ch; + + ch = str->characterAtIndex(i); + if ((ch >= '0') && (ch <= '9')) { + UChar characters[2]; + characters[0] = ch; + characters[1] = 0; + result->appendCharactersLength(characters, 1); + } + else if ((ch >= 'a') && (ch <= 'z')) { + UChar characters[2]; + characters[0] = ch; + characters[1] = 0; + result->appendCharactersLength(characters, 1); + } + else if ((ch >= 'A') && (ch <= 'Z')) { + UChar characters[2]; + characters[0] = ch; + characters[1] = 0; + result->appendCharactersLength(characters, 1); + } + else { + switch (ch) { + case ' ': + case '.': + case ',': + case '<': + case '>': + case '(': + case ')': + case '!': + case '@': + case '#': + case '$': + case '%': + case '^': + case '&': + case '*': + case '-': + case '_': + case '+': + case '=': + case '?': + case '{': + case '}': + case '[': + case ']': + case ':': + case ';': + case '|': + case '~': + case '\'': { + UChar characters[2]; + characters[0] = ch; + characters[1] = 0; + result->appendCharactersLength(characters, 1); + break; + } + case '"': + case '/': + case '\\': { + UChar characters[3]; + characters[0] = '\\'; + characters[1] = ch; + characters[2] = 0; + result->appendCharactersLength(characters, 2); + break; + } + default: { + result->appendUTF8Format("\\u%04x", (unsigned int) ch); + break; + } + } + } + } + + return result; +} + +void JSONParser::appendStringFromObject(Object * object, String * string) +{ + if (object->className()->isEqual(MCSTR("mailcore::String"))) { + string->appendString(MCSTR("\"")); + string->appendString(JSStringFromString((String *) object)); + string->appendString(MCSTR("\"")); + } + else if (object->className()->isEqual(MCSTR("mailcore::Value"))) { + Value * value = (Value *) object; + switch (value->type()) { + case ValueTypeBool: + string->appendString(value->boolValue() ? MCSTR("true") : MCSTR("false")); + break; + case ValueTypeChar: + string->appendUTF8Format("%i", (int) value->charValue()); + break; + case ValueTypeUnsignedChar: + string->appendUTF8Format("%i", (int) value->unsignedCharValue()); + break; + case ValueTypeShort: + string->appendUTF8Format("%i", (int) value->shortValue()); + break; + case ValueTypeUnsignedShort: + string->appendUTF8Format("%i", (int) value->unsignedShortValue()); + break; + case ValueTypeInt: + string->appendUTF8Format("%i", (int) value->intValue()); + break; + case ValueTypeUnsignedInt: + string->appendUTF8Format("%u", (int) value->unsignedIntValue()); + break; + case ValueTypeLong: + string->appendUTF8Format("%ld", value->longValue()); + break; + case ValueTypeUnsignedLong: + string->appendUTF8Format("%lu", value->unsignedLongValue()); + break; + case ValueTypeLongLong: + string->appendUTF8Format("%lld", value->longLongValue()); + break; + case ValueTypeUnsignedLongLong: + string->appendUTF8Format("%llu", value->unsignedLongLongValue()); + break; + case ValueTypeFloat: + string->appendUTF8Format("%g", value->floatValue()); + break; + case ValueTypeDouble: + string->appendUTF8Format("%lg", value->doubleValue()); + break; + default: + MCAssert(0); + break; + } + } + else if (object->className()->isEqual(MCSTR("mailcore::Null"))) { + string->appendString(MCSTR("null")); + } + else if (object->className()->isEqual(MCSTR("mailcore::Array"))) { + Array * array; + bool first; + + first = true; + array = (Array *) object; + string->appendString(MCSTR("[")); + for(unsigned int i = 0 ; i < array->count() ; i ++) { + Object * arrayElement = array->objectAtIndex(i); + if (first) { + first = false; + } + else { + string->appendString(MCSTR(",")); + } + appendStringFromObject(arrayElement, string); + } + string->appendString(MCSTR("]")); + } + else if (object->className()->isEqual(MCSTR("mailcore::HashMap"))) { + HashMap * dict; + bool first; + + first = true; + dict = (HashMap *) object; + string->appendString(MCSTR("{")); + Array * keys = dict->allKeys(); + for(unsigned int i = 0 ; i < keys->count() ; i ++) { + String * key = (String *) keys->objectAtIndex(i); + + if (first) { + first = false; + } + else { + string->appendString(MCSTR(",")); + } + appendStringFromObject(key, string); + string->appendString(MCSTR(":")); + appendStringFromObject(dict->objectForKey(key), string); + } + string->appendString(MCSTR("}")); + } +} diff --git a/src/core/basetypes/MCLibetpan.cc b/src/core/basetypes/MCLibetpan.cc deleted file mode 100644 index 51a27430..00000000 --- a/src/core/basetypes/MCLibetpan.cc +++ /dev/null @@ -1,223 +0,0 @@ -// -// MCLibetpan.cpp -// mailcore2 -// -// Created by Hoa Dinh on 6/28/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCWin32.h" // should be included first. - -#include "MCLibetpan.h" - -#include - -#include "MCDefines.h" - -using namespace mailcore; - -static time_t mkgmtime(struct tm * tmp); -static int tmcomp(struct tm * atmp, struct tm * btmp); - -INITIALIZE(Libetpan) -{ - // It will enable CFStream on platforms that supports it. - mailstream_cfstream_enabled = 1; -} - -time_t mailcore::timestampFromDate(struct mailimf_date_time * date_time) -{ - struct tm tmval; - time_t timeval; - int zone_min; - int zone_hour; - - tmval.tm_sec = date_time->dt_sec; - tmval.tm_min = date_time->dt_min; - tmval.tm_hour = date_time->dt_hour; - tmval.tm_mday = date_time->dt_day; - tmval.tm_mon = date_time->dt_month - 1; - if (date_time->dt_year < 1000) { - // workaround when century is not given in year - tmval.tm_year = date_time->dt_year + 2000 - 1900; - } - else { - tmval.tm_year = date_time->dt_year - 1900; - } - - timeval = mkgmtime(&tmval); - - if (date_time->dt_zone >= 0) { - zone_hour = date_time->dt_zone / 100; - zone_min = date_time->dt_zone % 100; - } - else { - zone_hour = -((- date_time->dt_zone) / 100); - zone_min = -((- date_time->dt_zone) % 100); - } - timeval -= zone_hour * 3600 + zone_min * 60; - - return timeval; -} - -struct mailimf_date_time * mailcore::dateFromTimestamp(time_t timeval) -{ - struct tm gmt; - struct tm lt; - int off; - struct mailimf_date_time * date_time; - int sign; - int hour; - int min; - - gmtime_r(&timeval, &gmt); - localtime_r(&timeval, <); - - off = (int) ((mkgmtime(<) - mkgmtime(&gmt)) / 60); - if (off < 0) { - sign = -1; - } - else { - sign = 1; - } - off = off * sign; - min = off % 60; - hour = off / 60; - off = hour * 100 + min; - off = off * sign; - - date_time = mailimf_date_time_new(lt.tm_mday, lt.tm_mon + 1, - lt.tm_year + 1900, - lt.tm_hour, lt.tm_min, lt.tm_sec, - off); - - return date_time; -} - -struct mailimap_date_time * mailcore::imapDateFromTimestamp(time_t timeval) -{ - struct tm gmt; - struct tm lt; - int off; - struct mailimap_date_time * date_time; - int sign; - int hour; - int min; - - gmtime_r(&timeval, &gmt); - localtime_r(&timeval, <); - - off = (int) ((mkgmtime(<) - mkgmtime(&gmt)) / 60); - if (off < 0) { - sign = -1; - } - else { - sign = 1; - } - off = off * sign; - min = off % 60; - hour = off / 60; - off = hour * 100 + min; - off = off * sign; - - date_time = mailimap_date_time_new(lt.tm_mday, lt.tm_mon + 1, - lt.tm_year + 1900, - lt.tm_hour, lt.tm_min, lt.tm_sec, - off); - - return date_time; -} - -time_t mailcore::timestampFromIMAPDate(struct mailimap_date_time * date_time) -{ - struct tm tmval; - time_t timeval; - int zone_min; - int zone_hour; - - tmval.tm_sec = date_time->dt_sec; - tmval.tm_min = date_time->dt_min; - tmval.tm_hour = date_time->dt_hour; - tmval.tm_mday = date_time->dt_day; - tmval.tm_mon = date_time->dt_month - 1; - if (date_time->dt_year < 1000) { - // workaround when century is not given in year - tmval.tm_year = date_time->dt_year + 2000 - 1900; - } - else { - tmval.tm_year = date_time->dt_year - 1900; - } - - timeval = mkgmtime(&tmval); - - if (date_time->dt_zone >= 0) { - zone_hour = date_time->dt_zone / 100; - zone_min = date_time->dt_zone % 100; - } - else { - zone_hour = -((- date_time->dt_zone) / 100); - zone_min = -((- date_time->dt_zone) % 100); - } - timeval -= zone_hour * 3600 + zone_min * 60; - - return timeval; -} - -#define INVALID_TIMESTAMP (-1) - -static int tmcomp(struct tm * atmp, struct tm * btmp) -{ - int result; - - if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && - (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && - (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && - (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && - (result = (atmp->tm_min - btmp->tm_min)) == 0) - result = atmp->tm_sec - btmp->tm_sec; - return result; -} - -static time_t mkgmtime(struct tm * tmp) -{ - int dir; - int bits; - int saved_seconds; - time_t t; - struct tm yourtm, mytm; - - yourtm = *tmp; - saved_seconds = yourtm.tm_sec; - yourtm.tm_sec = 0; - /* - ** Calculate the number of magnitude bits in a time_t - ** (this works regardless of whether time_t is - ** signed or unsigned, though lint complains if unsigned). - */ - for (bits = 0, t = 1; t > 0; ++bits, t <<= 1) - ; - /* - ** If time_t is signed, then 0 is the median value, - ** if time_t is unsigned, then 1 << bits is median. - */ - if(bits > 40) bits = 40; - t = (t < 0) ? 0 : ((time_t) 1 << bits); - for ( ; ; ) { - gmtime_r(&t, &mytm); - dir = tmcomp(&mytm, &yourtm); - if (dir != 0) { - if (bits-- < 0) { - return INVALID_TIMESTAMP; - } - if (bits < 0) - --t; - else if (dir > 0) - t -= (time_t) 1 << bits; - else t += (time_t) 1 << bits; - continue; - } - break; - } - t += saved_seconds; - return t; -} diff --git a/src/core/basetypes/MCLibetpan.cpp b/src/core/basetypes/MCLibetpan.cpp new file mode 100644 index 00000000..51a27430 --- /dev/null +++ b/src/core/basetypes/MCLibetpan.cpp @@ -0,0 +1,223 @@ +// +// MCLibetpan.cpp +// mailcore2 +// +// Created by Hoa Dinh on 6/28/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCWin32.h" // should be included first. + +#include "MCLibetpan.h" + +#include + +#include "MCDefines.h" + +using namespace mailcore; + +static time_t mkgmtime(struct tm * tmp); +static int tmcomp(struct tm * atmp, struct tm * btmp); + +INITIALIZE(Libetpan) +{ + // It will enable CFStream on platforms that supports it. + mailstream_cfstream_enabled = 1; +} + +time_t mailcore::timestampFromDate(struct mailimf_date_time * date_time) +{ + struct tm tmval; + time_t timeval; + int zone_min; + int zone_hour; + + tmval.tm_sec = date_time->dt_sec; + tmval.tm_min = date_time->dt_min; + tmval.tm_hour = date_time->dt_hour; + tmval.tm_mday = date_time->dt_day; + tmval.tm_mon = date_time->dt_month - 1; + if (date_time->dt_year < 1000) { + // workaround when century is not given in year + tmval.tm_year = date_time->dt_year + 2000 - 1900; + } + else { + tmval.tm_year = date_time->dt_year - 1900; + } + + timeval = mkgmtime(&tmval); + + if (date_time->dt_zone >= 0) { + zone_hour = date_time->dt_zone / 100; + zone_min = date_time->dt_zone % 100; + } + else { + zone_hour = -((- date_time->dt_zone) / 100); + zone_min = -((- date_time->dt_zone) % 100); + } + timeval -= zone_hour * 3600 + zone_min * 60; + + return timeval; +} + +struct mailimf_date_time * mailcore::dateFromTimestamp(time_t timeval) +{ + struct tm gmt; + struct tm lt; + int off; + struct mailimf_date_time * date_time; + int sign; + int hour; + int min; + + gmtime_r(&timeval, &gmt); + localtime_r(&timeval, <); + + off = (int) ((mkgmtime(<) - mkgmtime(&gmt)) / 60); + if (off < 0) { + sign = -1; + } + else { + sign = 1; + } + off = off * sign; + min = off % 60; + hour = off / 60; + off = hour * 100 + min; + off = off * sign; + + date_time = mailimf_date_time_new(lt.tm_mday, lt.tm_mon + 1, + lt.tm_year + 1900, + lt.tm_hour, lt.tm_min, lt.tm_sec, + off); + + return date_time; +} + +struct mailimap_date_time * mailcore::imapDateFromTimestamp(time_t timeval) +{ + struct tm gmt; + struct tm lt; + int off; + struct mailimap_date_time * date_time; + int sign; + int hour; + int min; + + gmtime_r(&timeval, &gmt); + localtime_r(&timeval, <); + + off = (int) ((mkgmtime(<) - mkgmtime(&gmt)) / 60); + if (off < 0) { + sign = -1; + } + else { + sign = 1; + } + off = off * sign; + min = off % 60; + hour = off / 60; + off = hour * 100 + min; + off = off * sign; + + date_time = mailimap_date_time_new(lt.tm_mday, lt.tm_mon + 1, + lt.tm_year + 1900, + lt.tm_hour, lt.tm_min, lt.tm_sec, + off); + + return date_time; +} + +time_t mailcore::timestampFromIMAPDate(struct mailimap_date_time * date_time) +{ + struct tm tmval; + time_t timeval; + int zone_min; + int zone_hour; + + tmval.tm_sec = date_time->dt_sec; + tmval.tm_min = date_time->dt_min; + tmval.tm_hour = date_time->dt_hour; + tmval.tm_mday = date_time->dt_day; + tmval.tm_mon = date_time->dt_month - 1; + if (date_time->dt_year < 1000) { + // workaround when century is not given in year + tmval.tm_year = date_time->dt_year + 2000 - 1900; + } + else { + tmval.tm_year = date_time->dt_year - 1900; + } + + timeval = mkgmtime(&tmval); + + if (date_time->dt_zone >= 0) { + zone_hour = date_time->dt_zone / 100; + zone_min = date_time->dt_zone % 100; + } + else { + zone_hour = -((- date_time->dt_zone) / 100); + zone_min = -((- date_time->dt_zone) % 100); + } + timeval -= zone_hour * 3600 + zone_min * 60; + + return timeval; +} + +#define INVALID_TIMESTAMP (-1) + +static int tmcomp(struct tm * atmp, struct tm * btmp) +{ + int result; + + if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && + (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && + (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && + (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && + (result = (atmp->tm_min - btmp->tm_min)) == 0) + result = atmp->tm_sec - btmp->tm_sec; + return result; +} + +static time_t mkgmtime(struct tm * tmp) +{ + int dir; + int bits; + int saved_seconds; + time_t t; + struct tm yourtm, mytm; + + yourtm = *tmp; + saved_seconds = yourtm.tm_sec; + yourtm.tm_sec = 0; + /* + ** Calculate the number of magnitude bits in a time_t + ** (this works regardless of whether time_t is + ** signed or unsigned, though lint complains if unsigned). + */ + for (bits = 0, t = 1; t > 0; ++bits, t <<= 1) + ; + /* + ** If time_t is signed, then 0 is the median value, + ** if time_t is unsigned, then 1 << bits is median. + */ + if(bits > 40) bits = 40; + t = (t < 0) ? 0 : ((time_t) 1 << bits); + for ( ; ; ) { + gmtime_r(&t, &mytm); + dir = tmcomp(&mytm, &yourtm); + if (dir != 0) { + if (bits-- < 0) { + return INVALID_TIMESTAMP; + } + if (bits < 0) + --t; + else if (dir > 0) + t -= (time_t) 1 << bits; + else t += (time_t) 1 << bits; + continue; + } + break; + } + t += saved_seconds; + return t; +} diff --git a/src/core/basetypes/MCMD5.cc b/src/core/basetypes/MCMD5.cc deleted file mode 100644 index f4fc70f3..00000000 --- a/src/core/basetypes/MCMD5.cc +++ /dev/null @@ -1,233 +0,0 @@ -// -// MCMD5.cpp -// hermes -// -// Created by DINH Viêt Hoà on 4/11/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCMD5.h" - -#include -#include - -using namespace mailcore; - -static int is_big_endian(void) { - static const int n = 1; - return ((char *) &n)[0] == 0; -} - -typedef struct MD5Context { - uint32_t buf[4]; - uint32_t bits[2]; - unsigned char in[64]; -} MD5_CTX; - -static void byteReverse(unsigned char *buf, unsigned longs) { - uint32_t t; - - // Forrest: MD5 expect LITTLE_ENDIAN, swap if BIG_ENDIAN - if (is_big_endian()) { - do { - t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 | - ((unsigned) buf[1] << 8 | buf[0]); - * (uint32_t *) buf = t; - buf += 4; - } while (--longs); - } -} - -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -#define MD5STEP(f, w, x, y, z, data, s) \ -( w += f(x, y, z) + data, w = w<>(32-s), w += x ) - -static void MD5Transform(uint32_t buf[4], uint32_t const in[16]) { - uint32_t a, b, c, d; - - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - - MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); - MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); - MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); - MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); - MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); - MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); - MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); - MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); - MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); - MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); - MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); - MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); - MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); - MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); - MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} - -// Start MD5 accumulation. Set bit count to 0 and buffer to mysterious -// initialization constants. -static void MD5Init(MD5_CTX *ctx) { - ctx->buf[0] = 0x67452301; - ctx->buf[1] = 0xefcdab89; - ctx->buf[2] = 0x98badcfe; - ctx->buf[3] = 0x10325476; - - ctx->bits[0] = 0; - ctx->bits[1] = 0; -} - -static void MD5Update(MD5_CTX *ctx, unsigned char const *buf, unsigned len) { - uint32_t t; - - t = ctx->bits[0]; - if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t) - ctx->bits[1]++; - ctx->bits[1] += len >> 29; - - t = (t >> 3) & 0x3f; - - if (t) { - unsigned char *p = (unsigned char *) ctx->in + t; - - t = 64 - t; - if (len < t) { - memcpy(p, buf, len); - return; - } - memcpy(p, buf, t); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32_t *) ctx->in); - buf += t; - len -= t; - } - - while (len >= 64) { - memcpy(ctx->in, buf, 64); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32_t *) ctx->in); - buf += 64; - len -= 64; - } - - memcpy(ctx->in, buf, len); -} - -static void MD5Final(unsigned char digest[16], MD5_CTX *ctx) { - unsigned count; - unsigned char *p; - uint32_t *a; - - count = (ctx->bits[0] >> 3) & 0x3F; - - p = ctx->in + count; - *p++ = 0x80; - count = 64 - 1 - count; - if (count < 8) { - memset(p, 0, count); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32_t *) ctx->in); - memset(ctx->in, 0, 56); - } else { - memset(p, 0, count - 8); - } - byteReverse(ctx->in, 14); - - a = (uint32_t *)ctx->in; - a[14] = ctx->bits[0]; - a[15] = ctx->bits[1]; - - MD5Transform(ctx->buf, (uint32_t *) ctx->in); - byteReverse((unsigned char *) ctx->buf, 4); - memcpy(digest, ctx->buf, 16); - memset((char *) ctx, 0, sizeof(*ctx)); -} - -Data * mailcore::md5Data(Data * data) -{ - MD5Context ctx; - unsigned char digest[16]; - Data * result = Data::dataWithCapacity(sizeof(digest)); - - MD5Init(&ctx); - MD5Update(&ctx, (unsigned char const *) data->bytes(), data->length()); - MD5Final(digest, &ctx); - - result->appendBytes((const char *) digest, sizeof(digest)); - - return result; -} - -String * mailcore::md5String(Data * data) -{ - Data * md5data = md5Data(data); - String * result = String::string(); - for(unsigned int i = 0 ; i < md5data->length() ; i ++) { - result->appendUTF8Format("%02x", (unsigned char) md5data->bytes()[i]); - } - return result; -} - diff --git a/src/core/basetypes/MCMD5.cpp b/src/core/basetypes/MCMD5.cpp new file mode 100644 index 00000000..f4fc70f3 --- /dev/null +++ b/src/core/basetypes/MCMD5.cpp @@ -0,0 +1,233 @@ +// +// MCMD5.cpp +// hermes +// +// Created by DINH Viêt Hoà on 4/11/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCMD5.h" + +#include +#include + +using namespace mailcore; + +static int is_big_endian(void) { + static const int n = 1; + return ((char *) &n)[0] == 0; +} + +typedef struct MD5Context { + uint32_t buf[4]; + uint32_t bits[2]; + unsigned char in[64]; +} MD5_CTX; + +static void byteReverse(unsigned char *buf, unsigned longs) { + uint32_t t; + + // Forrest: MD5 expect LITTLE_ENDIAN, swap if BIG_ENDIAN + if (is_big_endian()) { + do { + t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + * (uint32_t *) buf = t; + buf += 4; + } while (--longs); + } +} + +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +#define MD5STEP(f, w, x, y, z, data, s) \ +( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + +static void MD5Transform(uint32_t buf[4], uint32_t const in[16]) { + uint32_t a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +// Start MD5 accumulation. Set bit count to 0 and buffer to mysterious +// initialization constants. +static void MD5Init(MD5_CTX *ctx) { + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +static void MD5Update(MD5_CTX *ctx, unsigned char const *buf, unsigned len) { + uint32_t t; + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t) + ctx->bits[1]++; + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32_t *) ctx->in); + buf += t; + len -= t; + } + + while (len >= 64) { + memcpy(ctx->in, buf, 64); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32_t *) ctx->in); + buf += 64; + len -= 64; + } + + memcpy(ctx->in, buf, len); +} + +static void MD5Final(unsigned char digest[16], MD5_CTX *ctx) { + unsigned count; + unsigned char *p; + uint32_t *a; + + count = (ctx->bits[0] >> 3) & 0x3F; + + p = ctx->in + count; + *p++ = 0x80; + count = 64 - 1 - count; + if (count < 8) { + memset(p, 0, count); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32_t *) ctx->in); + memset(ctx->in, 0, 56); + } else { + memset(p, 0, count - 8); + } + byteReverse(ctx->in, 14); + + a = (uint32_t *)ctx->in; + a[14] = ctx->bits[0]; + a[15] = ctx->bits[1]; + + MD5Transform(ctx->buf, (uint32_t *) ctx->in); + byteReverse((unsigned char *) ctx->buf, 4); + memcpy(digest, ctx->buf, 16); + memset((char *) ctx, 0, sizeof(*ctx)); +} + +Data * mailcore::md5Data(Data * data) +{ + MD5Context ctx; + unsigned char digest[16]; + Data * result = Data::dataWithCapacity(sizeof(digest)); + + MD5Init(&ctx); + MD5Update(&ctx, (unsigned char const *) data->bytes(), data->length()); + MD5Final(digest, &ctx); + + result->appendBytes((const char *) digest, sizeof(digest)); + + return result; +} + +String * mailcore::md5String(Data * data) +{ + Data * md5data = md5Data(data); + String * result = String::string(); + for(unsigned int i = 0 ; i < md5data->length() ; i ++) { + result->appendUTF8Format("%02x", (unsigned char) md5data->bytes()[i]); + } + return result; +} + diff --git a/src/core/basetypes/MCNull.cc b/src/core/basetypes/MCNull.cc deleted file mode 100644 index cdb8335f..00000000 --- a/src/core/basetypes/MCNull.cc +++ /dev/null @@ -1,19 +0,0 @@ -// -// MCNull.cpp -// hermes -// -// Created by DINH Viêt Hoà on 4/9/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCNull.h" - -using namespace mailcore; - -Null * Null::null() -{ - Null * result = new Null(); - result->autorelease(); - return result; -} - diff --git a/src/core/basetypes/MCNull.cpp b/src/core/basetypes/MCNull.cpp new file mode 100644 index 00000000..cdb8335f --- /dev/null +++ b/src/core/basetypes/MCNull.cpp @@ -0,0 +1,19 @@ +// +// MCNull.cpp +// hermes +// +// Created by DINH Viêt Hoà on 4/9/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCNull.h" + +using namespace mailcore; + +Null * Null::null() +{ + Null * result = new Null(); + result->autorelease(); + return result; +} + diff --git a/src/core/basetypes/MCObject.cc b/src/core/basetypes/MCObject.cc deleted file mode 100644 index 7c1d83bb..00000000 --- a/src/core/basetypes/MCObject.cc +++ /dev/null @@ -1,449 +0,0 @@ -#include "MCObject.h" - -#include -#include -#ifndef _MSC_VER -#include -#endif -#include -#include -#if __APPLE__ -#include -#endif - -#include "MCAutoreleasePool.h" -#include "MCString.h" -#include "MCHash.h" -#include "MCLog.h" -#include "MCUtils.h" -#include "MCAssert.h" -#include "MCMainThread.h" -#include "MCLog.h" -#include "MCHashMap.h" - -using namespace mailcore; - -bool mailcore::zombieEnabled = 0; - -Object::Object() -{ - init(); -} - -Object::~Object() -{ -} - -void Object::init() -{ - pthread_mutex_init(&mLock, NULL); - mCounter = 1; -} - -int Object::retainCount() -{ - pthread_mutex_lock(&mLock); - int value = mCounter; - pthread_mutex_unlock(&mLock); - - return value; -} - -Object * Object::retain() -{ - pthread_mutex_lock(&mLock); - mCounter ++; - pthread_mutex_unlock(&mLock); - return this; -} - -void Object::release() -{ - bool shouldRelease = false; - - pthread_mutex_lock(&mLock); - mCounter --; - if (mCounter == 0) { - shouldRelease = true; - } - if (mCounter < 0) { - MCLog("release too much %p %s", this, MCUTF8(className())); - MCAssert(0); - } - pthread_mutex_unlock(&mLock); - - if (shouldRelease && !zombieEnabled) { - //int status; - //char * unmangled = abi::__cxa_demangle(typeid(* this).name(), NULL, NULL, &status); - //MCLog("dealloc %p %s", this, unmangled); - delete this; - } -} - -#ifndef __APPLE__ -Object * Object::autorelease() -{ - AutoreleasePool::autorelease(this); - return this; -} -#endif - -String * Object::className() -{ - int status; -#ifdef _MSC_VER - String * result = String::uniquedStringWithUTF8Characters(typeid(*this).name()); -#else - char * unmangled = abi::__cxa_demangle(typeid(* this).name(), NULL, NULL, &status); - String * result = String::uniquedStringWithUTF8Characters(unmangled); - free(unmangled); -#endif - return result; -} - -String * Object::description() -{ - return String::stringWithUTF8Format("<%s:%p>", className()->UTF8Characters(), this); -} - -bool Object::isEqual(Object * otherObject) -{ - return this == otherObject; -} - -unsigned int Object::hash() -{ - return hashCompute((const char *) this, sizeof(this)); -} - -Object * Object::copy() -{ - MCAssert(0); - return NULL; -} - -void Object::performMethod(Object::Method method, void * context) -{ - (this->*method)(context); -} - -struct mainThreadCallData { - Object * obj; - void * context; - Object::Method method; - void * caller; -}; - -static pthread_once_t delayedPerformOnce = PTHREAD_ONCE_INIT; -static chash * delayedPerformHash = NULL; -static pthread_mutex_t delayedPerformLock = PTHREAD_MUTEX_INITIALIZER; - -static void reallyInitDelayedPerform() -{ - delayedPerformHash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); -} - -static void initDelayedPerform() -{ - pthread_once(&delayedPerformOnce, reallyInitDelayedPerform); -} - -struct mainThreadCallKeyData { - Object * dispatchQueueIdentifier; - Object * obj; - void * context; - Object::Method method; -}; - -static void removeFromPerformHash(Object * obj, Object::Method method, void * context, void * targetDispatchQueue) -{ - chashdatum key; - struct mainThreadCallKeyData keyData; - Object * queueIdentifier = NULL; -#if __APPLE__ - queueIdentifier = (String *) dispatch_queue_get_specific((dispatch_queue_t) targetDispatchQueue, "MCDispatchQueueID"); -#endif - memset(&keyData, 0, sizeof(keyData)); - keyData.dispatchQueueIdentifier = queueIdentifier; - keyData.obj = obj; - keyData.context = context; - keyData.method = method; - key.data = &keyData; - key.len = sizeof(keyData); - - pthread_mutex_lock(&delayedPerformLock); - chash_delete(delayedPerformHash, (chashdatum *) &key, NULL); - pthread_mutex_unlock(&delayedPerformLock); -} - -static void queueIdentifierDestructor(void * identifier) -{ - Object * obj = (Object *) identifier; - MC_SAFE_RELEASE(obj); -} - -static void addToPerformHash(Object * obj, Object::Method method, void * context, void * targetDispatchQueue, - void * performValue) -{ - chashdatum key; - chashdatum value; - struct mainThreadCallKeyData keyData; - Object * queueIdentifier = NULL; -#if __APPLE__ - queueIdentifier = (String *) dispatch_queue_get_specific((dispatch_queue_t) targetDispatchQueue, "MCDispatchQueueID"); - if (queueIdentifier == NULL) { - queueIdentifier = new Object(); - dispatch_queue_set_specific((dispatch_queue_t) targetDispatchQueue, "MCDispatchQueueID", queueIdentifier, queueIdentifierDestructor); - } -#endif - memset(&keyData, 0, sizeof(keyData)); - keyData.dispatchQueueIdentifier = queueIdentifier; - keyData.obj = obj; - keyData.context = context; - keyData.method = method; - key.data = &keyData; - key.len = sizeof(keyData); - value.data = performValue; - value.len = 0; - pthread_mutex_lock(&delayedPerformLock); - chash_set(delayedPerformHash, &key, &value, NULL); - pthread_mutex_unlock(&delayedPerformLock); -} - -static void * getFromPerformHash(Object * obj, Object::Method method, void * context, void * targetDispatchQueue) -{ - chashdatum key; - chashdatum value; - struct mainThreadCallKeyData keyData; - int r; - - Object * queueIdentifier = NULL; -#if __APPLE__ - MCAssert(targetDispatchQueue != NULL); - queueIdentifier = (String *) dispatch_queue_get_specific((dispatch_queue_t) targetDispatchQueue, "MCDispatchQueueID"); - if (queueIdentifier == NULL) - return NULL; -#endif - memset(&keyData, 0, sizeof(keyData)); - keyData.dispatchQueueIdentifier = queueIdentifier; - keyData.obj = obj; - keyData.context = context; - keyData.method = method; - key.data = &keyData; - key.len = sizeof(keyData); - - pthread_mutex_lock(&delayedPerformLock); - r = chash_get(delayedPerformHash, &key, &value); - pthread_mutex_unlock(&delayedPerformLock); - if (r < 0) - return NULL; - - return value.data; -} - -static void performOnMainThread(void * info) -{ - struct mainThreadCallData * data; - void * context; - Object * obj; - Object::Method method; - - data = (struct mainThreadCallData *) info; - obj = data->obj; - context = data->context; - method = data->method; - - (obj->*method)(context); - - free(data); -} - -static void performAfterDelay(void * info) -{ - struct mainThreadCallData * data; - void * context; - Object * obj; - Object::Method method; - - data = (struct mainThreadCallData *) info; - obj = data->obj; - context = data->context; - method = data->method; - - removeFromPerformHash(obj, method, context, NULL); - (obj->*method)(context); - - free(data); -} - -void Object::performMethodOnMainThread(Method method, void * context, bool waitUntilDone) -{ - struct mainThreadCallData * data; - - data = (struct mainThreadCallData *) calloc(sizeof(* data), 1); - data->obj = this; - data->context = context; - data->method = method; - data->caller = NULL; - - if (waitUntilDone) { - callOnMainThreadAndWait(performOnMainThread, data); - } - else { - callOnMainThread(performOnMainThread, data); - } -} - -#if __APPLE__ -void Object::performMethodOnDispatchQueue(Method method, void * context, void * targetDispatchQueue, bool waitUntilDone) -{ - if (waitUntilDone) { - dispatch_sync((dispatch_queue_t) targetDispatchQueue, ^{ - (this->*method)(context); - }); - } - else { - dispatch_async((dispatch_queue_t) targetDispatchQueue, ^{ - (this->*method)(context); - }); - } -} - -struct cancellableBlock { - void (^block)(void); - bool cancelled; -}; - -void Object::performMethodOnDispatchQueueAfterDelay(Method method, void * context, void * targetDispatchQueue, double delay) -{ - initDelayedPerform(); - - __block bool cancelled = false; - - void (^cancelableBlock)(bool cancel) = ^(bool cancel) { - if (cancel) { - cancelled = true; - return; - } - if (!cancelled) { - (this->*method)(context); - } - }; - - void (^dupCancelableBlock)(bool cancel) = Block_copy(cancelableBlock); - - retain(); - addToPerformHash(this, method, context, targetDispatchQueue, (void *) dupCancelableBlock); - dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)); - dispatch_after(popTime, (dispatch_queue_t) targetDispatchQueue, ^(void) { - if (!cancelled) { - removeFromPerformHash(this, method, context, targetDispatchQueue); - } - dupCancelableBlock(false); - Block_release(dupCancelableBlock); - release(); - }); -} - -void Object::cancelDelayedPerformMethodOnDispatchQueue(Method method, void * context, void * targetDispatchQueue) -{ - initDelayedPerform(); - void (^dupCancelableBlock)(bool cancel) = (void (^)(bool)) getFromPerformHash(this, method, context, targetDispatchQueue); - if (dupCancelableBlock == NULL) { - return; - } - removeFromPerformHash(this, method, context, targetDispatchQueue); - dupCancelableBlock(true); -} -#endif - -void Object::performMethodAfterDelay(Method method, void * context, double delay) -{ -#if __APPLE__ - performMethodOnDispatchQueueAfterDelay(method, context, dispatch_get_main_queue(), delay); -#else - initDelayedPerform(); - - struct mainThreadCallData * data; - - data = (struct mainThreadCallData *) calloc(sizeof(* data), 1); - data->obj = this; - data->context = context; - data->method = method; - data->caller = callAfterDelay(performAfterDelay, data, delay); - addToPerformHash(this, method, context, NULL, data); -#endif -} - -void Object::cancelDelayedPerformMethod(Method method, void * context) -{ -#if __APPLE__ - cancelDelayedPerformMethodOnDispatchQueue(method, context, dispatch_get_main_queue()); -#else - initDelayedPerform(); - - struct mainThreadCallData * data = (struct mainThreadCallData *) getFromPerformHash(this, method, context, NULL); - if (data == NULL) - return; - - removeFromPerformHash(this, method, context, NULL); - cancelDelayedCall(data->caller); - free(data); -#endif -} - -HashMap * Object::serializable() -{ - HashMap * result = HashMap::hashMap(); - result->setObjectForKey(MCSTR("class"), className()); - return result; -} - -void Object::importSerializable(HashMap * serializable) -{ - MCAssert(0); -} - -static chash * constructors = NULL; - -void Object::initObjectConstructors() -{ - constructors = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); -} - -void Object::registerObjectConstructor(const char * className, void * (* objectConstructor)(void)) -{ - static pthread_once_t once = PTHREAD_ONCE_INIT; - pthread_once(&once, initObjectConstructors); - - chashdatum key; - chashdatum value; - key.data = (void *) className; - key.len = (unsigned int) strlen(className); - value.data = (void *) objectConstructor; - value.len = 0; - chash_set(constructors, &key, &value, NULL); -} - -Object * Object::objectWithSerializable(HashMap * serializable) -{ - if (serializable == NULL) - return NULL; - - void * (* objectConstructor)(void) = NULL; - - chashdatum key; - chashdatum value; - const char * className = ((String *) serializable->objectForKey(MCSTR("class")))->UTF8Characters(); - key.data = (void *) className; - key.len = (unsigned int) strlen(className); - int r = chash_get(constructors, &key, &value); - if (r < 0) - return NULL; - - objectConstructor = (void * (*)()) value.data; - Object * obj = (Object *) objectConstructor(); - obj->importSerializable(serializable); - return obj->autorelease(); -} - diff --git a/src/core/basetypes/MCObject.cpp b/src/core/basetypes/MCObject.cpp new file mode 100644 index 00000000..7c1d83bb --- /dev/null +++ b/src/core/basetypes/MCObject.cpp @@ -0,0 +1,449 @@ +#include "MCObject.h" + +#include +#include +#ifndef _MSC_VER +#include +#endif +#include +#include +#if __APPLE__ +#include +#endif + +#include "MCAutoreleasePool.h" +#include "MCString.h" +#include "MCHash.h" +#include "MCLog.h" +#include "MCUtils.h" +#include "MCAssert.h" +#include "MCMainThread.h" +#include "MCLog.h" +#include "MCHashMap.h" + +using namespace mailcore; + +bool mailcore::zombieEnabled = 0; + +Object::Object() +{ + init(); +} + +Object::~Object() +{ +} + +void Object::init() +{ + pthread_mutex_init(&mLock, NULL); + mCounter = 1; +} + +int Object::retainCount() +{ + pthread_mutex_lock(&mLock); + int value = mCounter; + pthread_mutex_unlock(&mLock); + + return value; +} + +Object * Object::retain() +{ + pthread_mutex_lock(&mLock); + mCounter ++; + pthread_mutex_unlock(&mLock); + return this; +} + +void Object::release() +{ + bool shouldRelease = false; + + pthread_mutex_lock(&mLock); + mCounter --; + if (mCounter == 0) { + shouldRelease = true; + } + if (mCounter < 0) { + MCLog("release too much %p %s", this, MCUTF8(className())); + MCAssert(0); + } + pthread_mutex_unlock(&mLock); + + if (shouldRelease && !zombieEnabled) { + //int status; + //char * unmangled = abi::__cxa_demangle(typeid(* this).name(), NULL, NULL, &status); + //MCLog("dealloc %p %s", this, unmangled); + delete this; + } +} + +#ifndef __APPLE__ +Object * Object::autorelease() +{ + AutoreleasePool::autorelease(this); + return this; +} +#endif + +String * Object::className() +{ + int status; +#ifdef _MSC_VER + String * result = String::uniquedStringWithUTF8Characters(typeid(*this).name()); +#else + char * unmangled = abi::__cxa_demangle(typeid(* this).name(), NULL, NULL, &status); + String * result = String::uniquedStringWithUTF8Characters(unmangled); + free(unmangled); +#endif + return result; +} + +String * Object::description() +{ + return String::stringWithUTF8Format("<%s:%p>", className()->UTF8Characters(), this); +} + +bool Object::isEqual(Object * otherObject) +{ + return this == otherObject; +} + +unsigned int Object::hash() +{ + return hashCompute((const char *) this, sizeof(this)); +} + +Object * Object::copy() +{ + MCAssert(0); + return NULL; +} + +void Object::performMethod(Object::Method method, void * context) +{ + (this->*method)(context); +} + +struct mainThreadCallData { + Object * obj; + void * context; + Object::Method method; + void * caller; +}; + +static pthread_once_t delayedPerformOnce = PTHREAD_ONCE_INIT; +static chash * delayedPerformHash = NULL; +static pthread_mutex_t delayedPerformLock = PTHREAD_MUTEX_INITIALIZER; + +static void reallyInitDelayedPerform() +{ + delayedPerformHash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); +} + +static void initDelayedPerform() +{ + pthread_once(&delayedPerformOnce, reallyInitDelayedPerform); +} + +struct mainThreadCallKeyData { + Object * dispatchQueueIdentifier; + Object * obj; + void * context; + Object::Method method; +}; + +static void removeFromPerformHash(Object * obj, Object::Method method, void * context, void * targetDispatchQueue) +{ + chashdatum key; + struct mainThreadCallKeyData keyData; + Object * queueIdentifier = NULL; +#if __APPLE__ + queueIdentifier = (String *) dispatch_queue_get_specific((dispatch_queue_t) targetDispatchQueue, "MCDispatchQueueID"); +#endif + memset(&keyData, 0, sizeof(keyData)); + keyData.dispatchQueueIdentifier = queueIdentifier; + keyData.obj = obj; + keyData.context = context; + keyData.method = method; + key.data = &keyData; + key.len = sizeof(keyData); + + pthread_mutex_lock(&delayedPerformLock); + chash_delete(delayedPerformHash, (chashdatum *) &key, NULL); + pthread_mutex_unlock(&delayedPerformLock); +} + +static void queueIdentifierDestructor(void * identifier) +{ + Object * obj = (Object *) identifier; + MC_SAFE_RELEASE(obj); +} + +static void addToPerformHash(Object * obj, Object::Method method, void * context, void * targetDispatchQueue, + void * performValue) +{ + chashdatum key; + chashdatum value; + struct mainThreadCallKeyData keyData; + Object * queueIdentifier = NULL; +#if __APPLE__ + queueIdentifier = (String *) dispatch_queue_get_specific((dispatch_queue_t) targetDispatchQueue, "MCDispatchQueueID"); + if (queueIdentifier == NULL) { + queueIdentifier = new Object(); + dispatch_queue_set_specific((dispatch_queue_t) targetDispatchQueue, "MCDispatchQueueID", queueIdentifier, queueIdentifierDestructor); + } +#endif + memset(&keyData, 0, sizeof(keyData)); + keyData.dispatchQueueIdentifier = queueIdentifier; + keyData.obj = obj; + keyData.context = context; + keyData.method = method; + key.data = &keyData; + key.len = sizeof(keyData); + value.data = performValue; + value.len = 0; + pthread_mutex_lock(&delayedPerformLock); + chash_set(delayedPerformHash, &key, &value, NULL); + pthread_mutex_unlock(&delayedPerformLock); +} + +static void * getFromPerformHash(Object * obj, Object::Method method, void * context, void * targetDispatchQueue) +{ + chashdatum key; + chashdatum value; + struct mainThreadCallKeyData keyData; + int r; + + Object * queueIdentifier = NULL; +#if __APPLE__ + MCAssert(targetDispatchQueue != NULL); + queueIdentifier = (String *) dispatch_queue_get_specific((dispatch_queue_t) targetDispatchQueue, "MCDispatchQueueID"); + if (queueIdentifier == NULL) + return NULL; +#endif + memset(&keyData, 0, sizeof(keyData)); + keyData.dispatchQueueIdentifier = queueIdentifier; + keyData.obj = obj; + keyData.context = context; + keyData.method = method; + key.data = &keyData; + key.len = sizeof(keyData); + + pthread_mutex_lock(&delayedPerformLock); + r = chash_get(delayedPerformHash, &key, &value); + pthread_mutex_unlock(&delayedPerformLock); + if (r < 0) + return NULL; + + return value.data; +} + +static void performOnMainThread(void * info) +{ + struct mainThreadCallData * data; + void * context; + Object * obj; + Object::Method method; + + data = (struct mainThreadCallData *) info; + obj = data->obj; + context = data->context; + method = data->method; + + (obj->*method)(context); + + free(data); +} + +static void performAfterDelay(void * info) +{ + struct mainThreadCallData * data; + void * context; + Object * obj; + Object::Method method; + + data = (struct mainThreadCallData *) info; + obj = data->obj; + context = data->context; + method = data->method; + + removeFromPerformHash(obj, method, context, NULL); + (obj->*method)(context); + + free(data); +} + +void Object::performMethodOnMainThread(Method method, void * context, bool waitUntilDone) +{ + struct mainThreadCallData * data; + + data = (struct mainThreadCallData *) calloc(sizeof(* data), 1); + data->obj = this; + data->context = context; + data->method = method; + data->caller = NULL; + + if (waitUntilDone) { + callOnMainThreadAndWait(performOnMainThread, data); + } + else { + callOnMainThread(performOnMainThread, data); + } +} + +#if __APPLE__ +void Object::performMethodOnDispatchQueue(Method method, void * context, void * targetDispatchQueue, bool waitUntilDone) +{ + if (waitUntilDone) { + dispatch_sync((dispatch_queue_t) targetDispatchQueue, ^{ + (this->*method)(context); + }); + } + else { + dispatch_async((dispatch_queue_t) targetDispatchQueue, ^{ + (this->*method)(context); + }); + } +} + +struct cancellableBlock { + void (^block)(void); + bool cancelled; +}; + +void Object::performMethodOnDispatchQueueAfterDelay(Method method, void * context, void * targetDispatchQueue, double delay) +{ + initDelayedPerform(); + + __block bool cancelled = false; + + void (^cancelableBlock)(bool cancel) = ^(bool cancel) { + if (cancel) { + cancelled = true; + return; + } + if (!cancelled) { + (this->*method)(context); + } + }; + + void (^dupCancelableBlock)(bool cancel) = Block_copy(cancelableBlock); + + retain(); + addToPerformHash(this, method, context, targetDispatchQueue, (void *) dupCancelableBlock); + dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)); + dispatch_after(popTime, (dispatch_queue_t) targetDispatchQueue, ^(void) { + if (!cancelled) { + removeFromPerformHash(this, method, context, targetDispatchQueue); + } + dupCancelableBlock(false); + Block_release(dupCancelableBlock); + release(); + }); +} + +void Object::cancelDelayedPerformMethodOnDispatchQueue(Method method, void * context, void * targetDispatchQueue) +{ + initDelayedPerform(); + void (^dupCancelableBlock)(bool cancel) = (void (^)(bool)) getFromPerformHash(this, method, context, targetDispatchQueue); + if (dupCancelableBlock == NULL) { + return; + } + removeFromPerformHash(this, method, context, targetDispatchQueue); + dupCancelableBlock(true); +} +#endif + +void Object::performMethodAfterDelay(Method method, void * context, double delay) +{ +#if __APPLE__ + performMethodOnDispatchQueueAfterDelay(method, context, dispatch_get_main_queue(), delay); +#else + initDelayedPerform(); + + struct mainThreadCallData * data; + + data = (struct mainThreadCallData *) calloc(sizeof(* data), 1); + data->obj = this; + data->context = context; + data->method = method; + data->caller = callAfterDelay(performAfterDelay, data, delay); + addToPerformHash(this, method, context, NULL, data); +#endif +} + +void Object::cancelDelayedPerformMethod(Method method, void * context) +{ +#if __APPLE__ + cancelDelayedPerformMethodOnDispatchQueue(method, context, dispatch_get_main_queue()); +#else + initDelayedPerform(); + + struct mainThreadCallData * data = (struct mainThreadCallData *) getFromPerformHash(this, method, context, NULL); + if (data == NULL) + return; + + removeFromPerformHash(this, method, context, NULL); + cancelDelayedCall(data->caller); + free(data); +#endif +} + +HashMap * Object::serializable() +{ + HashMap * result = HashMap::hashMap(); + result->setObjectForKey(MCSTR("class"), className()); + return result; +} + +void Object::importSerializable(HashMap * serializable) +{ + MCAssert(0); +} + +static chash * constructors = NULL; + +void Object::initObjectConstructors() +{ + constructors = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); +} + +void Object::registerObjectConstructor(const char * className, void * (* objectConstructor)(void)) +{ + static pthread_once_t once = PTHREAD_ONCE_INIT; + pthread_once(&once, initObjectConstructors); + + chashdatum key; + chashdatum value; + key.data = (void *) className; + key.len = (unsigned int) strlen(className); + value.data = (void *) objectConstructor; + value.len = 0; + chash_set(constructors, &key, &value, NULL); +} + +Object * Object::objectWithSerializable(HashMap * serializable) +{ + if (serializable == NULL) + return NULL; + + void * (* objectConstructor)(void) = NULL; + + chashdatum key; + chashdatum value; + const char * className = ((String *) serializable->objectForKey(MCSTR("class")))->UTF8Characters(); + key.data = (void *) className; + key.len = (unsigned int) strlen(className); + int r = chash_get(constructors, &key, &value); + if (r < 0) + return NULL; + + objectConstructor = (void * (*)()) value.data; + Object * obj = (Object *) objectConstructor(); + obj->importSerializable(serializable); + return obj->autorelease(); +} + diff --git a/src/core/basetypes/MCOperation.cc b/src/core/basetypes/MCOperation.cc deleted file mode 100644 index 51497cba..00000000 --- a/src/core/basetypes/MCOperation.cc +++ /dev/null @@ -1,107 +0,0 @@ -#include "MCOperation.h" - -using namespace mailcore; - -Operation::Operation() -{ - mCallback = NULL; - mCancelled = false; - mShouldRunWhenCancelled = false; - pthread_mutex_init(&mLock, NULL); -#if __APPLE__ - mCallbackDispatchQueue = dispatch_get_main_queue(); -#endif -} - -Operation::~Operation() -{ -#if __APPLE__ - if (mCallbackDispatchQueue != NULL) { - dispatch_release(mCallbackDispatchQueue); - } -#endif - pthread_mutex_destroy(&mLock); -} - -void Operation::setCallback(OperationCallback * callback) -{ - mCallback = callback; -} - -OperationCallback * Operation::callback() -{ - return mCallback; -} - -void Operation::cancel() -{ - pthread_mutex_lock(&mLock); - mCancelled = true; - pthread_mutex_unlock(&mLock); -} - -bool Operation::isCancelled() -{ - pthread_mutex_lock(&mLock); - bool value = mCancelled; - pthread_mutex_unlock(&mLock); - - return value; -} - -bool Operation::shouldRunWhenCancelled() -{ - return mShouldRunWhenCancelled; -} - -void Operation::setShouldRunWhenCancelled(bool shouldRunWhenCancelled) -{ - mShouldRunWhenCancelled = shouldRunWhenCancelled; -} - -void Operation::beforeMain() -{ -} - -void Operation::main() -{ -} - -void Operation::afterMain() -{ -} - -void Operation::start() -{ -} - -#if __APPLE__ -void Operation::setCallbackDispatchQueue(dispatch_queue_t callbackDispatchQueue) -{ - if (mCallbackDispatchQueue != NULL) { - dispatch_release(mCallbackDispatchQueue); - } - mCallbackDispatchQueue = callbackDispatchQueue; - if (mCallbackDispatchQueue != NULL) { - dispatch_retain(mCallbackDispatchQueue); - } -} - -dispatch_queue_t Operation::callbackDispatchQueue() -{ - return mCallbackDispatchQueue; -} -#endif - -void Operation::performMethodOnCallbackThread(Method method, void * context, bool waitUntilDone) -{ -#if __APPLE__ - dispatch_queue_t queue = mCallbackDispatchQueue; - if (queue == NULL) { - queue = dispatch_get_main_queue(); - } - performMethodOnDispatchQueue(method, context, queue, waitUntilDone); -#else - performMethodOnMainThread(method, context, waitUntilDone); -#endif -} diff --git a/src/core/basetypes/MCOperation.cpp b/src/core/basetypes/MCOperation.cpp new file mode 100644 index 00000000..51497cba --- /dev/null +++ b/src/core/basetypes/MCOperation.cpp @@ -0,0 +1,107 @@ +#include "MCOperation.h" + +using namespace mailcore; + +Operation::Operation() +{ + mCallback = NULL; + mCancelled = false; + mShouldRunWhenCancelled = false; + pthread_mutex_init(&mLock, NULL); +#if __APPLE__ + mCallbackDispatchQueue = dispatch_get_main_queue(); +#endif +} + +Operation::~Operation() +{ +#if __APPLE__ + if (mCallbackDispatchQueue != NULL) { + dispatch_release(mCallbackDispatchQueue); + } +#endif + pthread_mutex_destroy(&mLock); +} + +void Operation::setCallback(OperationCallback * callback) +{ + mCallback = callback; +} + +OperationCallback * Operation::callback() +{ + return mCallback; +} + +void Operation::cancel() +{ + pthread_mutex_lock(&mLock); + mCancelled = true; + pthread_mutex_unlock(&mLock); +} + +bool Operation::isCancelled() +{ + pthread_mutex_lock(&mLock); + bool value = mCancelled; + pthread_mutex_unlock(&mLock); + + return value; +} + +bool Operation::shouldRunWhenCancelled() +{ + return mShouldRunWhenCancelled; +} + +void Operation::setShouldRunWhenCancelled(bool shouldRunWhenCancelled) +{ + mShouldRunWhenCancelled = shouldRunWhenCancelled; +} + +void Operation::beforeMain() +{ +} + +void Operation::main() +{ +} + +void Operation::afterMain() +{ +} + +void Operation::start() +{ +} + +#if __APPLE__ +void Operation::setCallbackDispatchQueue(dispatch_queue_t callbackDispatchQueue) +{ + if (mCallbackDispatchQueue != NULL) { + dispatch_release(mCallbackDispatchQueue); + } + mCallbackDispatchQueue = callbackDispatchQueue; + if (mCallbackDispatchQueue != NULL) { + dispatch_retain(mCallbackDispatchQueue); + } +} + +dispatch_queue_t Operation::callbackDispatchQueue() +{ + return mCallbackDispatchQueue; +} +#endif + +void Operation::performMethodOnCallbackThread(Method method, void * context, bool waitUntilDone) +{ +#if __APPLE__ + dispatch_queue_t queue = mCallbackDispatchQueue; + if (queue == NULL) { + queue = dispatch_get_main_queue(); + } + performMethodOnDispatchQueue(method, context, queue, waitUntilDone); +#else + performMethodOnMainThread(method, context, waitUntilDone); +#endif +} diff --git a/src/core/basetypes/MCOperationQueue.cc b/src/core/basetypes/MCOperationQueue.cc deleted file mode 100644 index 7783a978..00000000 --- a/src/core/basetypes/MCOperationQueue.cc +++ /dev/null @@ -1,310 +0,0 @@ -#include "MCOperationQueue.h" - -#include - -#include "MCOperation.h" -#include "MCOperationCallback.h" -#include "MCOperationQueueCallback.h" -#include "MCMainThread.h" -#include "MCUtils.h" -#include "MCArray.h" -#include "MCLog.h" -#include "MCAutoreleasePool.h" - -using namespace mailcore; - -OperationQueue::OperationQueue() -{ - mOperations = new Array(); - mStarted = false; - pthread_mutex_init(&mLock, NULL); - mWaiting = false; - mOperationSem = mailsem_new(); - mStartSem = mailsem_new(); - mStopSem = mailsem_new(); - mWaitingFinishedSem = mailsem_new(); - mQuitting = false; - mCallback = NULL; -#if __APPLE__ - mDispatchQueue = dispatch_get_main_queue(); -#endif - _pendingCheckRunning = false; -} - -OperationQueue::~OperationQueue() -{ -#if __APPLE__ - if (mDispatchQueue != NULL) { - dispatch_release(mDispatchQueue); - } -#endif - MC_SAFE_RELEASE(mOperations); - pthread_mutex_destroy(&mLock); - mailsem_free(mOperationSem); - mailsem_free(mStartSem); - mailsem_free(mStopSem); - mailsem_free(mWaitingFinishedSem); -} - -void OperationQueue::addOperation(Operation * op) -{ - pthread_mutex_lock(&mLock); - mOperations->addObject(op); - pthread_mutex_unlock(&mLock); - mailsem_up(mOperationSem); - startThread(); -} - -void OperationQueue::cancelAllOperations() -{ - pthread_mutex_lock(&mLock); - for (unsigned int i = 0 ; i < mOperations->count() ; i ++) { - Operation * op = (Operation *) mOperations->objectAtIndex(i); - op->cancel(); - } - pthread_mutex_unlock(&mLock); -} - -void OperationQueue::runOperationsOnThread(OperationQueue * queue) -{ - queue->runOperations(); -} - -void OperationQueue::runOperations() -{ - MCLog("start thread"); - mailsem_up(mStartSem); - - while (true) { - Operation * op = NULL; - bool needsCheckRunning = false; - bool quitting; - - AutoreleasePool * pool = new AutoreleasePool(); - - mailsem_down(mOperationSem); - - pthread_mutex_lock(&mLock); - if (mOperations->count() > 0) { - op = (Operation *) mOperations->objectAtIndex(0); - } - quitting = mQuitting; - pthread_mutex_unlock(&mLock); - - //MCLog("quitting %i %p", mQuitting, op); - if ((op == NULL) && quitting) { - MCLog("stopping %p", this); - mailsem_up(mStopSem); - - retain(); // (2) -#if __APPLE__ - performMethodOnDispatchQueue((Object::Method) &OperationQueue::stoppedOnMainThread, NULL, mDispatchQueue, true); -#else - performMethodOnMainThread((Object::Method) &OperationQueue::stoppedOnMainThread, NULL, true); -#endif - - pool->release(); - break; - } - - performOnCallbackThread(op, (Object::Method) &OperationQueue::beforeMain, op, true); - - if (!op->isCancelled() || op->shouldRunWhenCancelled()) { - op->main(); - } - - op->retain()->autorelease(); - - pthread_mutex_lock(&mLock); - mOperations->removeObjectAtIndex(0); - if (mOperations->count() == 0) { - if (mWaiting) { - mailsem_up(mWaitingFinishedSem); - } - needsCheckRunning = true; - } - pthread_mutex_unlock(&mLock); - - if (!op->isCancelled()) { - performOnCallbackThread(op, (Object::Method) &OperationQueue::callbackOnMainThread, op, true); - } - - if (needsCheckRunning) { - retain(); // (1) - //MCLog("check running %p", this); -#if __APPLE__ - performMethodOnDispatchQueue((Object::Method) &OperationQueue::checkRunningOnMainThread, this, mDispatchQueue); -#else - performMethodOnMainThread((Object::Method) &OperationQueue::checkRunningOnMainThread, this); -#endif - } - - pool->release(); - } - MCLog("cleanup thread %p", this); -} - -void OperationQueue::performOnCallbackThread(Operation * op, Method method, void * context, bool waitUntilDone) -{ -#if __APPLE__ - dispatch_queue_t queue = op->callbackDispatchQueue(); - if (queue == NULL) { - queue = dispatch_get_main_queue(); - } - performMethodOnDispatchQueue(method, context, queue, waitUntilDone); -#else - performMethodOnMainThread(method, context, waitUntilDone); -#endif -} - -void OperationQueue::beforeMain(Operation * op) -{ - op->beforeMain(); -} - -void OperationQueue::callbackOnMainThread(Operation * op) -{ - op->afterMain(); - - if (op->isCancelled()) - return; - - if (op->callback() != NULL) { - op->callback()->operationFinished(op); - } -} - -void OperationQueue::checkRunningOnMainThread(void * context) -{ - retain(); // (4) - if (_pendingCheckRunning) { -#if __APPLE__ - cancelDelayedPerformMethodOnDispatchQueue((Object::Method) &OperationQueue::checkRunningAfterDelay, NULL, mDispatchQueue); -#else - cancelDelayedPerformMethod((Object::Method) &OperationQueue::checkRunningAfterDelay, NULL); -#endif - release(); // (4) - } - _pendingCheckRunning = true; - -#if __APPLE__ - performMethodOnDispatchQueueAfterDelay((Object::Method) &OperationQueue::checkRunningAfterDelay, NULL, mDispatchQueue, 1); -#else - performMethodAfterDelay((Object::Method) &OperationQueue::checkRunningAfterDelay, NULL, 1); -#endif - - release(); // (1) -} - -void OperationQueue::checkRunningAfterDelay(void * context) -{ - _pendingCheckRunning = false; - pthread_mutex_lock(&mLock); - if (!mQuitting) { - if (mOperations->count() == 0) { - MCLog("trying to quit %p", this); - mailsem_up(mOperationSem); - mQuitting = true; - } - } - pthread_mutex_unlock(&mLock); - - // Number of operations can't be changed because it runs on main thread. - // And addOperation() should also be called from main thread. - - release(); // (4) -} - -void OperationQueue::stoppedOnMainThread(void * context) -{ - MCLog("thread stopped %p", this); - mailsem_down(mStopSem); - mStarted = false; - - if (mCallback) { - mCallback->queueStoppedRunning(); - } - - if (mOperations->count() > 0) { - //Operations have been added while thread was quitting, so restart automatically - startThread(); - } - - release(); // (2) - - release(); // (3) -} - -void OperationQueue::startThread() -{ - if (mStarted) - return; - - if (mCallback) { - mCallback->queueStartRunning(); - } - - retain(); // (3) - mQuitting = false; - mStarted = true; - pthread_create(&mThreadID, NULL, (void * (*)(void *)) OperationQueue::runOperationsOnThread, this); - mailsem_down(mStartSem); -} - -unsigned int OperationQueue::count() -{ - unsigned int count; - - pthread_mutex_lock(&mLock); - count = mOperations->count(); - pthread_mutex_unlock(&mLock); - - return count; -} - -void OperationQueue::setCallback(OperationQueueCallback * callback) -{ - mCallback = callback; -} - -OperationQueueCallback * OperationQueue::callback() -{ - return mCallback; -} - -#if 0 -void OperationQueue::waitUntilAllOperationsAreFinished() -{ - bool waiting = false; - - pthread_mutex_lock(&mLock); - if (mOperations->count() > 0) { - mWaiting = true; - waiting = true; - } - pthread_mutex_unlock(&mLock); - - if (waiting) { - sem_wait(&mWaitingFinishedSem); - } - mWaiting = false; -} -#endif - -#if __APPLE__ -void OperationQueue::setDispatchQueue(dispatch_queue_t dispatchQueue) -{ - if (mDispatchQueue != NULL) { - dispatch_release(mDispatchQueue); - } - mDispatchQueue = dispatchQueue; - if (mDispatchQueue != NULL) { - dispatch_retain(mDispatchQueue); - } -} - -dispatch_queue_t OperationQueue::dispatchQueue() -{ - return mDispatchQueue; -} -#endif diff --git a/src/core/basetypes/MCOperationQueue.cpp b/src/core/basetypes/MCOperationQueue.cpp new file mode 100644 index 00000000..7783a978 --- /dev/null +++ b/src/core/basetypes/MCOperationQueue.cpp @@ -0,0 +1,310 @@ +#include "MCOperationQueue.h" + +#include + +#include "MCOperation.h" +#include "MCOperationCallback.h" +#include "MCOperationQueueCallback.h" +#include "MCMainThread.h" +#include "MCUtils.h" +#include "MCArray.h" +#include "MCLog.h" +#include "MCAutoreleasePool.h" + +using namespace mailcore; + +OperationQueue::OperationQueue() +{ + mOperations = new Array(); + mStarted = false; + pthread_mutex_init(&mLock, NULL); + mWaiting = false; + mOperationSem = mailsem_new(); + mStartSem = mailsem_new(); + mStopSem = mailsem_new(); + mWaitingFinishedSem = mailsem_new(); + mQuitting = false; + mCallback = NULL; +#if __APPLE__ + mDispatchQueue = dispatch_get_main_queue(); +#endif + _pendingCheckRunning = false; +} + +OperationQueue::~OperationQueue() +{ +#if __APPLE__ + if (mDispatchQueue != NULL) { + dispatch_release(mDispatchQueue); + } +#endif + MC_SAFE_RELEASE(mOperations); + pthread_mutex_destroy(&mLock); + mailsem_free(mOperationSem); + mailsem_free(mStartSem); + mailsem_free(mStopSem); + mailsem_free(mWaitingFinishedSem); +} + +void OperationQueue::addOperation(Operation * op) +{ + pthread_mutex_lock(&mLock); + mOperations->addObject(op); + pthread_mutex_unlock(&mLock); + mailsem_up(mOperationSem); + startThread(); +} + +void OperationQueue::cancelAllOperations() +{ + pthread_mutex_lock(&mLock); + for (unsigned int i = 0 ; i < mOperations->count() ; i ++) { + Operation * op = (Operation *) mOperations->objectAtIndex(i); + op->cancel(); + } + pthread_mutex_unlock(&mLock); +} + +void OperationQueue::runOperationsOnThread(OperationQueue * queue) +{ + queue->runOperations(); +} + +void OperationQueue::runOperations() +{ + MCLog("start thread"); + mailsem_up(mStartSem); + + while (true) { + Operation * op = NULL; + bool needsCheckRunning = false; + bool quitting; + + AutoreleasePool * pool = new AutoreleasePool(); + + mailsem_down(mOperationSem); + + pthread_mutex_lock(&mLock); + if (mOperations->count() > 0) { + op = (Operation *) mOperations->objectAtIndex(0); + } + quitting = mQuitting; + pthread_mutex_unlock(&mLock); + + //MCLog("quitting %i %p", mQuitting, op); + if ((op == NULL) && quitting) { + MCLog("stopping %p", this); + mailsem_up(mStopSem); + + retain(); // (2) +#if __APPLE__ + performMethodOnDispatchQueue((Object::Method) &OperationQueue::stoppedOnMainThread, NULL, mDispatchQueue, true); +#else + performMethodOnMainThread((Object::Method) &OperationQueue::stoppedOnMainThread, NULL, true); +#endif + + pool->release(); + break; + } + + performOnCallbackThread(op, (Object::Method) &OperationQueue::beforeMain, op, true); + + if (!op->isCancelled() || op->shouldRunWhenCancelled()) { + op->main(); + } + + op->retain()->autorelease(); + + pthread_mutex_lock(&mLock); + mOperations->removeObjectAtIndex(0); + if (mOperations->count() == 0) { + if (mWaiting) { + mailsem_up(mWaitingFinishedSem); + } + needsCheckRunning = true; + } + pthread_mutex_unlock(&mLock); + + if (!op->isCancelled()) { + performOnCallbackThread(op, (Object::Method) &OperationQueue::callbackOnMainThread, op, true); + } + + if (needsCheckRunning) { + retain(); // (1) + //MCLog("check running %p", this); +#if __APPLE__ + performMethodOnDispatchQueue((Object::Method) &OperationQueue::checkRunningOnMainThread, this, mDispatchQueue); +#else + performMethodOnMainThread((Object::Method) &OperationQueue::checkRunningOnMainThread, this); +#endif + } + + pool->release(); + } + MCLog("cleanup thread %p", this); +} + +void OperationQueue::performOnCallbackThread(Operation * op, Method method, void * context, bool waitUntilDone) +{ +#if __APPLE__ + dispatch_queue_t queue = op->callbackDispatchQueue(); + if (queue == NULL) { + queue = dispatch_get_main_queue(); + } + performMethodOnDispatchQueue(method, context, queue, waitUntilDone); +#else + performMethodOnMainThread(method, context, waitUntilDone); +#endif +} + +void OperationQueue::beforeMain(Operation * op) +{ + op->beforeMain(); +} + +void OperationQueue::callbackOnMainThread(Operation * op) +{ + op->afterMain(); + + if (op->isCancelled()) + return; + + if (op->callback() != NULL) { + op->callback()->operationFinished(op); + } +} + +void OperationQueue::checkRunningOnMainThread(void * context) +{ + retain(); // (4) + if (_pendingCheckRunning) { +#if __APPLE__ + cancelDelayedPerformMethodOnDispatchQueue((Object::Method) &OperationQueue::checkRunningAfterDelay, NULL, mDispatchQueue); +#else + cancelDelayedPerformMethod((Object::Method) &OperationQueue::checkRunningAfterDelay, NULL); +#endif + release(); // (4) + } + _pendingCheckRunning = true; + +#if __APPLE__ + performMethodOnDispatchQueueAfterDelay((Object::Method) &OperationQueue::checkRunningAfterDelay, NULL, mDispatchQueue, 1); +#else + performMethodAfterDelay((Object::Method) &OperationQueue::checkRunningAfterDelay, NULL, 1); +#endif + + release(); // (1) +} + +void OperationQueue::checkRunningAfterDelay(void * context) +{ + _pendingCheckRunning = false; + pthread_mutex_lock(&mLock); + if (!mQuitting) { + if (mOperations->count() == 0) { + MCLog("trying to quit %p", this); + mailsem_up(mOperationSem); + mQuitting = true; + } + } + pthread_mutex_unlock(&mLock); + + // Number of operations can't be changed because it runs on main thread. + // And addOperation() should also be called from main thread. + + release(); // (4) +} + +void OperationQueue::stoppedOnMainThread(void * context) +{ + MCLog("thread stopped %p", this); + mailsem_down(mStopSem); + mStarted = false; + + if (mCallback) { + mCallback->queueStoppedRunning(); + } + + if (mOperations->count() > 0) { + //Operations have been added while thread was quitting, so restart automatically + startThread(); + } + + release(); // (2) + + release(); // (3) +} + +void OperationQueue::startThread() +{ + if (mStarted) + return; + + if (mCallback) { + mCallback->queueStartRunning(); + } + + retain(); // (3) + mQuitting = false; + mStarted = true; + pthread_create(&mThreadID, NULL, (void * (*)(void *)) OperationQueue::runOperationsOnThread, this); + mailsem_down(mStartSem); +} + +unsigned int OperationQueue::count() +{ + unsigned int count; + + pthread_mutex_lock(&mLock); + count = mOperations->count(); + pthread_mutex_unlock(&mLock); + + return count; +} + +void OperationQueue::setCallback(OperationQueueCallback * callback) +{ + mCallback = callback; +} + +OperationQueueCallback * OperationQueue::callback() +{ + return mCallback; +} + +#if 0 +void OperationQueue::waitUntilAllOperationsAreFinished() +{ + bool waiting = false; + + pthread_mutex_lock(&mLock); + if (mOperations->count() > 0) { + mWaiting = true; + waiting = true; + } + pthread_mutex_unlock(&mLock); + + if (waiting) { + sem_wait(&mWaitingFinishedSem); + } + mWaiting = false; +} +#endif + +#if __APPLE__ +void OperationQueue::setDispatchQueue(dispatch_queue_t dispatchQueue) +{ + if (mDispatchQueue != NULL) { + dispatch_release(mDispatchQueue); + } + mDispatchQueue = dispatchQueue; + if (mDispatchQueue != NULL) { + dispatch_retain(mDispatchQueue); + } +} + +dispatch_queue_t OperationQueue::dispatchQueue() +{ + return mDispatchQueue; +} +#endif diff --git a/src/core/basetypes/MCRange.cc b/src/core/basetypes/MCRange.cc deleted file mode 100644 index d99e3dec..00000000 --- a/src/core/basetypes/MCRange.cc +++ /dev/null @@ -1,162 +0,0 @@ -#include "MCWin32.h" // should be included first. - -#include "MCRange.h" - -#include "MCIndexSet.h" -#include "MCHashMap.h" -#include "MCString.h" -#include "MCUtils.h" -#include "MCArray.h" - -#ifndef _MSC_VER -#include -#endif - -using namespace mailcore; - -Range mailcore::RangeEmpty = {UINT64_MAX, 0}; - -Range mailcore::RangeMake(uint64_t location, uint64_t length) -{ - Range range; - range.location = location; - range.length = length; - return range; -} - -Range mailcore::RangeIntersection(Range range1, Range range2) -{ - if (RangeRightBound(range2) < range1.location) { - return RangeEmpty; - } - else if (RangeRightBound(range1) < range2.location) { - return RangeEmpty; - } - else { - uint64_t left1; - uint64_t right1; - uint64_t left2; - uint64_t right2; - uint64_t leftResult; - uint64_t rightResult; - - left1 = range1.location; - right1 = RangeRightBound(range1); - left2 = range2.location; - right2 = RangeRightBound(range2); - - leftResult = MAX(left1, left2); - rightResult = MIN(right1, right2); - if (rightResult == UINT64_MAX) { - return RangeMake(leftResult, UINT64_MAX); - } - else { - return RangeMake(leftResult, rightResult - leftResult); - } - } -} - -bool mailcore::RangeHasIntersection(Range range1, Range range2) -{ - return RangeIntersection(range1, range2).location != UINT64_MAX; -} - -IndexSet * mailcore::RangeRemoveRange(Range range1, Range range2) -{ - uint64_t left1; - uint64_t right1; - uint64_t left2; - uint64_t right2; - IndexSet * result; - - if (!RangeHasIntersection(range1, range2)) - return IndexSet::indexSetWithRange(range1); - - result = IndexSet::indexSet(); - - range2 = RangeIntersection(range1, range2); - - left1 = range1.location; - right1 = RangeRightBound(range1); - left2 = range2.location; - right2 = RangeRightBound(range2); - - if (left2 > left1) { - result->addRange(RangeMake(left1, left2 - left1 - 1)); - } - - if (right2 != UINT64_MAX) { - if (right1 == UINT64_MAX) { - result->addRange(RangeMake(right2 + 1, UINT64_MAX)); - } - else { - if (right2 < right1) { - result->addRange(RangeMake(right2 + 1, right1 - (right2 + 1))); - } - } - } - - return result; -} - -IndexSet * mailcore::RangeUnion(Range range1, Range range2) -{ - if (!RangeHasIntersection(range1, range2)) { - IndexSet * result = IndexSet::indexSet(); - - result->addRange(range1); - result->addRange(range2); - - return result; - } - else { - uint64_t left1; - uint64_t right1; - uint64_t left2; - uint64_t right2; - uint64_t resultLeft; - uint64_t resultRight; - - left1 = range1.location; - right1 = RangeRightBound(range1); - left2 = range2.location; - right2 = RangeRightBound(range2); - - resultLeft = MIN(left1, left2); - resultRight = MAX(right1, right2); - if (resultRight == UINT64_MAX) { - return IndexSet::indexSetWithRange(RangeMake(resultLeft, UINT64_MAX)); - } - else { - return IndexSet::indexSetWithRange(RangeMake(resultLeft, resultRight - resultLeft)); - } - } -} - -uint64_t mailcore::RangeLeftBound(Range range) -{ - return range.location; -} - -uint64_t mailcore::RangeRightBound(Range range) -{ - if (range.length == UINT64_MAX) - return UINT64_MAX; - return range.location + range.length; -} - -String * mailcore::RangeToString(Range range) -{ - return String::stringWithUTF8Format("%llu-%llu", (unsigned long long) range.location, - (unsigned long long) range.length); -} - -Range mailcore::RangeFromString(String * rangeString) -{ - Array * components = rangeString->componentsSeparatedByString(MCSTR("-")); - if (components->count() != 2) - return RangeEmpty; - String * locationString = (String *) components->objectAtIndex(0); - String * lengthString = (String *) components->objectAtIndex(1); - return RangeMake(locationString->unsignedLongLongValue(), lengthString->unsignedLongLongValue()); -} diff --git a/src/core/basetypes/MCRange.cpp b/src/core/basetypes/MCRange.cpp new file mode 100644 index 00000000..d99e3dec --- /dev/null +++ b/src/core/basetypes/MCRange.cpp @@ -0,0 +1,162 @@ +#include "MCWin32.h" // should be included first. + +#include "MCRange.h" + +#include "MCIndexSet.h" +#include "MCHashMap.h" +#include "MCString.h" +#include "MCUtils.h" +#include "MCArray.h" + +#ifndef _MSC_VER +#include +#endif + +using namespace mailcore; + +Range mailcore::RangeEmpty = {UINT64_MAX, 0}; + +Range mailcore::RangeMake(uint64_t location, uint64_t length) +{ + Range range; + range.location = location; + range.length = length; + return range; +} + +Range mailcore::RangeIntersection(Range range1, Range range2) +{ + if (RangeRightBound(range2) < range1.location) { + return RangeEmpty; + } + else if (RangeRightBound(range1) < range2.location) { + return RangeEmpty; + } + else { + uint64_t left1; + uint64_t right1; + uint64_t left2; + uint64_t right2; + uint64_t leftResult; + uint64_t rightResult; + + left1 = range1.location; + right1 = RangeRightBound(range1); + left2 = range2.location; + right2 = RangeRightBound(range2); + + leftResult = MAX(left1, left2); + rightResult = MIN(right1, right2); + if (rightResult == UINT64_MAX) { + return RangeMake(leftResult, UINT64_MAX); + } + else { + return RangeMake(leftResult, rightResult - leftResult); + } + } +} + +bool mailcore::RangeHasIntersection(Range range1, Range range2) +{ + return RangeIntersection(range1, range2).location != UINT64_MAX; +} + +IndexSet * mailcore::RangeRemoveRange(Range range1, Range range2) +{ + uint64_t left1; + uint64_t right1; + uint64_t left2; + uint64_t right2; + IndexSet * result; + + if (!RangeHasIntersection(range1, range2)) + return IndexSet::indexSetWithRange(range1); + + result = IndexSet::indexSet(); + + range2 = RangeIntersection(range1, range2); + + left1 = range1.location; + right1 = RangeRightBound(range1); + left2 = range2.location; + right2 = RangeRightBound(range2); + + if (left2 > left1) { + result->addRange(RangeMake(left1, left2 - left1 - 1)); + } + + if (right2 != UINT64_MAX) { + if (right1 == UINT64_MAX) { + result->addRange(RangeMake(right2 + 1, UINT64_MAX)); + } + else { + if (right2 < right1) { + result->addRange(RangeMake(right2 + 1, right1 - (right2 + 1))); + } + } + } + + return result; +} + +IndexSet * mailcore::RangeUnion(Range range1, Range range2) +{ + if (!RangeHasIntersection(range1, range2)) { + IndexSet * result = IndexSet::indexSet(); + + result->addRange(range1); + result->addRange(range2); + + return result; + } + else { + uint64_t left1; + uint64_t right1; + uint64_t left2; + uint64_t right2; + uint64_t resultLeft; + uint64_t resultRight; + + left1 = range1.location; + right1 = RangeRightBound(range1); + left2 = range2.location; + right2 = RangeRightBound(range2); + + resultLeft = MIN(left1, left2); + resultRight = MAX(right1, right2); + if (resultRight == UINT64_MAX) { + return IndexSet::indexSetWithRange(RangeMake(resultLeft, UINT64_MAX)); + } + else { + return IndexSet::indexSetWithRange(RangeMake(resultLeft, resultRight - resultLeft)); + } + } +} + +uint64_t mailcore::RangeLeftBound(Range range) +{ + return range.location; +} + +uint64_t mailcore::RangeRightBound(Range range) +{ + if (range.length == UINT64_MAX) + return UINT64_MAX; + return range.location + range.length; +} + +String * mailcore::RangeToString(Range range) +{ + return String::stringWithUTF8Format("%llu-%llu", (unsigned long long) range.location, + (unsigned long long) range.length); +} + +Range mailcore::RangeFromString(String * rangeString) +{ + Array * components = rangeString->componentsSeparatedByString(MCSTR("-")); + if (components->count() != 2) + return RangeEmpty; + String * locationString = (String *) components->objectAtIndex(0); + String * lengthString = (String *) components->objectAtIndex(1); + return RangeMake(locationString->unsignedLongLongValue(), lengthString->unsignedLongLongValue()); +} diff --git a/src/core/basetypes/MCSet.cc b/src/core/basetypes/MCSet.cc deleted file mode 100644 index a49a7f68..00000000 --- a/src/core/basetypes/MCSet.cc +++ /dev/null @@ -1,126 +0,0 @@ -#include "MCSet.h" - -#include "MCDefines.h" -#include "MCHashMap.h" -#include "MCString.h" -#include "MCUtils.h" -#include "MCArray.h" -#include "MCLog.h" - -using namespace mailcore; - -void Set::init() -{ - mHash = new HashMap(); -} - -Set::Set() -{ - init(); -} - -Set::Set(Set * o) -{ - init(); - MC_SAFE_REPLACE_COPY(HashMap, mHash, o->mHash); -} - -Set::~Set() -{ - delete mHash; -} - -Set * Set::set() -{ - Set * result = new Set(); - return (Set *) result->autorelease(); -} - -Set * Set::setWithArray(Array * objects) -{ - Set * result = new Set(); - result->addObjectsFromArray(objects); - return (Set *) result->autorelease(); -} - -String * Set::description() -{ - String * result = String::string(); - result->appendUTF8Format("<%s:%p ", MCUTF8(className()), this); - result->appendString(mHash->allKeys()->description()); - result->appendUTF8Characters(">"); - return result; -} - -Object * Set::copy() -{ - return new Set(this); -} - -unsigned int Set::count() -{ - return mHash->count(); -} - -void Set::addObject(Object * obj) -{ - mHash->setObjectForKey(obj, obj); -} - -void Set::removeObject(Object * obj) -{ - mHash->removeObjectForKey(obj); -} - -Object * Set::member(Object * obj) -{ - return mHash->objectForKey(obj); -} - -bool Set::containsObject(Object * obj) -{ - return (mHash->objectForKey(obj) != NULL); -} - -Array * Set::allObjects() -{ - return mHash->allKeys(); -} - -void Set::removeAllObjects() -{ - mHash->removeAllObjects(); -} - -void Set::addObjectsFromArray(Array * objects) -{ - if (objects == NULL) - return; - - for(unsigned int i= 0 ; i < objects->count() ; i ++) { - addObject(objects->objectAtIndex(i)); - } -} - -HashMap * Set::serializable() -{ - HashMap * result = Object::serializable(); - result->setObjectForKey(MCSTR("items"), allObjects()->serializable()); - return result; -} - -void Set::importSerializable(HashMap * serializable) -{ - Array * array = (Array *) Object::objectWithSerializable((HashMap *) serializable->objectForKey(MCSTR("items"))); - addObjectsFromArray(array); -} - -static void * createObject() -{ - return new Set(); -} - -INITIALIZE(Set) -{ - Object::registerObjectConstructor("mailcore::Set", &createObject); -} diff --git a/src/core/basetypes/MCSet.cpp b/src/core/basetypes/MCSet.cpp new file mode 100644 index 00000000..a49a7f68 --- /dev/null +++ b/src/core/basetypes/MCSet.cpp @@ -0,0 +1,126 @@ +#include "MCSet.h" + +#include "MCDefines.h" +#include "MCHashMap.h" +#include "MCString.h" +#include "MCUtils.h" +#include "MCArray.h" +#include "MCLog.h" + +using namespace mailcore; + +void Set::init() +{ + mHash = new HashMap(); +} + +Set::Set() +{ + init(); +} + +Set::Set(Set * o) +{ + init(); + MC_SAFE_REPLACE_COPY(HashMap, mHash, o->mHash); +} + +Set::~Set() +{ + delete mHash; +} + +Set * Set::set() +{ + Set * result = new Set(); + return (Set *) result->autorelease(); +} + +Set * Set::setWithArray(Array * objects) +{ + Set * result = new Set(); + result->addObjectsFromArray(objects); + return (Set *) result->autorelease(); +} + +String * Set::description() +{ + String * result = String::string(); + result->appendUTF8Format("<%s:%p ", MCUTF8(className()), this); + result->appendString(mHash->allKeys()->description()); + result->appendUTF8Characters(">"); + return result; +} + +Object * Set::copy() +{ + return new Set(this); +} + +unsigned int Set::count() +{ + return mHash->count(); +} + +void Set::addObject(Object * obj) +{ + mHash->setObjectForKey(obj, obj); +} + +void Set::removeObject(Object * obj) +{ + mHash->removeObjectForKey(obj); +} + +Object * Set::member(Object * obj) +{ + return mHash->objectForKey(obj); +} + +bool Set::containsObject(Object * obj) +{ + return (mHash->objectForKey(obj) != NULL); +} + +Array * Set::allObjects() +{ + return mHash->allKeys(); +} + +void Set::removeAllObjects() +{ + mHash->removeAllObjects(); +} + +void Set::addObjectsFromArray(Array * objects) +{ + if (objects == NULL) + return; + + for(unsigned int i= 0 ; i < objects->count() ; i ++) { + addObject(objects->objectAtIndex(i)); + } +} + +HashMap * Set::serializable() +{ + HashMap * result = Object::serializable(); + result->setObjectForKey(MCSTR("items"), allObjects()->serializable()); + return result; +} + +void Set::importSerializable(HashMap * serializable) +{ + Array * array = (Array *) Object::objectWithSerializable((HashMap *) serializable->objectForKey(MCSTR("items"))); + addObjectsFromArray(array); +} + +static void * createObject() +{ + return new Set(); +} + +INITIALIZE(Set) +{ + Object::registerObjectConstructor("mailcore::Set", &createObject); +} diff --git a/src/core/basetypes/MCString.cc b/src/core/basetypes/MCString.cc deleted file mode 100644 index c17c7074..00000000 --- a/src/core/basetypes/MCString.cc +++ /dev/null @@ -1,2460 +0,0 @@ -#include "MCWin32.h" // should be included first. - -#include "MCString.h" - -#if __APPLE__ -#define DISABLE_ICU 1 -#endif - -#include -#include -#if !DISABLE_ICU -#include -#include -#include -#endif -#ifndef _MSC_VER -#include -#endif -#include -#include -#include -#include -#if __APPLE__ -#include -#endif - -#include "MCDefines.h" -#include "MCData.h" -#include "MCHash.h" -#include "MCLog.h" -#include "MCUtils.h" -#include "MCRange.h" -#include "MCArray.h" -#include "MCSet.h" -#include "MCHashMap.h" -#include "MCAutoreleasePool.h" -#include "MCValue.h" -#include "MCHTMLCleaner.h" -#include "MCBase64.h" -#include "MCIterator.h" -#include "ConvertUTF.h" - -using namespace mailcore; - -static String * s_unicode160 = NULL; -static String * s_unicode133 = NULL; -static String * s_unicode2028 = NULL; - -#if DISABLE_ICU -static int32_t u_strlen(const UChar *s) { - if (s == NULL) { - return 0; - } - const UChar * p = s; - while (* p != 0) { - p ++; - } - return (int32_t) (p - s); -} - -static UChar * u_memcpy(UChar * dest, const UChar * src, int32_t count) { - memcpy(dest, src, count * sizeof(* src)); - return dest; -} - -static UChar * u_strstr(const UChar * s, const UChar * substring) -{ - if (s == NULL) { - return NULL; - } - CFStringRef cfS = CFStringCreateWithCharactersNoCopy(NULL, (const UniChar *) s, u_strlen(s), kCFAllocatorNull); - CFStringRef cfSubstring = CFStringCreateWithCharactersNoCopy(NULL, (const UniChar *) substring, u_strlen(substring), kCFAllocatorNull); - - CFRange range = CFStringFind(cfS, cfSubstring, 0); - CFRelease(cfSubstring); - CFRelease(cfS); - if (range.length == 0) { - return NULL; - } - return (UChar *) (s + range.location); -} - -static UChar * u_strrstr(const UChar * s, const UChar * substring) -{ - if (s == NULL) { - return NULL; - } - CFStringRef cfS = CFStringCreateWithCharactersNoCopy(NULL, (const UniChar *) s, u_strlen(s), kCFAllocatorNull); - CFStringRef cfSubstring = CFStringCreateWithCharactersNoCopy(NULL, (const UniChar *) substring, u_strlen(substring), kCFAllocatorNull); - - CFRange range = CFStringFind(cfS, cfSubstring, kCFCompareBackwards); - CFRelease(cfSubstring); - CFRelease(cfS); - if (range.length == 0) { - return NULL; - } - return (UChar *) (s + range.location); -} - -static int32_t u_memcmp(const UChar * buf1, const UChar * buf2, int32_t count) -{ - return memcmp(buf1, buf2, count * sizeof(* buf1)); -} - -static UChar * u_strchr(const UChar *s, UChar c) -{ - if (s == NULL) { - return NULL; - } - const UChar * p = s; - while (* p != 0) { - if (* p == c) { - return (UChar *) p; - } - p ++; - } - return NULL; -} - -static UChar * u_strrchr(const UChar *s, UChar c) -{ - if (s == NULL) { - return NULL; - } - const UChar * lastOccurrence = NULL; - const UChar * p = s; - while (* p != 0) { - if (* p == c) { - lastOccurrence = p; - } - p ++; - } - return (UChar *) lastOccurrence; -} -#endif - -void mailcore::setICUDataDirectory(String * directory) -{ -#if !DISABLE_ICU - u_setDataDirectory(directory->fileSystemRepresentation()); -#endif -} - -#pragma mark quote headers string - -static inline int to_be_quoted(const char * word, size_t size, int subject) -{ - int do_quote; - const char * cur; - size_t i; - - do_quote = 0; - cur = word; - for(i = 0 ; i < size ; i ++) { - if (* cur == '=') - do_quote = 1; - - if (!subject) { - switch (* cur) { - case ',': - case ':': - case '!': - case '"': - case '#': - case '$': - case '@': - case '[': - case '\\': - case ']': - case '^': - case '`': - case '{': - case '|': - case '}': - case '~': - case '=': - case '?': - case '_': - do_quote = 1; - break; - } - } - if (((unsigned char) * cur) >= 128) - do_quote = 1; - - cur ++; - } - - return do_quote; -} - -#define MAX_IMF_LINE 72 - -static inline void quote_word(const char * display_charset, - MMAPString * mmapstr, const char * word, size_t size) -{ - const char * cur; - size_t i; - char hex[4]; - int col; - - mmap_string_append(mmapstr, "=?"); - mmap_string_append(mmapstr, display_charset); - mmap_string_append(mmapstr, "?Q?"); - - col = (int) mmapstr->len; - - cur = word; - for(i = 0 ; i < size ; i ++) { - int do_quote_char; - - do_quote_char = 0; - switch (* cur) { - case ',': - case ':': - case '!': - case '"': - case '#': - case '$': - case '@': - case '[': - case '\\': - case ']': - case '^': - case '`': - case '{': - case '|': - case '}': - case '~': - case '=': - case '?': - case '_': - do_quote_char = 1; - break; - - default: - if (((unsigned char) * cur) >= 128) - do_quote_char = 1; - break; - } - - if (do_quote_char) { - snprintf(hex, 4, "=%2.2X", (unsigned char) * cur); - mmap_string_append(mmapstr, hex); - col += 3; - } - else { - if (* cur == ' ') { - mmap_string_append_c(mmapstr, '_'); - } - else { - mmap_string_append_c(mmapstr, * cur); - } - col += 3; - } - cur ++; - } - - mmap_string_append(mmapstr, "?="); -} - -static inline void get_word(const char * begin, const char ** pend, int subject, int * pto_be_quoted) -{ - const char * cur; - - cur = begin; - - while ((* cur != ' ') && (* cur != '\t') && (* cur != '\0')) { - cur ++; - } - while (((* cur == ' ') || (* cur == '\t')) && (* cur != '\0')) { - cur ++; - } - - if (cur - begin + - 1 /* minimum column of string in a - folded header */ > MAX_IMF_LINE) - * pto_be_quoted = 1; - else - * pto_be_quoted = to_be_quoted(begin, cur - begin, subject); - - * pend = cur; -} - -static char * etpan_make_full_quoted_printable(const char * display_charset, - const char * phrase) -{ - int needs_quote; - char * str; - - needs_quote = to_be_quoted(phrase, strlen(phrase), 0); - if (needs_quote) { - MMAPString * mmapstr; - - mmapstr = mmap_string_new(""); - quote_word(display_charset, mmapstr, phrase, strlen(phrase)); - str = strdup(mmapstr->str); - mmap_string_free(mmapstr); - } - else { - str = strdup(phrase); - } - - return str; -} - -static char * etpan_make_quoted_printable(const char * display_charset, - const char * phrase, int subject) -{ - char * str; - const char * cur; - MMAPString * mmapstr; - - mmapstr = mmap_string_new(""); - - cur = phrase; - while (* cur != '\0') { - const char * begin; - const char * end; - int do_quote; - int quote_words; - - begin = cur; - end = begin; - quote_words = 0; - do_quote = 1; - - while (* cur != '\0') { - get_word(cur, &cur, subject, &do_quote); - if (do_quote) { - quote_words = 1; - end = cur; - } - else - break; - if (* cur != '\0') - cur ++; - } - - if (quote_words) { - quote_word(display_charset, mmapstr, begin, end - begin); - - if ((* end == ' ') || (* end == '\t')) { - mmap_string_append_c(mmapstr, * end); - end ++; - } - - if (* end != '\0') { - mmap_string_append_len(mmapstr, end, cur - end); - } - } - else { - mmap_string_append_len(mmapstr, begin, cur - begin); - } - - if ((* cur == ' ') || (* cur == '\t')) { - mmap_string_append_c(mmapstr, * cur); - cur ++; - } - } - - str = strdup(mmapstr->str); - mmap_string_free(mmapstr); - - return str; -} - -#pragma mark extract subject - -static inline int skip_subj_blob(char * subj, size_t * begin, - size_t length, int keep_bracket) -{ - if (keep_bracket) - return 0; - - /* subj-blob = "[" *BLOBCHAR "]" *WSP */ - size_t cur_token; - - cur_token = * begin; - - if (subj[cur_token] != '[') - return 0; - - cur_token ++; - - while (1) { - if (cur_token >= length) - return 0; - - if (subj[cur_token] == '[') - return 0; - - if (subj[cur_token] == ']') - break; - - cur_token ++; - } - - cur_token ++; - - while (1) { - if (cur_token >= length) - break; - - if (subj[cur_token] != ' ') - break; - - cur_token ++; - } - - * begin = cur_token; - - return 1; -} - -static inline int skip_subj_refwd(char * subj, size_t * begin, - size_t length, int keep_bracket) -{ - /* subj-refwd = ("re" / ("fw" ["d"])) *WSP [subj-blob] ":" */ - size_t cur_token; - int prefix; - int has_suffix; - - cur_token = * begin; - prefix = 0; - if (!prefix) { - if (length - cur_token >= 18) { - if (strncasecmp(subj + cur_token, "Переслать", 18) == 0) { - cur_token += 18; - prefix = 1; - } - } - } - if (!prefix) { - if (length - cur_token >= 10) { - if (strncasecmp(subj + cur_token, "Ответ", 10) == 0) { - cur_token += 10; - prefix = 1; - } - } - } - if (!prefix) { - if (length - cur_token >= 7) { - if (strncasecmp(subj + cur_token, "Antwort", 7) == 0) { - cur_token += 7; - prefix = 1; - } - } - } - if (!prefix) { - if (length - cur_token >= 6) { - if (strncasecmp(subj + cur_token, "回复", 6) == 0) { - cur_token += 6; - prefix = 1; - } - else if (strncasecmp(subj + cur_token, "转发", 6) == 0) { - cur_token += 6; - prefix = 1; - } - } - } - if (!prefix) { - if (length - cur_token >= 5) { - // é is 2 chars in utf-8 - if (strncasecmp(subj + cur_token, "réf.", 5) == 0) { - cur_token += 5; - prefix = 1; - } - else if (strncasecmp(subj + cur_token, "rép.", 5) == 0) { - cur_token += 5; - prefix = 1; - } - else if (strncasecmp(subj + cur_token, "trans", 5) == 0) { - cur_token += 5; - prefix = 1; - } - } - } - if (!prefix) { - if (length - cur_token >= 4) { - if (strncasecmp(subj + cur_token, "antw", 4) == 0) { - cur_token += 4; - prefix = 1; - } - } - } - if (!prefix) { - if (length - cur_token >= 3) { - if (strncasecmp(subj + cur_token, "fwd", 3) == 0) { - cur_token += 3; - prefix = 1; - } - else if (strncasecmp(subj + cur_token, "ogg", 3) == 0) { - cur_token += 3; - prefix = 1; - } - else if (strncasecmp(subj + cur_token, "odp", 3) == 0) { - cur_token += 3; - prefix = 1; - } - else if (strncasecmp(subj + cur_token, "res", 3) == 0) { - cur_token += 3; - prefix = 1; - } - else if (strncasecmp(subj + cur_token, "end", 3) == 0) { - cur_token += 3; - prefix = 1; - } - } - } - if (!prefix) { - if (length - cur_token >= 2) { - if (strncasecmp(subj + cur_token, "fw", 2) == 0) { - cur_token += 2; - prefix = 1; - } - else if (strncasecmp(subj + cur_token, "re", 2) == 0) { - cur_token += 2; - prefix = 1; - } - else if (strncasecmp(subj + cur_token, "tr", 2) == 0) { - cur_token += 2; - prefix = 1; - } - else if (strncasecmp(subj + cur_token, "aw", 2) == 0) { - cur_token += 2; - prefix = 1; - } - else if (strncasecmp(subj + cur_token, "sv", 2) == 0) { - cur_token += 2; - prefix = 1; - } - else if (strncasecmp(subj + cur_token, "rv", 2) == 0) { - cur_token += 2; - prefix = 1; - } - } - } - if (!prefix) { - if (length - cur_token >= 1) { - if (strncasecmp(subj + cur_token, "r", 1) == 0) { - cur_token += 1; - prefix = 1; - } - } - } - - if (!prefix) - return 0; - - while (1) { - if (cur_token >= length) - break; - - if (subj[cur_token] != ' ') - break; - - cur_token ++; - } - - skip_subj_blob(subj, &cur_token, length, keep_bracket); - - has_suffix = 0; - - if (!has_suffix) { - if (length - cur_token >= 3) { - if (strncasecmp(subj + cur_token, ":", 3) == 0) { - cur_token += 3; - has_suffix = 1; - } - } - } - - if (!has_suffix) { - if (cur_token < length) { - if (subj[cur_token] == ':') { - cur_token ++; - has_suffix = 1; - } - } - } - - if (!has_suffix) { - return 0; - } - - * begin = cur_token; - - return 1; -} - -static inline int skip_subj_leader(char * subj, size_t * begin, - size_t length, int keep_bracket) -{ - size_t cur_token; - - cur_token = * begin; - - /* subj-leader = (*subj-blob subj-refwd) / WSP */ - - if (subj[cur_token] == ' ') { - cur_token ++; - } - else { - while (cur_token < length) { - if (!skip_subj_blob(subj, &cur_token, length, keep_bracket)) - break; - } - if (!skip_subj_refwd(subj, &cur_token, length, keep_bracket)) - return 0; - } - - * begin = cur_token; - - return 1; -} - -static char * extract_subject(char * str, int keep_bracket) -{ - char * subj; - char * cur; - char * write_pos; - size_t len; - size_t begin; - int do_repeat_5; - int do_repeat_6; - - /* - (1) Convert any RFC 2047 encoded-words in the subject to - UTF-8. - We work on UTF-8 string -- DVH - */ - - subj = strdup(str); - if (subj == NULL) - return NULL; - - len = strlen(subj); - - /* - Convert all tabs and continuations to space. - Convert all multiple spaces to a single space. - */ - - cur = subj; - write_pos = subj; - while (* cur != '\0') { - int cont; - - switch (* cur) { - case '\t': - case '\r': - case '\n': - cont = 1; - - cur ++; - while (* cur && cont) { - switch (* cur) { - case '\t': - case '\r': - case '\n': - cont = 1; - break; - default: - cont = 0; - break; - } - cur ++; - } - - * write_pos = ' '; - write_pos ++; - - break; - - default: - * write_pos = * cur; - write_pos ++; - - cur ++; - - break; - } - } - * write_pos = '\0'; - - begin = 0; - - do { - do_repeat_6 = 0; - - /* - (2) Remove all trailing text of the subject that matches - the subj-trailer ABNF, repeat until no more matches are - possible. - */ - - while (len > 0) { - /* subj-trailer = "(fwd)" / WSP */ - if (subj[len - 1] == ' ') { - subj[len - 1] = '\0'; - len --; - } - else { - if (len < 5) - break; - - if (strncasecmp(subj + len - 5, "(fwd)", 5) != 0) - break; - - subj[len - 5] = '\0'; - len -= 5; - } - } - - do { - size_t saved_begin; - - do_repeat_5 = 0; - - /* - (3) Remove all prefix text of the subject that matches the - subj-leader ABNF. - */ - - if (skip_subj_leader(subj, &begin, len, keep_bracket)) - do_repeat_5 = 1; - - /* - (4) If there is prefix text of the subject that matches the - subj-blob ABNF, and removing that prefix leaves a non-empty - subj-base, then remove the prefix text. - */ - - saved_begin = begin; - if (skip_subj_blob(subj, &begin, len, keep_bracket)) { - if (begin == len) { - /* this will leave a empty subject base */ - begin = saved_begin; - } - else - do_repeat_5 = 1; - } - - /* - (5) Repeat (3) and (4) until no matches remain. - Note: it is possible to defer step (2) until step (6), - but this requires checking for subj-trailer in step (4). - */ - - } - while (do_repeat_5); - - /* - (6) If the resulting text begins with the subj-fwd-hdr ABNF - and ends with the subj-fwd-trl ABNF, remove the - subj-fwd-hdr and subj-fwd-trl and repeat from step (2). - */ - - if (len >= 5) { - if (strncasecmp(subj + begin, "[fwd:", 5) == 0) { - begin += 5; - - if (subj[len - 1] == ']') { - subj[len - 1] = '\0'; - len --; - do_repeat_6 = 1; - } - } - } - - } - while (do_repeat_6); - - /* - (7) The resulting text is the "base subject" used in - threading. - */ - - /* convert to upper case */ - - cur = subj + begin; - write_pos = subj; - - while (* cur != '\0') { - * write_pos = * cur; - cur ++; - write_pos ++; - } - * write_pos = '\0'; - - return subj; -} - -String::String(const UChar * unicodeChars) -{ - mUnicodeChars = NULL; - reset(); - if (unicodeChars != NULL) { - allocate(u_strlen(unicodeChars), true); - } - appendCharacters(unicodeChars); -} - -String::String(const UChar * unicodeChars, unsigned int length) -{ - mUnicodeChars = NULL; - reset(); - allocate(length, true); - appendCharactersLength(unicodeChars, length); -} - -String::String(const char * UTF8Characters) -{ - mUnicodeChars = NULL; - reset(); - allocate((unsigned int) strlen(UTF8Characters), true); - appendUTF8Characters(UTF8Characters); -} - -String::String(String * otherString) -{ - mUnicodeChars = NULL; - reset(); - appendString(otherString); -} - -String::String(Data * data, const char * charset) -{ - mUnicodeChars = NULL; - reset(); - appendBytes(data->bytes(), data->length(), charset); -} - -String::String(const char * bytes, unsigned int length, const char * charset) -{ - mUnicodeChars = NULL; - reset(); - allocate(length, true); - if (charset == NULL) { - appendUTF8CharactersLength(bytes, length); - } - else { - appendBytes(bytes, length, charset); - } -} - -String::~String() -{ - reset(); -} - -static int isPowerOfTwo (unsigned int x) -{ - return ((x != 0) && !(x & (x - 1))); -} - -void String::allocate(unsigned int length, bool force) -{ - length ++; - if (length <= mAllocated) - return; - - if (force) { - mAllocated = length; - } - else { - if (!isPowerOfTwo(mAllocated)) { - mAllocated = 0; - } - if (mAllocated == 0) { - mAllocated = 4; - } - while (length > mAllocated) { - mAllocated *= 2; - } - } - - mUnicodeChars = (UChar *) realloc(mUnicodeChars, mAllocated * sizeof(* mUnicodeChars)); -} - -String * String::string() -{ - return stringWithCharacters(NULL); -} - -String * String::stringWithData(Data * data, const char * charset) -{ - if (data == NULL) { - return String::string(); - } - String * result = NULL; - result = new String(data->bytes(), data->length(), charset); - result->autorelease(); - return result; -} - -String * String::stringWithUTF8Format(const char * format, ...) -{ - va_list argp; - - va_start(argp, format); - String * result = stringWithVUTF8Format(format, argp); - va_end(argp); - - return result; -} - -String * String::stringWithVUTF8Format(const char * format, va_list ap) -{ - char * result; - vasprintf(&result, format, ap); - String * str = stringWithUTF8Characters(result); - free(result); - return str; -} - -String * String::stringWithUTF8Characters(const char * UTF8Characters) -{ - String * result = new String(UTF8Characters); - return (String *) result->autorelease(); -} - -String * String::stringWithCharacters(const UChar * characters) -{ - String * result = new String(characters); - return (String *) result->autorelease(); -} - -String * String::stringWithCharacters(const UChar * characters, unsigned int length) -{ - String * result = new String(characters, length); - return (String *) result->autorelease(); -} - -void String::appendCharactersLength(const UChar * unicodeCharacters, unsigned int length) -{ - if (unicodeCharacters == NULL) { - return; - } - allocate(mLength + length); - memcpy(&mUnicodeChars[mLength], unicodeCharacters, length * sizeof(* mUnicodeChars)); - mLength += length; - mUnicodeChars[mLength] = 0; -} - -void String::appendString(String * otherString) -{ - if (otherString == NULL) { - return; - } - appendCharactersLength(otherString->unicodeCharacters(), otherString->length()); -} - -void String::appendUTF8Format(const char * format, ...) -{ - va_list argp; - - va_start(argp, format); - String * otherString = stringWithVUTF8Format(format, argp); - va_end(argp); - - this->appendString(otherString); -} - -void String::appendUTF8CharactersLength(const char * UTF8Characters, unsigned int length) -{ - if (UTF8Characters == NULL) { - return; - } - - const UTF8 * source = (const UTF8 *) UTF8Characters; - UTF16 * target = (UTF16 *) malloc(length * sizeof(* target)); - UTF16 * targetStart = target; - ConvertUTF8toUTF16(&source, source + length, - &targetStart, targetStart + length, lenientConversion); - appendCharactersLength((UChar *) target, (unsigned int ) (targetStart - target)); - free(target); -} - -void String::appendUTF8Characters(const char * UTF8Characters) -{ - appendUTF8CharactersLength(UTF8Characters, (unsigned int) strlen(UTF8Characters)); -} - -void String::appendCharacters(const UChar * unicodeCharacters) -{ - if (unicodeCharacters == NULL) - return; - - appendCharactersLength(unicodeCharacters, u_strlen(unicodeCharacters)); -} - -const UChar * String::unicodeCharacters() -{ - return mUnicodeChars; -} - -const char * String::UTF8Characters() -{ - const UTF16 * source = (const UTF16 *) mUnicodeChars; - UTF8 * target = (UTF8 *) malloc(mLength * 6 + 1); - UTF8 * targetStart = target; - ConvertUTF16toUTF8(&source, source + mLength, - &targetStart, targetStart + mLength * 6 + 1, lenientConversion); - unsigned int utf8length = (unsigned int) (targetStart - target); - target[utf8length] = 0; - Data * data = Data::dataWithBytes((const char *) target, utf8length + 1); - free(target); - - return data->bytes(); -} - -unsigned int String::length() -{ - return mLength; -} - -String * String::stringByAppendingString(String * otherString) -{ - String * result = new String(this); - result->appendString(otherString); - return (String *) result->autorelease(); -} - -String * String::stringByAppendingUTF8Format(const char * format, ...) -{ - va_list argp; - - va_start(argp, format); - String * otherString = stringWithVUTF8Format(format, argp); - va_end(argp); - - return this->stringByAppendingString(otherString); -} - -String * String::stringByAppendingUTF8Characters(const char * UTF8Characters) -{ - String * otherString = stringWithUTF8Characters(UTF8Characters); - return this->stringByAppendingString(otherString); -} - -String * String::stringByAppendingCharacters(const UChar * unicodeCharacters) -{ - String * otherString = stringWithCharacters(unicodeCharacters); - return this->stringByAppendingString(otherString); -} - -void String::reset() -{ - free(mUnicodeChars); - mUnicodeChars = NULL; - mLength = 0; - mAllocated = 0; -} - -void String::setString(String * otherString) -{ - reset(); - appendString(otherString); -} - -void String::setUTF8Characters(const char * UTF8Characters) -{ - reset(); - appendUTF8Characters(UTF8Characters); -} - -void String::setCharacters(const UChar * unicodeCharacters) -{ - reset(); - appendCharacters(unicodeCharacters); -} - -String * String::description() -{ - return this; -} - -Object * String::copy() -{ - return new String(this); -} - -bool String::isEqual(Object * otherObject) -{ - if (otherObject == NULL) - return false; - - String * otherString = (String *) otherObject; - if (length() != otherString->length()) - return false; - return compare(otherString) == 0; -} - -unsigned int String::hash() -{ - return hashCompute((const char *) mUnicodeChars, mLength * sizeof(* mUnicodeChars)); -} - -#define DEFAULT_INCOMING_CHARSET "iso-8859-1" -#define DEFAULT_DISPLAY_CHARSET "utf-8" - -String * String::stringByDecodingMIMEHeaderValue(const char * phrase) -{ - size_t cur_token; - char * decoded; - String * result; - bool hasEncoding; - - if (phrase == NULL) - return string(); - - if (* phrase == '\0') { - return string(); - } - - hasEncoding = false; - if (strstr(phrase, "=?") != NULL) { - if ((strcasestr(phrase, "?Q?") != NULL) || (strcasestr(phrase, "?B?") != NULL)) { - hasEncoding = true; - } - } - - if (!hasEncoding) { - return Data::dataWithBytes(phrase, (unsigned int) strlen(phrase))->stringWithDetectedCharset(); - } - - cur_token = 0; - decoded = NULL; - mailmime_encoded_phrase_parse(DEFAULT_INCOMING_CHARSET, - phrase, strlen(phrase), - &cur_token, DEFAULT_DISPLAY_CHARSET, - &decoded); - - result = NULL; - if (decoded != NULL) { - result = stringWithUTF8Characters(decoded); - } - else { - MCLog("could not decode: %s\n", phrase); - } - - free(decoded); - - return result; -} - -Data * String::encodedAddressDisplayNameValue() -{ - char * str; - Data * result; - - str = etpan_make_full_quoted_printable(DEFAULT_DISPLAY_CHARSET, UTF8Characters()); - result = Data::dataWithBytes(str, (unsigned int) strlen(str) + 1); - free(str); - - return result; -} - -Data * String::encodedMIMEHeaderValue() -{ - char * str; - Data * result; - - str = etpan_make_quoted_printable(DEFAULT_DISPLAY_CHARSET, UTF8Characters(), 0); - result = Data::dataWithBytes(str, (unsigned int) strlen(str) + 1); - free(str); - - return result; -} - -Data * String::encodedMIMEHeaderValueForSubject() -{ - char * str; - Data * result; - - str = etpan_make_quoted_printable(DEFAULT_DISPLAY_CHARSET, UTF8Characters(), 1); - result = Data::dataWithBytes(str, (unsigned int) strlen(str) + 1); - free(str); - - return result; -} - -int String::compareWithCaseSensitive(String * otherString, bool caseSensitive) -{ - if ((unicodeCharacters() == NULL) && (otherString->unicodeCharacters() != NULL)) { - return 0; - } - - if (unicodeCharacters() == NULL) { - return -1; - } - - if (otherString->unicodeCharacters() == NULL) { - return -1; - } - -#if DISABLE_ICU - CFStringRef cfThis = CFStringCreateWithCharactersNoCopy(NULL, mUnicodeChars, mLength, kCFAllocatorNull); - CFStringRef cfOther = CFStringCreateWithCharactersNoCopy(NULL, otherString->mUnicodeChars, otherString->mLength, kCFAllocatorNull); - CFComparisonResult result = CFStringCompare(cfThis, cfOther, caseSensitive ? 0 : kCFCompareCaseInsensitive); - CFRelease(cfThis); - CFRelease(cfOther); - return result; -#else - if (caseSensitive) { - return u_strcmp(unicodeCharacters(), otherString->unicodeCharacters()); - } - else { - return u_strcasecmp(unicodeCharacters(), otherString->unicodeCharacters(), 0); - } -#endif -} - -int String::compare(String * otherString) -{ - return compareWithCaseSensitive(otherString, true); -} - -int String::caseInsensitiveCompare(String * otherString) -{ - return compareWithCaseSensitive(otherString, false); -} - -//Any-Lower, Any-Upper -String * String::lowercaseString() -{ -#if DISABLE_ICU - CFMutableStringRef cfStr = CFStringCreateMutable(NULL, 0); - CFStringAppendCharacters(cfStr, (const UniChar *) mUnicodeChars, mLength); - CFStringLowercase(cfStr, NULL); - UniChar * characters = (UniChar *) malloc(sizeof(* characters) * mLength); - CFStringGetCharacters(cfStr, CFRangeMake(0, mLength), characters); - String * result = String::stringWithCharacters(characters, mLength); - free(characters); - CFRelease(cfStr); - return result; -#else - UErrorCode err; - String * result = (String *) copy()->autorelease(); - err = U_ZERO_ERROR; - u_strToLower(result->mUnicodeChars, result->mLength, - result->mUnicodeChars, result->mLength, - NULL, &err); - return result; -#endif -} - -String * String::uppercaseString() -{ -#if DISABLE_ICU - CFMutableStringRef cfStr = CFStringCreateMutable(NULL, 0); - CFStringAppendCharacters(cfStr, (const UniChar *) mUnicodeChars, mLength); - CFStringUppercase(cfStr, NULL); - UniChar * characters = (UniChar *) malloc(sizeof(* characters) * mLength); - CFStringGetCharacters(cfStr, CFRangeMake(0, mLength), characters); - String * result = String::stringWithCharacters(characters, mLength); - free(characters); - CFRelease(cfStr); - return result; -#else - UErrorCode err; - String * result = (String *) copy()->autorelease(); - err = U_ZERO_ERROR; - u_strToUpper(result->mUnicodeChars, result->mLength, - result->mUnicodeChars, result->mLength, - NULL, &err); - return result; -#endif -} - -void String::appendBytes(const char * bytes, unsigned int length, const char * charset) -{ - if (bytes == NULL) { - return; - } - -#if __APPLE__ - CFStringEncoding encoding; - if (strcasecmp(charset, "mutf-7") == 0) { - encoding = kCFStringEncodingUTF7_IMAP; - } - else { - CFStringRef encodingName = CFStringCreateWithCString(NULL, charset, kCFStringEncodingUTF8); - encoding = CFStringConvertIANACharSetNameToEncoding(encodingName); - if (encoding == kCFStringEncodingBig5) { - encoding = kCFStringEncodingBig5_HKSCS_1999; - } - if (encoding == kCFStringEncodingGBK_95) { - encoding = kCFStringEncodingGB_18030_2000; - } - if (encoding == kCFStringEncodingGB_2312_80) { - encoding = kCFStringEncodingGB_18030_2000; - } - CFRelease(encodingName); - } - if (encoding == kCFStringEncodingUTF8) { - appendUTF8CharactersLength(bytes, length); - return; - } - - bool converted = false; - int conversionCount = 0; - while (!converted) { - CFStringRef cfStr = CFStringCreateWithBytes(NULL, (const UInt8 *) bytes, (CFIndex) length, encoding, false); - if (cfStr != NULL) { - converted = true; - CFDataRef data = CFStringCreateExternalRepresentation(NULL, cfStr, kCFStringEncodingUTF16LE, '_'); - if (data != NULL) { - UChar * fixedData = (UChar *) malloc(CFDataGetLength(data)); - memcpy(fixedData, CFDataGetBytePtr(data), CFDataGetLength(data)); - unsigned int length = (unsigned int) CFDataGetLength(data) / 2; - for(int32_t i = 0 ; i < length ; i ++) { - if (fixedData[i] == 0) { - fixedData[i] = ' '; - } - } - appendCharactersLength(fixedData, length); - free(fixedData); - CFRelease(data); - } - CFRelease(cfStr); - } - else { - length --; - conversionCount ++; - if (conversionCount > 10) { - // failed. - break; - } - } - } -#else - UErrorCode err; - - err = U_ZERO_ERROR; - UConverter * converter = ucnv_open(charset, &err); - if (converter == NULL) { - MCLog("invalid charset %s %i", charset, err); - return; - } - - err = U_ZERO_ERROR; - int32_t destLength = ucnv_toUChars(converter, NULL, 0, - bytes, length, &err); - int32_t destCapacity = destLength + 1; - UChar * dest = (UChar *) malloc(destCapacity * sizeof(* dest)); - err = U_ZERO_ERROR; - destLength = ucnv_toUChars(converter, dest, destCapacity, bytes, length, &err); - dest[destLength] = 0; - - // Fix in case of bad conversion. - for(int32_t i = 0 ; i < destLength ; i ++) { - if (dest[i] == 0) { - dest[i] = ' '; - } - } - - appendCharactersLength(dest, destLength); - free(dest); - - ucnv_close(converter); -#endif -} - -String * String::extractedSubject() -{ - return extractedSubjectAndKeepBracket(false); -} - -String * String::extractedSubjectAndKeepBracket(bool keepBracket) -{ - char * result; - String * str; - - result = extract_subject((char *) UTF8Characters(), keepBracket); - str = String::stringWithUTF8Characters(result); - free(result); - - return str; -} - -#ifndef _MSC_VER -String * String::uuidString() -{ - uuid_t uuid; -#ifdef _UUID_STRING_T - uuid_string_t uuidString; -#else - char uuidString[37]; -#endif - - uuid_generate(uuid); - uuid_unparse_lower(uuid, uuidString); - return String::stringWithUTF8Characters(uuidString); -} -#endif - -unsigned int String::replaceOccurrencesOfString(String * occurrence, String * replacement) -{ - unsigned int count; - - if (occurrence->length() == 0) - return 0; - - count = 0; - UChar * p = mUnicodeChars; - while (1) { - UChar * location; - location = u_strstr(p, occurrence->unicodeCharacters()); - if (location == NULL) - break; - p = location + occurrence->length(); - count ++; - } - - UChar * unicodeChars; - int delta = replacement->length() - occurrence->length(); - int modifiedLength = mLength + delta * count + 1; - unicodeChars = (UChar *) malloc(modifiedLength * sizeof(* unicodeChars)); - unicodeChars[modifiedLength - 1] = 0; - UChar * dest_p = unicodeChars; - p = mUnicodeChars; - while (1) { - UChar * location; - unsigned int count; - - location = u_strstr(p, occurrence->unicodeCharacters()); - if (location == NULL) - break; - count = (unsigned int) (location - p); - u_memcpy(dest_p, p, count); - dest_p += count; - p += count; - u_memcpy(dest_p, replacement->unicodeCharacters(), replacement->length()); - p += occurrence->length(); - dest_p += replacement->length(); - } - // copy remaining - if(p) { - unsigned int remainingLength = mLength - (unsigned int) (p - mUnicodeChars); - memcpy(dest_p, p, remainingLength * sizeof(* p)); - dest_p += remainingLength; - * dest_p = 0; - } - - free(mUnicodeChars); - mUnicodeChars = unicodeChars; - mLength = modifiedLength - 1; - - return count; -} - -UChar String::characterAtIndex(unsigned int index) -{ - return mUnicodeChars[index]; -} - -void String::deleteCharactersInRange(Range range) -{ - if (range.location > mLength) - return; - - if (range.length > mLength) { - range.length = mLength - range.location; - } - else if (range.location + range.length > mLength) { - range.length = mLength - range.location; - } - - int32_t count = mLength - (int32_t) (range.location + range.length); - memmove(&mUnicodeChars[range.location], &mUnicodeChars[range.location + range.length], count * sizeof(* mUnicodeChars)); - mLength -= range.length; - mUnicodeChars[mLength] = 0; -} - -int String::locationOfString(String * occurrence) -{ - UChar * location; - location = u_strstr(mUnicodeChars, occurrence->unicodeCharacters()); - if (location == NULL) { - return -1; - } - - return (int) (location - mUnicodeChars); -} - -#pragma mark strip HTML - -struct parserState { - int level; - int enabled; - int disabledLevel; - String * result; - int logEnabled; - int hasQuote; - int quoteLevel; - bool hasText; - bool lastCharIsWhitespace; - bool showBlockQuote; - bool showLink; - bool hasReturnToLine; - Array * linkStack; - Array * paragraphSpacingStack; -}; - -static void appendQuote(struct parserState * state); - -static void charactersParsed(void * context, - const xmlChar * ch, int len) -/*" Callback function for stringByStrippingHTML. "*/ -{ - struct parserState * state; - - state = (struct parserState *) context; - String * result = state->result; - - if (!state->enabled) { - return; - } - - if (state->logEnabled) { - MCLog("text %s", ch); - } - String * modifiedString; - modifiedString = new String((const char *) ch, len); - modifiedString->autorelease(); - modifiedString = modifiedString->stripWhitespace(); - - if (modifiedString->length() > 0) { - if (state->lastCharIsWhitespace) { - if (modifiedString->characterAtIndex(0) == ' ') { - modifiedString->deleteCharactersInRange(RangeMake(0, 1)); - } - } - } - - if (modifiedString->length() > 0) { - bool lastIsWhiteSpace; - bool isWhiteSpace; - - isWhiteSpace = false; - lastIsWhiteSpace = false; - if (modifiedString->length() > 0) { - if (modifiedString->characterAtIndex(modifiedString->length() - 1) == ' ') { - lastIsWhiteSpace = true; - } - } - if (lastIsWhiteSpace && (modifiedString->length() == 1)) { - isWhiteSpace = true; - } - - if (isWhiteSpace) { - if (state->lastCharIsWhitespace) { - // do nothing - } - else if (!state->hasText) { - // do nothing - } - else { - result->appendString(MCSTR(" ")); - state->lastCharIsWhitespace = true; - state->hasText = true; - } - } - else { - if (!state->hasQuote) { - appendQuote(state); - state->hasQuote = true; - } - result->appendString(modifiedString); - state->lastCharIsWhitespace = lastIsWhiteSpace; - state->hasText = true; - } - } -} - -/* GCS: custom error function to ignore errors */ -static void structuredError(void * userData, - xmlErrorPtr error) -{ - /* ignore all errors */ - (void)userData; - (void)error; -} - -static void appendQuote(struct parserState * state) -{ - if (state->quoteLevel < 0) { - MCLog("error consistency in quote level"); - state->lastCharIsWhitespace = true; - return; - } - for(int i = 0 ; i < state->quoteLevel ; i ++) { - state->result->appendString(MCSTR("> ")); - } - state->lastCharIsWhitespace = true; -} - -static void returnToLine(struct parserState * state) -{ - if (!state->hasQuote) { - appendQuote(state); - state->hasQuote = true; - } - state->result->appendString(MCSTR("\n")); - state->hasText = false; - state->lastCharIsWhitespace = true; - state->hasQuote = false; - state->hasReturnToLine = false; -} - -static void returnToLineAtBeginningOfBlock(struct parserState * state) -{ - if (state->hasText) { - returnToLine(state); - } - state->hasQuote = false; -} - -static Set * blockElements(void) -{ - static Set * elements = NULL; - pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; - - pthread_mutex_lock(&lock); - if (elements == NULL) { - elements = new Set(); - elements->addObject(MCSTR("address")); - elements->addObject(MCSTR("div")); - elements->addObject(MCSTR("p")); - elements->addObject(MCSTR("h1")); - elements->addObject(MCSTR("h2")); - elements->addObject(MCSTR("h3")); - elements->addObject(MCSTR("h4")); - elements->addObject(MCSTR("h5")); - elements->addObject(MCSTR("h6")); - elements->addObject(MCSTR("pre")); - elements->addObject(MCSTR("ul")); - elements->addObject(MCSTR("ol")); - elements->addObject(MCSTR("li")); - elements->addObject(MCSTR("dl")); - elements->addObject(MCSTR("dt")); - elements->addObject(MCSTR("dd")); - elements->addObject(MCSTR("form")); - // tables - elements->addObject(MCSTR("col")); - elements->addObject(MCSTR("colgroup")); - elements->addObject(MCSTR("th")); - elements->addObject(MCSTR("tbody")); - elements->addObject(MCSTR("thead")); - elements->addObject(MCSTR("tfoot")); - elements->addObject(MCSTR("table")); - elements->addObject(MCSTR("tr")); - elements->addObject(MCSTR("td")); - } - pthread_mutex_unlock(&lock); - - return elements; -} - -static HashMap * dictionaryFromAttributes(const xmlChar ** atts) -{ - HashMap * result; - - if (atts == NULL) - return NULL; - - result = HashMap::hashMap(); - for(const xmlChar ** curAtt = atts ; * curAtt != NULL ; curAtt += 2) { - const xmlChar * attrName; - const xmlChar * attrValue; - String * name; - - attrName = * curAtt; - attrValue = * (curAtt + 1); - if ((attrName == NULL) || (attrValue == NULL)) - continue; - - name = String::stringWithUTF8Characters((const char *) attrName); - name = name->lowercaseString(); - result->setObjectForKey(name, String::stringWithUTF8Characters((const char *) attrValue)); - } - - return result; -} - -static void elementStarted(void * ctx, const xmlChar * name, const xmlChar ** atts) -{ - struct parserState * state; - - state = (struct parserState *) ctx; - - if (state->logEnabled) { - MCLog("parsed element %s", name); - } - - if (strcasecmp((const char *) name, "blockquote") == 0) { - state->quoteLevel ++; - } - else if (strcasecmp((const char *) name, "a") == 0) { - AutoreleasePool * pool; - String * link = NULL; - HashMap * attributes; - - pool = new AutoreleasePool(); - attributes = dictionaryFromAttributes(atts); - if (attributes != NULL) { - link = (String *) attributes->objectForKey(MCSTR("href")); - } - if (link == NULL) - link = MCSTR(""); - - Array * item; - item = new Array(); - item->addObject(link); - item->addObject(Value::valueWithUnsignedIntValue(state->result->length())); - state->linkStack->addObject(item); - item->release(); - pool->release(); - } - else if (strcasecmp((const char *) name, "p") == 0) { - bool hasSpacing; - String * style; - AutoreleasePool * pool; - HashMap * attributes; - - hasSpacing = true; - - pool = new AutoreleasePool(); - attributes = dictionaryFromAttributes(atts); - if (attributes != NULL) { - style = (String *) attributes->objectForKey(MCSTR("style")); - if (style != NULL) { - if (style->locationOfString(MCSTR("margin: 0.0px 0.0px 0.0px 0.0px;")) != -1) { - hasSpacing = false; - } - else if (style->locationOfString(MCSTR("margin: 0px 0px 0px 0px;")) != -1) { - hasSpacing = false; - } - else if (style->locationOfString(MCSTR("margin: 0.0px;")) != -1) { - hasSpacing = false; - } - else if (style->locationOfString(MCSTR("margin: 0px;")) != -1) { - hasSpacing = false; - } - } - } - pool->release(); - - state->paragraphSpacingStack->addObject(Value::valueWithBoolValue(hasSpacing)); - } - - if (state->enabled) { - if (state->level == 1) { - if (strcasecmp((const char *) name, "head") == 0) { - state->enabled = 0; - state->disabledLevel = state->level; - } - } - if (strcasecmp((const char *) name, "style") == 0) { - state->enabled = 0; - state->disabledLevel = state->level; - } - else if (strcasecmp((const char *) name, "script") == 0) { - state->enabled = 0; - state->disabledLevel = state->level; - } - else if (strcasecmp((const char *) name, "p") == 0) { - returnToLineAtBeginningOfBlock(state); - if (((Value *) state->paragraphSpacingStack->lastObject())->boolValue()) { - returnToLine(state); - } - } - else if (blockElements()->containsObject(String::stringWithUTF8Characters((const char *) name)->lowercaseString())) { - returnToLineAtBeginningOfBlock(state); - } - else if (strcasecmp((const char *) name, "blockquote") == 0) { - if (!state->showBlockQuote) { - AutoreleasePool * pool; - String * type; - bool cite; - HashMap * attributes; - - cite = false; - pool = new AutoreleasePool(); - attributes = dictionaryFromAttributes(atts); - if (attributes != NULL) { - type = (String *) attributes->objectForKey(MCSTR("type")); - if (type != NULL) { - if (type->caseInsensitiveCompare(MCSTR("cite")) == 0) { - cite = true; - } - } - } - pool->release(); - - if (cite) { - state->enabled = 0; - state->disabledLevel = state->level; - } - else { - returnToLineAtBeginningOfBlock(state); - } - } - else { - returnToLineAtBeginningOfBlock(state); - } - } - else if (strcasecmp((const char *) name, "br") == 0) { - returnToLine(state); - state->hasReturnToLine = true; - } - } - - state->level ++; -} - -static void elementEnded(void * ctx, const xmlChar * name) -{ - struct parserState * state; - - state = (struct parserState *) ctx; - - if (state->logEnabled) { - MCLog("ended element %s", name); - } - - if (strcasecmp((const char *) name, "blockquote") == 0) { - state->quoteLevel --; - } - - state->level --; - if (!state->enabled) { - if (state->level == state->disabledLevel) { - state->enabled = 1; - } - } - - bool hasReturnToLine; - - hasReturnToLine = false; - if (strcasecmp((const char *) name, "a") == 0) { - if (state->enabled) { - Array * item; - String * link; - unsigned int offset; - - item = (Array *) state->linkStack->lastObject(); - link = (String *) item->objectAtIndex(0); - offset = ((Value *) item->objectAtIndex(1))->unsignedIntValue(); - if (state->showLink) { - if (offset != state->result->length()) { - if (link->length() > 0) { - if (!state->result->hasSuffix(link)) { - state->result->appendUTF8Characters("("); - state->result->appendString(link); - state->result->appendUTF8Characters(")"); - state->hasText = true; - state->lastCharIsWhitespace = false; - } - } - } - } - } - - state->linkStack->removeObjectAtIndex(state->linkStack->count() - 1); - } - else if (strcasecmp((const char *) name, "p") == 0) { - if (state->enabled) { - if (((Value *) state->paragraphSpacingStack->lastObject())->boolValue()) { - returnToLine(state); - } - } - state->paragraphSpacingStack->removeObjectAtIndex(state->paragraphSpacingStack->count() - 1); - hasReturnToLine = true; - } - else if (blockElements()->containsObject(String::stringWithUTF8Characters((const char *) name)->lowercaseString())) { - hasReturnToLine = true; - } - else if (strcasecmp((const char *) name, "blockquote") == 0) { - hasReturnToLine = true; - } - - if (hasReturnToLine) { - if (state->enabled) { - if (!state->hasReturnToLine) { - returnToLine(state); - } - } - } -} - -static void commentParsed(void * ctx, const xmlChar * value) -{ - struct parserState * state; - - state = (struct parserState *) ctx; - - if (state->logEnabled) { - MCLog("comments %s", value); - } -} - -void initializeLibXML() -{ - static bool initDone = false; - static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; - - pthread_mutex_lock(&lock); - if (!initDone) { - initDone = true; - xmlInitParser(); - - /* GCS: override structuredErrorFunc to mine so - I can ignore errors */ - xmlSetStructuredErrorFunc(xmlGenericErrorContext, - &structuredError); - } - pthread_mutex_unlock(&lock); -} - -String * String::flattenHTMLAndShowBlockquoteAndLink(bool showBlockquote, bool showLink) -/*" Interpretes the receiver als HTML, removes all tags - and returns the plain text. "*/ -{ - initializeLibXML(); - - int mem_base = xmlMemBlocks(); - String * result = String::string(); - xmlSAXHandler handler; - memset(&handler, 0, sizeof(xmlSAXHandler)); - handler.characters = charactersParsed; - handler.startElement = elementStarted; - handler.endElement = elementEnded; - handler.comment = commentParsed; - struct parserState state; - state.result = result; - state.level = 0; - state.enabled = 1; - state.logEnabled = 0; - state.disabledLevel = 0; - state.quoteLevel = 0; - state.hasText = false; - state.hasQuote = false; - state.hasReturnToLine = false; - state.showBlockQuote = showBlockquote; - state.showLink = showLink; - state.lastCharIsWhitespace = true; - state.linkStack = new Array(); - state.paragraphSpacingStack = new Array(); - - const char * characters = cleanedHTMLString()->UTF8Characters(); - - htmlSAXParseDoc((xmlChar*) characters, "utf-8", &handler, &state); - - if (mem_base != xmlMemBlocks()) { - MCLog("Leak of %d blocks found in htmlSAXParseDoc", - xmlMemBlocks() - mem_base); - } - - state.paragraphSpacingStack->release(); - state.linkStack->release(); - - UChar ch[2]; - ch[0] = 160; - ch[1] = 0; - result->replaceOccurrencesOfString(String::stringWithCharacters(ch), MCSTR(" ")); - - return result; -} - -String * String::flattenHTMLAndShowBlockquote(bool showBlockquote) -{ - return flattenHTMLAndShowBlockquoteAndLink(showBlockquote, true); -} - -String * String::flattenHTML() -{ - return flattenHTMLAndShowBlockquote(true); -} - -String * String::stripWhitespace() -{ - String *str = (String *)copy(); - - str->replaceOccurrencesOfString(MCSTR("\t"), MCSTR(" ")); - str->replaceOccurrencesOfString(MCSTR("\n"), MCSTR(" ")); - str->replaceOccurrencesOfString(MCSTR("\v"), MCSTR(" ")); - str->replaceOccurrencesOfString(MCSTR("\f"), MCSTR(" ")); - str->replaceOccurrencesOfString(MCSTR("\r"), MCSTR(" ")); - str->replaceOccurrencesOfString(s_unicode160, MCSTR(" ")); - str->replaceOccurrencesOfString(s_unicode133, MCSTR(" ")); - str->replaceOccurrencesOfString(s_unicode2028, MCSTR(" ")); - - while (str->replaceOccurrencesOfString(MCSTR(" "), MCSTR(" ")) > 0) { - /* do nothing */ - } - while (str->hasPrefix(MCSTR(" "))) { - str->deleteCharactersInRange(RangeMake(0, 1)); - } - while (str->hasSuffix(MCSTR(" "))) { - str->deleteCharactersInRange(RangeMake(str->length() - 1, 1)); - } - - str->autorelease(); - return str; -} - - -bool String::hasSuffix(String * suffix) -{ - if (mLength >= suffix->mLength) { - if (u_memcmp(mUnicodeChars + (mLength - suffix->mLength), - suffix->mUnicodeChars, suffix->mLength) == 0) { - return true; - } - } - return false; -} - -bool String::hasPrefix(String * prefix) -{ - if (mLength >= prefix->mLength) { - if (u_memcmp(prefix->mUnicodeChars, mUnicodeChars, prefix->mLength) == 0) { - return true; - } - } - return false; -} - -String * String::lastPathComponent() -{ - // TODO: Improve Windows compatibility. - if (mUnicodeChars == NULL) - return MCSTR(""); - UChar * component = u_strrchr(mUnicodeChars, '/'); - if (component == NULL) - return (String *) this->copy()->autorelease(); - return String::stringWithCharacters(component + 1); -} - -String * String::pathExtension() -{ - UChar * component = u_strrchr(mUnicodeChars, '.'); - if (component == NULL) - return MCSTR(""); - return String::stringWithCharacters(component + 1); -} - -Data * String::dataUsingEncoding(const char * charset) -{ - if (charset == NULL) { - charset = "utf-8"; - } - -#if __APPLE__ - Data * data; - - data = NULL; - CFStringEncoding encoding; - if (strcasecmp(charset, "mutf-7") == 0) { - encoding = kCFStringEncodingUTF7_IMAP; - } - else { - CFStringRef encodingName = CFStringCreateWithCString(NULL, charset, kCFStringEncodingUTF8); - encoding = CFStringConvertIANACharSetNameToEncoding(encodingName); - CFRelease(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); - } - - return data; -#else - UErrorCode err; - Data * data; - - err = U_ZERO_ERROR; - UConverter * converter = ucnv_open(charset, &err); - if (converter == NULL) { - MCLog("invalid charset %s %i", charset, err); - return NULL; - } - - err = U_ZERO_ERROR; - int32_t destLength = ucnv_fromUChars(converter, NULL, 0, mUnicodeChars, mLength, &err); - int32_t destCapacity = destLength + 1; - char * dest = (char *) malloc(destCapacity * sizeof(* dest)); - err = U_ZERO_ERROR; - destLength = ucnv_fromUChars(converter, dest, destCapacity, mUnicodeChars, mLength, &err); - dest[destLength] = 0; - - // Fix in case of bad conversion. - for(int32_t i = 0 ; i < destLength ; i ++) { - if (dest[i] == 0) { - dest[i] = ' '; - } - } - - data = Data::dataWithBytes(dest, destLength); - - free(dest); - - ucnv_close(converter); - - return data; -#endif -} - -const char * String::fileSystemRepresentation() -{ - return UTF8Characters(); -} - -String * String::stringWithFileSystemRepresentation(const char * filename) -{ - return stringWithUTF8Characters(filename); -} - -String * String::stringByAppendingPathComponent(String * component) -{ - // TODO: Improve Windows compatibility. - String * result = (String *) this->copy()->autorelease(); - if (result->length() > 0) { - UChar lastChar = result->unicodeCharacters()[result->length() - 1]; - if (lastChar != '/') { - result->appendUTF8Characters("/"); - } - } - result->appendString(component); - return result; -} - -String * String::stringByDeletingLastPathComponent() -{ - String * component = lastPathComponent(); - String * result = (String *) this->copy()->autorelease(); - result->deleteCharactersInRange(RangeMake(result->length() - component->length(), component->length())); - return result; -} - -Array * String::componentsSeparatedByString(String * separator) -{ - UChar * p; - Array * result; - - result = Array::array(); - p = mUnicodeChars; - while (1) { - UChar * location; - location = u_strstr(p, separator->unicodeCharacters()); - if (location == NULL) { - break; - } - - unsigned int length = (unsigned int) (location - p); - String * value = new String(p, length); - result->addObject(value); - value->release(); - - p = location + separator->length(); - } - unsigned int length = (unsigned int) (mLength - (p - mUnicodeChars)); - String * value = new String(p, length); - result->addObject(value); - value->release(); - - return result; -} - -int String::intValue() -{ - return (int) strtol(UTF8Characters(), NULL, 10); -} - -unsigned int String::unsignedIntValue() -{ - return (unsigned int) strtoul(UTF8Characters(), NULL, 10); -} - -long String::longValue() -{ - return strtol(UTF8Characters(), NULL, 10); -} - -unsigned long String::unsignedLongValue() -{ - return strtoul(UTF8Characters(), NULL, 10); -} - -long long String::longLongValue() -{ - return strtoll(UTF8Characters(), NULL, 10); -} - -unsigned long long String::unsignedLongLongValue() -{ - return strtoull(UTF8Characters(), NULL, 10); -} - -double String::doubleValue() -{ - return strtod(UTF8Characters(), NULL); - -} - -Data * String::mUTF7EncodedData() -{ - return dataUsingEncoding("mutf-7"); -} - -String * String::stringWithMUTF7Data(Data * data) -{ - return data->stringWithCharset("mutf-7"); -} - -String * String::mUTF7EncodedString() -{ - Data * data = mUTF7EncodedData(); - return data->stringWithCharset("ascii"); -} - -String * String::mUTF7DecodedString() -{ - Data * data = dataUsingEncoding("utf-8"); - return stringWithMUTF7Data(data); -} - -String * String::substringFromIndex(unsigned int idx) -{ - return substringWithRange(RangeMake(idx, length() - idx)); -} - -String * String::substringToIndex(unsigned int idx) -{ - return substringWithRange(RangeMake(0, idx)); -} - -String * String::substringWithRange(Range range) -{ - if (range.location > length()) { - return MCSTR(""); - } - - if (range.location + range.length > length()) { - range.length = length() - range.location; - } - - return stringWithCharacters(unicodeCharacters() + range.location, (unsigned int) range.length); -} - -static chash * uniquedStringHash = NULL; -static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; - -static void initUniquedStringHash() -{ - uniquedStringHash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); -} - -String * String::uniquedStringWithUTF8Characters(const char * UTF8Characters) -{ - chashdatum key; - chashdatum value; - static pthread_once_t once = PTHREAD_ONCE_INIT; - int r; - - pthread_once(&once, initUniquedStringHash); - key.data = (void *) UTF8Characters; - key.len = (unsigned int) strlen(UTF8Characters); - pthread_mutex_lock(&lock); - r = chash_get(uniquedStringHash, &key, &value); - if (r == 0) { - pthread_mutex_unlock(&lock); - return (String *) value.data; - } - else { - value.data = new String(UTF8Characters); - value.len = 0; - chash_set(uniquedStringHash, &key, &value, NULL); - pthread_mutex_unlock(&lock); - return (String *) value.data; - } -} - -String * String::htmlEncodedString() -{ - String * htmlStr = String::string(); -#define kBufSz 2000 - - const char * inStr = UTF8Characters(); - const uint32_t kInStrSz = (const uint32_t) strlen(inStr); - int nInStrConsumed = 0; - - static char buf[kBufSz]; - - int outVal = -1; - int nBufConsumed; - int inStrSz; - do { - nBufConsumed = kBufSz-1; - inStrSz = kInStrSz - nInStrConsumed; - outVal = htmlEncodeEntities( (unsigned char*)buf, - &nBufConsumed, - (const unsigned char*)inStr+nInStrConsumed, - &inStrSz, - 0 ); - if (-2 == outVal || -1 == outVal) { - MCLog("Unable to encode html entities of %s", MCUTF8DESC(this)); - break; - } - buf[nBufConsumed] = '\0'; - htmlStr->appendUTF8Characters(buf); - nInStrConsumed += inStrSz; - } while (nInStrConsumed != kInStrSz); - - htmlStr->replaceOccurrencesOfString(MCSTR("\n"), MCSTR("
")); - - return htmlStr; -} - -String * String::cleanedHTMLString() -{ - return HTMLCleaner::cleanHTML(this); -} - -String * String::htmlMessageContent() -{ - String * str = this; - - Array * lines = str->componentsSeparatedByString(MCSTR("\n")); - - while (1) { - if (lines->count() == 0) { - break; - } - - if (((String *) lines->lastObject())->length() > 0) { - break; - } - - lines->removeLastObject(); - } - - String * localString; - int state; - localString = String::string(); - - String * quoted = NULL; - state = 0; - mc_foreacharray(String, line, lines) { - if (state == 0) { - if (line->hasPrefix(MCSTR(">"))) { - state = 1; - quoted = new String(); - int i = 1; - while (i < line->length()) { - if (line->characterAtIndex(i) != ' ') { - break; - } - i ++; - } - quoted->appendString(line->substringFromIndex(i)); - quoted->appendString(MCSTR("\n")); - } - else { - localString->appendString(line->htmlEncodedString()); - localString->appendString(MCSTR("
")); - } - } - else if (state == 1) { - if (line->hasPrefix(MCSTR(">"))) { - int i = 1; - while (i < line->length()) { - if (line->characterAtIndex(i) != ' ') { - break; - } - i ++; - } - quoted->appendString(line->substringFromIndex(i)); - quoted->appendString(MCSTR("\n")); - } - else { - if (quoted != NULL) { - localString->appendString(MCSTR("
")); - localString->appendString(quoted->htmlMessageContent()); - localString->appendString(MCSTR("
")); - MC_SAFE_RELEASE(quoted); - state = 0; - } - localString->appendString(line->htmlEncodedString()); - localString->appendString(MCSTR("
")); - } - } - } - - if (quoted != NULL) { - localString->appendString(MCSTR("
")); - localString->appendString(quoted->htmlMessageContent()); - localString->appendString(MCSTR("
")); - MC_SAFE_RELEASE(quoted); - } - - return localString; -} - -bool String::isEqualCaseInsensitive(String * otherString) -{ - return caseInsensitiveCompare(otherString) == 0; -} - -Data * String::decodedBase64Data() -{ - const char * utf8 = UTF8Characters(); - unsigned int encoded_len = (unsigned int) strlen(utf8); - int decoded_len = 0; - char * decoded = MCDecodeBase64(utf8, encoded_len, &decoded_len); - Data * result = Data::dataWithBytes(decoded, decoded_len); - free(decoded); - return result; -} - -HashMap * String::serializable() -{ - HashMap * result = Object::serializable(); - result->setObjectForKey(MCSTR("value"), this); - return result; -} - -void String::importSerializable(HashMap * serializable) -{ - String * value = (String *) serializable->objectForKey(MCSTR("value")); - setString(value); -} - -static void * createObject() -{ - return new String(); -} - -INITIALIZE(String) -{ - Object::registerObjectConstructor("mailcore::String", &createObject); - - UChar chars_160[1] = {160}; - s_unicode160 = new String(chars_160, 1); - UChar chars_133[1] = {133}; - s_unicode133 = new String(chars_133, 1); - UChar chars_2028[1] = {0x2028}; - s_unicode2028 = new String(chars_2028, 1); -} diff --git a/src/core/basetypes/MCString.cpp b/src/core/basetypes/MCString.cpp new file mode 100644 index 00000000..c17c7074 --- /dev/null +++ b/src/core/basetypes/MCString.cpp @@ -0,0 +1,2460 @@ +#include "MCWin32.h" // should be included first. + +#include "MCString.h" + +#if __APPLE__ +#define DISABLE_ICU 1 +#endif + +#include +#include +#if !DISABLE_ICU +#include +#include +#include +#endif +#ifndef _MSC_VER +#include +#endif +#include +#include +#include +#include +#if __APPLE__ +#include +#endif + +#include "MCDefines.h" +#include "MCData.h" +#include "MCHash.h" +#include "MCLog.h" +#include "MCUtils.h" +#include "MCRange.h" +#include "MCArray.h" +#include "MCSet.h" +#include "MCHashMap.h" +#include "MCAutoreleasePool.h" +#include "MCValue.h" +#include "MCHTMLCleaner.h" +#include "MCBase64.h" +#include "MCIterator.h" +#include "ConvertUTF.h" + +using namespace mailcore; + +static String * s_unicode160 = NULL; +static String * s_unicode133 = NULL; +static String * s_unicode2028 = NULL; + +#if DISABLE_ICU +static int32_t u_strlen(const UChar *s) { + if (s == NULL) { + return 0; + } + const UChar * p = s; + while (* p != 0) { + p ++; + } + return (int32_t) (p - s); +} + +static UChar * u_memcpy(UChar * dest, const UChar * src, int32_t count) { + memcpy(dest, src, count * sizeof(* src)); + return dest; +} + +static UChar * u_strstr(const UChar * s, const UChar * substring) +{ + if (s == NULL) { + return NULL; + } + CFStringRef cfS = CFStringCreateWithCharactersNoCopy(NULL, (const UniChar *) s, u_strlen(s), kCFAllocatorNull); + CFStringRef cfSubstring = CFStringCreateWithCharactersNoCopy(NULL, (const UniChar *) substring, u_strlen(substring), kCFAllocatorNull); + + CFRange range = CFStringFind(cfS, cfSubstring, 0); + CFRelease(cfSubstring); + CFRelease(cfS); + if (range.length == 0) { + return NULL; + } + return (UChar *) (s + range.location); +} + +static UChar * u_strrstr(const UChar * s, const UChar * substring) +{ + if (s == NULL) { + return NULL; + } + CFStringRef cfS = CFStringCreateWithCharactersNoCopy(NULL, (const UniChar *) s, u_strlen(s), kCFAllocatorNull); + CFStringRef cfSubstring = CFStringCreateWithCharactersNoCopy(NULL, (const UniChar *) substring, u_strlen(substring), kCFAllocatorNull); + + CFRange range = CFStringFind(cfS, cfSubstring, kCFCompareBackwards); + CFRelease(cfSubstring); + CFRelease(cfS); + if (range.length == 0) { + return NULL; + } + return (UChar *) (s + range.location); +} + +static int32_t u_memcmp(const UChar * buf1, const UChar * buf2, int32_t count) +{ + return memcmp(buf1, buf2, count * sizeof(* buf1)); +} + +static UChar * u_strchr(const UChar *s, UChar c) +{ + if (s == NULL) { + return NULL; + } + const UChar * p = s; + while (* p != 0) { + if (* p == c) { + return (UChar *) p; + } + p ++; + } + return NULL; +} + +static UChar * u_strrchr(const UChar *s, UChar c) +{ + if (s == NULL) { + return NULL; + } + const UChar * lastOccurrence = NULL; + const UChar * p = s; + while (* p != 0) { + if (* p == c) { + lastOccurrence = p; + } + p ++; + } + return (UChar *) lastOccurrence; +} +#endif + +void mailcore::setICUDataDirectory(String * directory) +{ +#if !DISABLE_ICU + u_setDataDirectory(directory->fileSystemRepresentation()); +#endif +} + +#pragma mark quote headers string + +static inline int to_be_quoted(const char * word, size_t size, int subject) +{ + int do_quote; + const char * cur; + size_t i; + + do_quote = 0; + cur = word; + for(i = 0 ; i < size ; i ++) { + if (* cur == '=') + do_quote = 1; + + if (!subject) { + switch (* cur) { + case ',': + case ':': + case '!': + case '"': + case '#': + case '$': + case '@': + case '[': + case '\\': + case ']': + case '^': + case '`': + case '{': + case '|': + case '}': + case '~': + case '=': + case '?': + case '_': + do_quote = 1; + break; + } + } + if (((unsigned char) * cur) >= 128) + do_quote = 1; + + cur ++; + } + + return do_quote; +} + +#define MAX_IMF_LINE 72 + +static inline void quote_word(const char * display_charset, + MMAPString * mmapstr, const char * word, size_t size) +{ + const char * cur; + size_t i; + char hex[4]; + int col; + + mmap_string_append(mmapstr, "=?"); + mmap_string_append(mmapstr, display_charset); + mmap_string_append(mmapstr, "?Q?"); + + col = (int) mmapstr->len; + + cur = word; + for(i = 0 ; i < size ; i ++) { + int do_quote_char; + + do_quote_char = 0; + switch (* cur) { + case ',': + case ':': + case '!': + case '"': + case '#': + case '$': + case '@': + case '[': + case '\\': + case ']': + case '^': + case '`': + case '{': + case '|': + case '}': + case '~': + case '=': + case '?': + case '_': + do_quote_char = 1; + break; + + default: + if (((unsigned char) * cur) >= 128) + do_quote_char = 1; + break; + } + + if (do_quote_char) { + snprintf(hex, 4, "=%2.2X", (unsigned char) * cur); + mmap_string_append(mmapstr, hex); + col += 3; + } + else { + if (* cur == ' ') { + mmap_string_append_c(mmapstr, '_'); + } + else { + mmap_string_append_c(mmapstr, * cur); + } + col += 3; + } + cur ++; + } + + mmap_string_append(mmapstr, "?="); +} + +static inline void get_word(const char * begin, const char ** pend, int subject, int * pto_be_quoted) +{ + const char * cur; + + cur = begin; + + while ((* cur != ' ') && (* cur != '\t') && (* cur != '\0')) { + cur ++; + } + while (((* cur == ' ') || (* cur == '\t')) && (* cur != '\0')) { + cur ++; + } + + if (cur - begin + + 1 /* minimum column of string in a + folded header */ > MAX_IMF_LINE) + * pto_be_quoted = 1; + else + * pto_be_quoted = to_be_quoted(begin, cur - begin, subject); + + * pend = cur; +} + +static char * etpan_make_full_quoted_printable(const char * display_charset, + const char * phrase) +{ + int needs_quote; + char * str; + + needs_quote = to_be_quoted(phrase, strlen(phrase), 0); + if (needs_quote) { + MMAPString * mmapstr; + + mmapstr = mmap_string_new(""); + quote_word(display_charset, mmapstr, phrase, strlen(phrase)); + str = strdup(mmapstr->str); + mmap_string_free(mmapstr); + } + else { + str = strdup(phrase); + } + + return str; +} + +static char * etpan_make_quoted_printable(const char * display_charset, + const char * phrase, int subject) +{ + char * str; + const char * cur; + MMAPString * mmapstr; + + mmapstr = mmap_string_new(""); + + cur = phrase; + while (* cur != '\0') { + const char * begin; + const char * end; + int do_quote; + int quote_words; + + begin = cur; + end = begin; + quote_words = 0; + do_quote = 1; + + while (* cur != '\0') { + get_word(cur, &cur, subject, &do_quote); + if (do_quote) { + quote_words = 1; + end = cur; + } + else + break; + if (* cur != '\0') + cur ++; + } + + if (quote_words) { + quote_word(display_charset, mmapstr, begin, end - begin); + + if ((* end == ' ') || (* end == '\t')) { + mmap_string_append_c(mmapstr, * end); + end ++; + } + + if (* end != '\0') { + mmap_string_append_len(mmapstr, end, cur - end); + } + } + else { + mmap_string_append_len(mmapstr, begin, cur - begin); + } + + if ((* cur == ' ') || (* cur == '\t')) { + mmap_string_append_c(mmapstr, * cur); + cur ++; + } + } + + str = strdup(mmapstr->str); + mmap_string_free(mmapstr); + + return str; +} + +#pragma mark extract subject + +static inline int skip_subj_blob(char * subj, size_t * begin, + size_t length, int keep_bracket) +{ + if (keep_bracket) + return 0; + + /* subj-blob = "[" *BLOBCHAR "]" *WSP */ + size_t cur_token; + + cur_token = * begin; + + if (subj[cur_token] != '[') + return 0; + + cur_token ++; + + while (1) { + if (cur_token >= length) + return 0; + + if (subj[cur_token] == '[') + return 0; + + if (subj[cur_token] == ']') + break; + + cur_token ++; + } + + cur_token ++; + + while (1) { + if (cur_token >= length) + break; + + if (subj[cur_token] != ' ') + break; + + cur_token ++; + } + + * begin = cur_token; + + return 1; +} + +static inline int skip_subj_refwd(char * subj, size_t * begin, + size_t length, int keep_bracket) +{ + /* subj-refwd = ("re" / ("fw" ["d"])) *WSP [subj-blob] ":" */ + size_t cur_token; + int prefix; + int has_suffix; + + cur_token = * begin; + prefix = 0; + if (!prefix) { + if (length - cur_token >= 18) { + if (strncasecmp(subj + cur_token, "Переслать", 18) == 0) { + cur_token += 18; + prefix = 1; + } + } + } + if (!prefix) { + if (length - cur_token >= 10) { + if (strncasecmp(subj + cur_token, "Ответ", 10) == 0) { + cur_token += 10; + prefix = 1; + } + } + } + if (!prefix) { + if (length - cur_token >= 7) { + if (strncasecmp(subj + cur_token, "Antwort", 7) == 0) { + cur_token += 7; + prefix = 1; + } + } + } + if (!prefix) { + if (length - cur_token >= 6) { + if (strncasecmp(subj + cur_token, "回复", 6) == 0) { + cur_token += 6; + prefix = 1; + } + else if (strncasecmp(subj + cur_token, "转发", 6) == 0) { + cur_token += 6; + prefix = 1; + } + } + } + if (!prefix) { + if (length - cur_token >= 5) { + // é is 2 chars in utf-8 + if (strncasecmp(subj + cur_token, "réf.", 5) == 0) { + cur_token += 5; + prefix = 1; + } + else if (strncasecmp(subj + cur_token, "rép.", 5) == 0) { + cur_token += 5; + prefix = 1; + } + else if (strncasecmp(subj + cur_token, "trans", 5) == 0) { + cur_token += 5; + prefix = 1; + } + } + } + if (!prefix) { + if (length - cur_token >= 4) { + if (strncasecmp(subj + cur_token, "antw", 4) == 0) { + cur_token += 4; + prefix = 1; + } + } + } + if (!prefix) { + if (length - cur_token >= 3) { + if (strncasecmp(subj + cur_token, "fwd", 3) == 0) { + cur_token += 3; + prefix = 1; + } + else if (strncasecmp(subj + cur_token, "ogg", 3) == 0) { + cur_token += 3; + prefix = 1; + } + else if (strncasecmp(subj + cur_token, "odp", 3) == 0) { + cur_token += 3; + prefix = 1; + } + else if (strncasecmp(subj + cur_token, "res", 3) == 0) { + cur_token += 3; + prefix = 1; + } + else if (strncasecmp(subj + cur_token, "end", 3) == 0) { + cur_token += 3; + prefix = 1; + } + } + } + if (!prefix) { + if (length - cur_token >= 2) { + if (strncasecmp(subj + cur_token, "fw", 2) == 0) { + cur_token += 2; + prefix = 1; + } + else if (strncasecmp(subj + cur_token, "re", 2) == 0) { + cur_token += 2; + prefix = 1; + } + else if (strncasecmp(subj + cur_token, "tr", 2) == 0) { + cur_token += 2; + prefix = 1; + } + else if (strncasecmp(subj + cur_token, "aw", 2) == 0) { + cur_token += 2; + prefix = 1; + } + else if (strncasecmp(subj + cur_token, "sv", 2) == 0) { + cur_token += 2; + prefix = 1; + } + else if (strncasecmp(subj + cur_token, "rv", 2) == 0) { + cur_token += 2; + prefix = 1; + } + } + } + if (!prefix) { + if (length - cur_token >= 1) { + if (strncasecmp(subj + cur_token, "r", 1) == 0) { + cur_token += 1; + prefix = 1; + } + } + } + + if (!prefix) + return 0; + + while (1) { + if (cur_token >= length) + break; + + if (subj[cur_token] != ' ') + break; + + cur_token ++; + } + + skip_subj_blob(subj, &cur_token, length, keep_bracket); + + has_suffix = 0; + + if (!has_suffix) { + if (length - cur_token >= 3) { + if (strncasecmp(subj + cur_token, ":", 3) == 0) { + cur_token += 3; + has_suffix = 1; + } + } + } + + if (!has_suffix) { + if (cur_token < length) { + if (subj[cur_token] == ':') { + cur_token ++; + has_suffix = 1; + } + } + } + + if (!has_suffix) { + return 0; + } + + * begin = cur_token; + + return 1; +} + +static inline int skip_subj_leader(char * subj, size_t * begin, + size_t length, int keep_bracket) +{ + size_t cur_token; + + cur_token = * begin; + + /* subj-leader = (*subj-blob subj-refwd) / WSP */ + + if (subj[cur_token] == ' ') { + cur_token ++; + } + else { + while (cur_token < length) { + if (!skip_subj_blob(subj, &cur_token, length, keep_bracket)) + break; + } + if (!skip_subj_refwd(subj, &cur_token, length, keep_bracket)) + return 0; + } + + * begin = cur_token; + + return 1; +} + +static char * extract_subject(char * str, int keep_bracket) +{ + char * subj; + char * cur; + char * write_pos; + size_t len; + size_t begin; + int do_repeat_5; + int do_repeat_6; + + /* + (1) Convert any RFC 2047 encoded-words in the subject to + UTF-8. + We work on UTF-8 string -- DVH + */ + + subj = strdup(str); + if (subj == NULL) + return NULL; + + len = strlen(subj); + + /* + Convert all tabs and continuations to space. + Convert all multiple spaces to a single space. + */ + + cur = subj; + write_pos = subj; + while (* cur != '\0') { + int cont; + + switch (* cur) { + case '\t': + case '\r': + case '\n': + cont = 1; + + cur ++; + while (* cur && cont) { + switch (* cur) { + case '\t': + case '\r': + case '\n': + cont = 1; + break; + default: + cont = 0; + break; + } + cur ++; + } + + * write_pos = ' '; + write_pos ++; + + break; + + default: + * write_pos = * cur; + write_pos ++; + + cur ++; + + break; + } + } + * write_pos = '\0'; + + begin = 0; + + do { + do_repeat_6 = 0; + + /* + (2) Remove all trailing text of the subject that matches + the subj-trailer ABNF, repeat until no more matches are + possible. + */ + + while (len > 0) { + /* subj-trailer = "(fwd)" / WSP */ + if (subj[len - 1] == ' ') { + subj[len - 1] = '\0'; + len --; + } + else { + if (len < 5) + break; + + if (strncasecmp(subj + len - 5, "(fwd)", 5) != 0) + break; + + subj[len - 5] = '\0'; + len -= 5; + } + } + + do { + size_t saved_begin; + + do_repeat_5 = 0; + + /* + (3) Remove all prefix text of the subject that matches the + subj-leader ABNF. + */ + + if (skip_subj_leader(subj, &begin, len, keep_bracket)) + do_repeat_5 = 1; + + /* + (4) If there is prefix text of the subject that matches the + subj-blob ABNF, and removing that prefix leaves a non-empty + subj-base, then remove the prefix text. + */ + + saved_begin = begin; + if (skip_subj_blob(subj, &begin, len, keep_bracket)) { + if (begin == len) { + /* this will leave a empty subject base */ + begin = saved_begin; + } + else + do_repeat_5 = 1; + } + + /* + (5) Repeat (3) and (4) until no matches remain. + Note: it is possible to defer step (2) until step (6), + but this requires checking for subj-trailer in step (4). + */ + + } + while (do_repeat_5); + + /* + (6) If the resulting text begins with the subj-fwd-hdr ABNF + and ends with the subj-fwd-trl ABNF, remove the + subj-fwd-hdr and subj-fwd-trl and repeat from step (2). + */ + + if (len >= 5) { + if (strncasecmp(subj + begin, "[fwd:", 5) == 0) { + begin += 5; + + if (subj[len - 1] == ']') { + subj[len - 1] = '\0'; + len --; + do_repeat_6 = 1; + } + } + } + + } + while (do_repeat_6); + + /* + (7) The resulting text is the "base subject" used in + threading. + */ + + /* convert to upper case */ + + cur = subj + begin; + write_pos = subj; + + while (* cur != '\0') { + * write_pos = * cur; + cur ++; + write_pos ++; + } + * write_pos = '\0'; + + return subj; +} + +String::String(const UChar * unicodeChars) +{ + mUnicodeChars = NULL; + reset(); + if (unicodeChars != NULL) { + allocate(u_strlen(unicodeChars), true); + } + appendCharacters(unicodeChars); +} + +String::String(const UChar * unicodeChars, unsigned int length) +{ + mUnicodeChars = NULL; + reset(); + allocate(length, true); + appendCharactersLength(unicodeChars, length); +} + +String::String(const char * UTF8Characters) +{ + mUnicodeChars = NULL; + reset(); + allocate((unsigned int) strlen(UTF8Characters), true); + appendUTF8Characters(UTF8Characters); +} + +String::String(String * otherString) +{ + mUnicodeChars = NULL; + reset(); + appendString(otherString); +} + +String::String(Data * data, const char * charset) +{ + mUnicodeChars = NULL; + reset(); + appendBytes(data->bytes(), data->length(), charset); +} + +String::String(const char * bytes, unsigned int length, const char * charset) +{ + mUnicodeChars = NULL; + reset(); + allocate(length, true); + if (charset == NULL) { + appendUTF8CharactersLength(bytes, length); + } + else { + appendBytes(bytes, length, charset); + } +} + +String::~String() +{ + reset(); +} + +static int isPowerOfTwo (unsigned int x) +{ + return ((x != 0) && !(x & (x - 1))); +} + +void String::allocate(unsigned int length, bool force) +{ + length ++; + if (length <= mAllocated) + return; + + if (force) { + mAllocated = length; + } + else { + if (!isPowerOfTwo(mAllocated)) { + mAllocated = 0; + } + if (mAllocated == 0) { + mAllocated = 4; + } + while (length > mAllocated) { + mAllocated *= 2; + } + } + + mUnicodeChars = (UChar *) realloc(mUnicodeChars, mAllocated * sizeof(* mUnicodeChars)); +} + +String * String::string() +{ + return stringWithCharacters(NULL); +} + +String * String::stringWithData(Data * data, const char * charset) +{ + if (data == NULL) { + return String::string(); + } + String * result = NULL; + result = new String(data->bytes(), data->length(), charset); + result->autorelease(); + return result; +} + +String * String::stringWithUTF8Format(const char * format, ...) +{ + va_list argp; + + va_start(argp, format); + String * result = stringWithVUTF8Format(format, argp); + va_end(argp); + + return result; +} + +String * String::stringWithVUTF8Format(const char * format, va_list ap) +{ + char * result; + vasprintf(&result, format, ap); + String * str = stringWithUTF8Characters(result); + free(result); + return str; +} + +String * String::stringWithUTF8Characters(const char * UTF8Characters) +{ + String * result = new String(UTF8Characters); + return (String *) result->autorelease(); +} + +String * String::stringWithCharacters(const UChar * characters) +{ + String * result = new String(characters); + return (String *) result->autorelease(); +} + +String * String::stringWithCharacters(const UChar * characters, unsigned int length) +{ + String * result = new String(characters, length); + return (String *) result->autorelease(); +} + +void String::appendCharactersLength(const UChar * unicodeCharacters, unsigned int length) +{ + if (unicodeCharacters == NULL) { + return; + } + allocate(mLength + length); + memcpy(&mUnicodeChars[mLength], unicodeCharacters, length * sizeof(* mUnicodeChars)); + mLength += length; + mUnicodeChars[mLength] = 0; +} + +void String::appendString(String * otherString) +{ + if (otherString == NULL) { + return; + } + appendCharactersLength(otherString->unicodeCharacters(), otherString->length()); +} + +void String::appendUTF8Format(const char * format, ...) +{ + va_list argp; + + va_start(argp, format); + String * otherString = stringWithVUTF8Format(format, argp); + va_end(argp); + + this->appendString(otherString); +} + +void String::appendUTF8CharactersLength(const char * UTF8Characters, unsigned int length) +{ + if (UTF8Characters == NULL) { + return; + } + + const UTF8 * source = (const UTF8 *) UTF8Characters; + UTF16 * target = (UTF16 *) malloc(length * sizeof(* target)); + UTF16 * targetStart = target; + ConvertUTF8toUTF16(&source, source + length, + &targetStart, targetStart + length, lenientConversion); + appendCharactersLength((UChar *) target, (unsigned int ) (targetStart - target)); + free(target); +} + +void String::appendUTF8Characters(const char * UTF8Characters) +{ + appendUTF8CharactersLength(UTF8Characters, (unsigned int) strlen(UTF8Characters)); +} + +void String::appendCharacters(const UChar * unicodeCharacters) +{ + if (unicodeCharacters == NULL) + return; + + appendCharactersLength(unicodeCharacters, u_strlen(unicodeCharacters)); +} + +const UChar * String::unicodeCharacters() +{ + return mUnicodeChars; +} + +const char * String::UTF8Characters() +{ + const UTF16 * source = (const UTF16 *) mUnicodeChars; + UTF8 * target = (UTF8 *) malloc(mLength * 6 + 1); + UTF8 * targetStart = target; + ConvertUTF16toUTF8(&source, source + mLength, + &targetStart, targetStart + mLength * 6 + 1, lenientConversion); + unsigned int utf8length = (unsigned int) (targetStart - target); + target[utf8length] = 0; + Data * data = Data::dataWithBytes((const char *) target, utf8length + 1); + free(target); + + return data->bytes(); +} + +unsigned int String::length() +{ + return mLength; +} + +String * String::stringByAppendingString(String * otherString) +{ + String * result = new String(this); + result->appendString(otherString); + return (String *) result->autorelease(); +} + +String * String::stringByAppendingUTF8Format(const char * format, ...) +{ + va_list argp; + + va_start(argp, format); + String * otherString = stringWithVUTF8Format(format, argp); + va_end(argp); + + return this->stringByAppendingString(otherString); +} + +String * String::stringByAppendingUTF8Characters(const char * UTF8Characters) +{ + String * otherString = stringWithUTF8Characters(UTF8Characters); + return this->stringByAppendingString(otherString); +} + +String * String::stringByAppendingCharacters(const UChar * unicodeCharacters) +{ + String * otherString = stringWithCharacters(unicodeCharacters); + return this->stringByAppendingString(otherString); +} + +void String::reset() +{ + free(mUnicodeChars); + mUnicodeChars = NULL; + mLength = 0; + mAllocated = 0; +} + +void String::setString(String * otherString) +{ + reset(); + appendString(otherString); +} + +void String::setUTF8Characters(const char * UTF8Characters) +{ + reset(); + appendUTF8Characters(UTF8Characters); +} + +void String::setCharacters(const UChar * unicodeCharacters) +{ + reset(); + appendCharacters(unicodeCharacters); +} + +String * String::description() +{ + return this; +} + +Object * String::copy() +{ + return new String(this); +} + +bool String::isEqual(Object * otherObject) +{ + if (otherObject == NULL) + return false; + + String * otherString = (String *) otherObject; + if (length() != otherString->length()) + return false; + return compare(otherString) == 0; +} + +unsigned int String::hash() +{ + return hashCompute((const char *) mUnicodeChars, mLength * sizeof(* mUnicodeChars)); +} + +#define DEFAULT_INCOMING_CHARSET "iso-8859-1" +#define DEFAULT_DISPLAY_CHARSET "utf-8" + +String * String::stringByDecodingMIMEHeaderValue(const char * phrase) +{ + size_t cur_token; + char * decoded; + String * result; + bool hasEncoding; + + if (phrase == NULL) + return string(); + + if (* phrase == '\0') { + return string(); + } + + hasEncoding = false; + if (strstr(phrase, "=?") != NULL) { + if ((strcasestr(phrase, "?Q?") != NULL) || (strcasestr(phrase, "?B?") != NULL)) { + hasEncoding = true; + } + } + + if (!hasEncoding) { + return Data::dataWithBytes(phrase, (unsigned int) strlen(phrase))->stringWithDetectedCharset(); + } + + cur_token = 0; + decoded = NULL; + mailmime_encoded_phrase_parse(DEFAULT_INCOMING_CHARSET, + phrase, strlen(phrase), + &cur_token, DEFAULT_DISPLAY_CHARSET, + &decoded); + + result = NULL; + if (decoded != NULL) { + result = stringWithUTF8Characters(decoded); + } + else { + MCLog("could not decode: %s\n", phrase); + } + + free(decoded); + + return result; +} + +Data * String::encodedAddressDisplayNameValue() +{ + char * str; + Data * result; + + str = etpan_make_full_quoted_printable(DEFAULT_DISPLAY_CHARSET, UTF8Characters()); + result = Data::dataWithBytes(str, (unsigned int) strlen(str) + 1); + free(str); + + return result; +} + +Data * String::encodedMIMEHeaderValue() +{ + char * str; + Data * result; + + str = etpan_make_quoted_printable(DEFAULT_DISPLAY_CHARSET, UTF8Characters(), 0); + result = Data::dataWithBytes(str, (unsigned int) strlen(str) + 1); + free(str); + + return result; +} + +Data * String::encodedMIMEHeaderValueForSubject() +{ + char * str; + Data * result; + + str = etpan_make_quoted_printable(DEFAULT_DISPLAY_CHARSET, UTF8Characters(), 1); + result = Data::dataWithBytes(str, (unsigned int) strlen(str) + 1); + free(str); + + return result; +} + +int String::compareWithCaseSensitive(String * otherString, bool caseSensitive) +{ + if ((unicodeCharacters() == NULL) && (otherString->unicodeCharacters() != NULL)) { + return 0; + } + + if (unicodeCharacters() == NULL) { + return -1; + } + + if (otherString->unicodeCharacters() == NULL) { + return -1; + } + +#if DISABLE_ICU + CFStringRef cfThis = CFStringCreateWithCharactersNoCopy(NULL, mUnicodeChars, mLength, kCFAllocatorNull); + CFStringRef cfOther = CFStringCreateWithCharactersNoCopy(NULL, otherString->mUnicodeChars, otherString->mLength, kCFAllocatorNull); + CFComparisonResult result = CFStringCompare(cfThis, cfOther, caseSensitive ? 0 : kCFCompareCaseInsensitive); + CFRelease(cfThis); + CFRelease(cfOther); + return result; +#else + if (caseSensitive) { + return u_strcmp(unicodeCharacters(), otherString->unicodeCharacters()); + } + else { + return u_strcasecmp(unicodeCharacters(), otherString->unicodeCharacters(), 0); + } +#endif +} + +int String::compare(String * otherString) +{ + return compareWithCaseSensitive(otherString, true); +} + +int String::caseInsensitiveCompare(String * otherString) +{ + return compareWithCaseSensitive(otherString, false); +} + +//Any-Lower, Any-Upper +String * String::lowercaseString() +{ +#if DISABLE_ICU + CFMutableStringRef cfStr = CFStringCreateMutable(NULL, 0); + CFStringAppendCharacters(cfStr, (const UniChar *) mUnicodeChars, mLength); + CFStringLowercase(cfStr, NULL); + UniChar * characters = (UniChar *) malloc(sizeof(* characters) * mLength); + CFStringGetCharacters(cfStr, CFRangeMake(0, mLength), characters); + String * result = String::stringWithCharacters(characters, mLength); + free(characters); + CFRelease(cfStr); + return result; +#else + UErrorCode err; + String * result = (String *) copy()->autorelease(); + err = U_ZERO_ERROR; + u_strToLower(result->mUnicodeChars, result->mLength, + result->mUnicodeChars, result->mLength, + NULL, &err); + return result; +#endif +} + +String * String::uppercaseString() +{ +#if DISABLE_ICU + CFMutableStringRef cfStr = CFStringCreateMutable(NULL, 0); + CFStringAppendCharacters(cfStr, (const UniChar *) mUnicodeChars, mLength); + CFStringUppercase(cfStr, NULL); + UniChar * characters = (UniChar *) malloc(sizeof(* characters) * mLength); + CFStringGetCharacters(cfStr, CFRangeMake(0, mLength), characters); + String * result = String::stringWithCharacters(characters, mLength); + free(characters); + CFRelease(cfStr); + return result; +#else + UErrorCode err; + String * result = (String *) copy()->autorelease(); + err = U_ZERO_ERROR; + u_strToUpper(result->mUnicodeChars, result->mLength, + result->mUnicodeChars, result->mLength, + NULL, &err); + return result; +#endif +} + +void String::appendBytes(const char * bytes, unsigned int length, const char * charset) +{ + if (bytes == NULL) { + return; + } + +#if __APPLE__ + CFStringEncoding encoding; + if (strcasecmp(charset, "mutf-7") == 0) { + encoding = kCFStringEncodingUTF7_IMAP; + } + else { + CFStringRef encodingName = CFStringCreateWithCString(NULL, charset, kCFStringEncodingUTF8); + encoding = CFStringConvertIANACharSetNameToEncoding(encodingName); + if (encoding == kCFStringEncodingBig5) { + encoding = kCFStringEncodingBig5_HKSCS_1999; + } + if (encoding == kCFStringEncodingGBK_95) { + encoding = kCFStringEncodingGB_18030_2000; + } + if (encoding == kCFStringEncodingGB_2312_80) { + encoding = kCFStringEncodingGB_18030_2000; + } + CFRelease(encodingName); + } + if (encoding == kCFStringEncodingUTF8) { + appendUTF8CharactersLength(bytes, length); + return; + } + + bool converted = false; + int conversionCount = 0; + while (!converted) { + CFStringRef cfStr = CFStringCreateWithBytes(NULL, (const UInt8 *) bytes, (CFIndex) length, encoding, false); + if (cfStr != NULL) { + converted = true; + CFDataRef data = CFStringCreateExternalRepresentation(NULL, cfStr, kCFStringEncodingUTF16LE, '_'); + if (data != NULL) { + UChar * fixedData = (UChar *) malloc(CFDataGetLength(data)); + memcpy(fixedData, CFDataGetBytePtr(data), CFDataGetLength(data)); + unsigned int length = (unsigned int) CFDataGetLength(data) / 2; + for(int32_t i = 0 ; i < length ; i ++) { + if (fixedData[i] == 0) { + fixedData[i] = ' '; + } + } + appendCharactersLength(fixedData, length); + free(fixedData); + CFRelease(data); + } + CFRelease(cfStr); + } + else { + length --; + conversionCount ++; + if (conversionCount > 10) { + // failed. + break; + } + } + } +#else + UErrorCode err; + + err = U_ZERO_ERROR; + UConverter * converter = ucnv_open(charset, &err); + if (converter == NULL) { + MCLog("invalid charset %s %i", charset, err); + return; + } + + err = U_ZERO_ERROR; + int32_t destLength = ucnv_toUChars(converter, NULL, 0, + bytes, length, &err); + int32_t destCapacity = destLength + 1; + UChar * dest = (UChar *) malloc(destCapacity * sizeof(* dest)); + err = U_ZERO_ERROR; + destLength = ucnv_toUChars(converter, dest, destCapacity, bytes, length, &err); + dest[destLength] = 0; + + // Fix in case of bad conversion. + for(int32_t i = 0 ; i < destLength ; i ++) { + if (dest[i] == 0) { + dest[i] = ' '; + } + } + + appendCharactersLength(dest, destLength); + free(dest); + + ucnv_close(converter); +#endif +} + +String * String::extractedSubject() +{ + return extractedSubjectAndKeepBracket(false); +} + +String * String::extractedSubjectAndKeepBracket(bool keepBracket) +{ + char * result; + String * str; + + result = extract_subject((char *) UTF8Characters(), keepBracket); + str = String::stringWithUTF8Characters(result); + free(result); + + return str; +} + +#ifndef _MSC_VER +String * String::uuidString() +{ + uuid_t uuid; +#ifdef _UUID_STRING_T + uuid_string_t uuidString; +#else + char uuidString[37]; +#endif + + uuid_generate(uuid); + uuid_unparse_lower(uuid, uuidString); + return String::stringWithUTF8Characters(uuidString); +} +#endif + +unsigned int String::replaceOccurrencesOfString(String * occurrence, String * replacement) +{ + unsigned int count; + + if (occurrence->length() == 0) + return 0; + + count = 0; + UChar * p = mUnicodeChars; + while (1) { + UChar * location; + location = u_strstr(p, occurrence->unicodeCharacters()); + if (location == NULL) + break; + p = location + occurrence->length(); + count ++; + } + + UChar * unicodeChars; + int delta = replacement->length() - occurrence->length(); + int modifiedLength = mLength + delta * count + 1; + unicodeChars = (UChar *) malloc(modifiedLength * sizeof(* unicodeChars)); + unicodeChars[modifiedLength - 1] = 0; + UChar * dest_p = unicodeChars; + p = mUnicodeChars; + while (1) { + UChar * location; + unsigned int count; + + location = u_strstr(p, occurrence->unicodeCharacters()); + if (location == NULL) + break; + count = (unsigned int) (location - p); + u_memcpy(dest_p, p, count); + dest_p += count; + p += count; + u_memcpy(dest_p, replacement->unicodeCharacters(), replacement->length()); + p += occurrence->length(); + dest_p += replacement->length(); + } + // copy remaining + if(p) { + unsigned int remainingLength = mLength - (unsigned int) (p - mUnicodeChars); + memcpy(dest_p, p, remainingLength * sizeof(* p)); + dest_p += remainingLength; + * dest_p = 0; + } + + free(mUnicodeChars); + mUnicodeChars = unicodeChars; + mLength = modifiedLength - 1; + + return count; +} + +UChar String::characterAtIndex(unsigned int index) +{ + return mUnicodeChars[index]; +} + +void String::deleteCharactersInRange(Range range) +{ + if (range.location > mLength) + return; + + if (range.length > mLength) { + range.length = mLength - range.location; + } + else if (range.location + range.length > mLength) { + range.length = mLength - range.location; + } + + int32_t count = mLength - (int32_t) (range.location + range.length); + memmove(&mUnicodeChars[range.location], &mUnicodeChars[range.location + range.length], count * sizeof(* mUnicodeChars)); + mLength -= range.length; + mUnicodeChars[mLength] = 0; +} + +int String::locationOfString(String * occurrence) +{ + UChar * location; + location = u_strstr(mUnicodeChars, occurrence->unicodeCharacters()); + if (location == NULL) { + return -1; + } + + return (int) (location - mUnicodeChars); +} + +#pragma mark strip HTML + +struct parserState { + int level; + int enabled; + int disabledLevel; + String * result; + int logEnabled; + int hasQuote; + int quoteLevel; + bool hasText; + bool lastCharIsWhitespace; + bool showBlockQuote; + bool showLink; + bool hasReturnToLine; + Array * linkStack; + Array * paragraphSpacingStack; +}; + +static void appendQuote(struct parserState * state); + +static void charactersParsed(void * context, + const xmlChar * ch, int len) +/*" Callback function for stringByStrippingHTML. "*/ +{ + struct parserState * state; + + state = (struct parserState *) context; + String * result = state->result; + + if (!state->enabled) { + return; + } + + if (state->logEnabled) { + MCLog("text %s", ch); + } + String * modifiedString; + modifiedString = new String((const char *) ch, len); + modifiedString->autorelease(); + modifiedString = modifiedString->stripWhitespace(); + + if (modifiedString->length() > 0) { + if (state->lastCharIsWhitespace) { + if (modifiedString->characterAtIndex(0) == ' ') { + modifiedString->deleteCharactersInRange(RangeMake(0, 1)); + } + } + } + + if (modifiedString->length() > 0) { + bool lastIsWhiteSpace; + bool isWhiteSpace; + + isWhiteSpace = false; + lastIsWhiteSpace = false; + if (modifiedString->length() > 0) { + if (modifiedString->characterAtIndex(modifiedString->length() - 1) == ' ') { + lastIsWhiteSpace = true; + } + } + if (lastIsWhiteSpace && (modifiedString->length() == 1)) { + isWhiteSpace = true; + } + + if (isWhiteSpace) { + if (state->lastCharIsWhitespace) { + // do nothing + } + else if (!state->hasText) { + // do nothing + } + else { + result->appendString(MCSTR(" ")); + state->lastCharIsWhitespace = true; + state->hasText = true; + } + } + else { + if (!state->hasQuote) { + appendQuote(state); + state->hasQuote = true; + } + result->appendString(modifiedString); + state->lastCharIsWhitespace = lastIsWhiteSpace; + state->hasText = true; + } + } +} + +/* GCS: custom error function to ignore errors */ +static void structuredError(void * userData, + xmlErrorPtr error) +{ + /* ignore all errors */ + (void)userData; + (void)error; +} + +static void appendQuote(struct parserState * state) +{ + if (state->quoteLevel < 0) { + MCLog("error consistency in quote level"); + state->lastCharIsWhitespace = true; + return; + } + for(int i = 0 ; i < state->quoteLevel ; i ++) { + state->result->appendString(MCSTR("> ")); + } + state->lastCharIsWhitespace = true; +} + +static void returnToLine(struct parserState * state) +{ + if (!state->hasQuote) { + appendQuote(state); + state->hasQuote = true; + } + state->result->appendString(MCSTR("\n")); + state->hasText = false; + state->lastCharIsWhitespace = true; + state->hasQuote = false; + state->hasReturnToLine = false; +} + +static void returnToLineAtBeginningOfBlock(struct parserState * state) +{ + if (state->hasText) { + returnToLine(state); + } + state->hasQuote = false; +} + +static Set * blockElements(void) +{ + static Set * elements = NULL; + pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + + pthread_mutex_lock(&lock); + if (elements == NULL) { + elements = new Set(); + elements->addObject(MCSTR("address")); + elements->addObject(MCSTR("div")); + elements->addObject(MCSTR("p")); + elements->addObject(MCSTR("h1")); + elements->addObject(MCSTR("h2")); + elements->addObject(MCSTR("h3")); + elements->addObject(MCSTR("h4")); + elements->addObject(MCSTR("h5")); + elements->addObject(MCSTR("h6")); + elements->addObject(MCSTR("pre")); + elements->addObject(MCSTR("ul")); + elements->addObject(MCSTR("ol")); + elements->addObject(MCSTR("li")); + elements->addObject(MCSTR("dl")); + elements->addObject(MCSTR("dt")); + elements->addObject(MCSTR("dd")); + elements->addObject(MCSTR("form")); + // tables + elements->addObject(MCSTR("col")); + elements->addObject(MCSTR("colgroup")); + elements->addObject(MCSTR("th")); + elements->addObject(MCSTR("tbody")); + elements->addObject(MCSTR("thead")); + elements->addObject(MCSTR("tfoot")); + elements->addObject(MCSTR("table")); + elements->addObject(MCSTR("tr")); + elements->addObject(MCSTR("td")); + } + pthread_mutex_unlock(&lock); + + return elements; +} + +static HashMap * dictionaryFromAttributes(const xmlChar ** atts) +{ + HashMap * result; + + if (atts == NULL) + return NULL; + + result = HashMap::hashMap(); + for(const xmlChar ** curAtt = atts ; * curAtt != NULL ; curAtt += 2) { + const xmlChar * attrName; + const xmlChar * attrValue; + String * name; + + attrName = * curAtt; + attrValue = * (curAtt + 1); + if ((attrName == NULL) || (attrValue == NULL)) + continue; + + name = String::stringWithUTF8Characters((const char *) attrName); + name = name->lowercaseString(); + result->setObjectForKey(name, String::stringWithUTF8Characters((const char *) attrValue)); + } + + return result; +} + +static void elementStarted(void * ctx, const xmlChar * name, const xmlChar ** atts) +{ + struct parserState * state; + + state = (struct parserState *) ctx; + + if (state->logEnabled) { + MCLog("parsed element %s", name); + } + + if (strcasecmp((const char *) name, "blockquote") == 0) { + state->quoteLevel ++; + } + else if (strcasecmp((const char *) name, "a") == 0) { + AutoreleasePool * pool; + String * link = NULL; + HashMap * attributes; + + pool = new AutoreleasePool(); + attributes = dictionaryFromAttributes(atts); + if (attributes != NULL) { + link = (String *) attributes->objectForKey(MCSTR("href")); + } + if (link == NULL) + link = MCSTR(""); + + Array * item; + item = new Array(); + item->addObject(link); + item->addObject(Value::valueWithUnsignedIntValue(state->result->length())); + state->linkStack->addObject(item); + item->release(); + pool->release(); + } + else if (strcasecmp((const char *) name, "p") == 0) { + bool hasSpacing; + String * style; + AutoreleasePool * pool; + HashMap * attributes; + + hasSpacing = true; + + pool = new AutoreleasePool(); + attributes = dictionaryFromAttributes(atts); + if (attributes != NULL) { + style = (String *) attributes->objectForKey(MCSTR("style")); + if (style != NULL) { + if (style->locationOfString(MCSTR("margin: 0.0px 0.0px 0.0px 0.0px;")) != -1) { + hasSpacing = false; + } + else if (style->locationOfString(MCSTR("margin: 0px 0px 0px 0px;")) != -1) { + hasSpacing = false; + } + else if (style->locationOfString(MCSTR("margin: 0.0px;")) != -1) { + hasSpacing = false; + } + else if (style->locationOfString(MCSTR("margin: 0px;")) != -1) { + hasSpacing = false; + } + } + } + pool->release(); + + state->paragraphSpacingStack->addObject(Value::valueWithBoolValue(hasSpacing)); + } + + if (state->enabled) { + if (state->level == 1) { + if (strcasecmp((const char *) name, "head") == 0) { + state->enabled = 0; + state->disabledLevel = state->level; + } + } + if (strcasecmp((const char *) name, "style") == 0) { + state->enabled = 0; + state->disabledLevel = state->level; + } + else if (strcasecmp((const char *) name, "script") == 0) { + state->enabled = 0; + state->disabledLevel = state->level; + } + else if (strcasecmp((const char *) name, "p") == 0) { + returnToLineAtBeginningOfBlock(state); + if (((Value *) state->paragraphSpacingStack->lastObject())->boolValue()) { + returnToLine(state); + } + } + else if (blockElements()->containsObject(String::stringWithUTF8Characters((const char *) name)->lowercaseString())) { + returnToLineAtBeginningOfBlock(state); + } + else if (strcasecmp((const char *) name, "blockquote") == 0) { + if (!state->showBlockQuote) { + AutoreleasePool * pool; + String * type; + bool cite; + HashMap * attributes; + + cite = false; + pool = new AutoreleasePool(); + attributes = dictionaryFromAttributes(atts); + if (attributes != NULL) { + type = (String *) attributes->objectForKey(MCSTR("type")); + if (type != NULL) { + if (type->caseInsensitiveCompare(MCSTR("cite")) == 0) { + cite = true; + } + } + } + pool->release(); + + if (cite) { + state->enabled = 0; + state->disabledLevel = state->level; + } + else { + returnToLineAtBeginningOfBlock(state); + } + } + else { + returnToLineAtBeginningOfBlock(state); + } + } + else if (strcasecmp((const char *) name, "br") == 0) { + returnToLine(state); + state->hasReturnToLine = true; + } + } + + state->level ++; +} + +static void elementEnded(void * ctx, const xmlChar * name) +{ + struct parserState * state; + + state = (struct parserState *) ctx; + + if (state->logEnabled) { + MCLog("ended element %s", name); + } + + if (strcasecmp((const char *) name, "blockquote") == 0) { + state->quoteLevel --; + } + + state->level --; + if (!state->enabled) { + if (state->level == state->disabledLevel) { + state->enabled = 1; + } + } + + bool hasReturnToLine; + + hasReturnToLine = false; + if (strcasecmp((const char *) name, "a") == 0) { + if (state->enabled) { + Array * item; + String * link; + unsigned int offset; + + item = (Array *) state->linkStack->lastObject(); + link = (String *) item->objectAtIndex(0); + offset = ((Value *) item->objectAtIndex(1))->unsignedIntValue(); + if (state->showLink) { + if (offset != state->result->length()) { + if (link->length() > 0) { + if (!state->result->hasSuffix(link)) { + state->result->appendUTF8Characters("("); + state->result->appendString(link); + state->result->appendUTF8Characters(")"); + state->hasText = true; + state->lastCharIsWhitespace = false; + } + } + } + } + } + + state->linkStack->removeObjectAtIndex(state->linkStack->count() - 1); + } + else if (strcasecmp((const char *) name, "p") == 0) { + if (state->enabled) { + if (((Value *) state->paragraphSpacingStack->lastObject())->boolValue()) { + returnToLine(state); + } + } + state->paragraphSpacingStack->removeObjectAtIndex(state->paragraphSpacingStack->count() - 1); + hasReturnToLine = true; + } + else if (blockElements()->containsObject(String::stringWithUTF8Characters((const char *) name)->lowercaseString())) { + hasReturnToLine = true; + } + else if (strcasecmp((const char *) name, "blockquote") == 0) { + hasReturnToLine = true; + } + + if (hasReturnToLine) { + if (state->enabled) { + if (!state->hasReturnToLine) { + returnToLine(state); + } + } + } +} + +static void commentParsed(void * ctx, const xmlChar * value) +{ + struct parserState * state; + + state = (struct parserState *) ctx; + + if (state->logEnabled) { + MCLog("comments %s", value); + } +} + +void initializeLibXML() +{ + static bool initDone = false; + static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + + pthread_mutex_lock(&lock); + if (!initDone) { + initDone = true; + xmlInitParser(); + + /* GCS: override structuredErrorFunc to mine so + I can ignore errors */ + xmlSetStructuredErrorFunc(xmlGenericErrorContext, + &structuredError); + } + pthread_mutex_unlock(&lock); +} + +String * String::flattenHTMLAndShowBlockquoteAndLink(bool showBlockquote, bool showLink) +/*" Interpretes the receiver als HTML, removes all tags + and returns the plain text. "*/ +{ + initializeLibXML(); + + int mem_base = xmlMemBlocks(); + String * result = String::string(); + xmlSAXHandler handler; + memset(&handler, 0, sizeof(xmlSAXHandler)); + handler.characters = charactersParsed; + handler.startElement = elementStarted; + handler.endElement = elementEnded; + handler.comment = commentParsed; + struct parserState state; + state.result = result; + state.level = 0; + state.enabled = 1; + state.logEnabled = 0; + state.disabledLevel = 0; + state.quoteLevel = 0; + state.hasText = false; + state.hasQuote = false; + state.hasReturnToLine = false; + state.showBlockQuote = showBlockquote; + state.showLink = showLink; + state.lastCharIsWhitespace = true; + state.linkStack = new Array(); + state.paragraphSpacingStack = new Array(); + + const char * characters = cleanedHTMLString()->UTF8Characters(); + + htmlSAXParseDoc((xmlChar*) characters, "utf-8", &handler, &state); + + if (mem_base != xmlMemBlocks()) { + MCLog("Leak of %d blocks found in htmlSAXParseDoc", + xmlMemBlocks() - mem_base); + } + + state.paragraphSpacingStack->release(); + state.linkStack->release(); + + UChar ch[2]; + ch[0] = 160; + ch[1] = 0; + result->replaceOccurrencesOfString(String::stringWithCharacters(ch), MCSTR(" ")); + + return result; +} + +String * String::flattenHTMLAndShowBlockquote(bool showBlockquote) +{ + return flattenHTMLAndShowBlockquoteAndLink(showBlockquote, true); +} + +String * String::flattenHTML() +{ + return flattenHTMLAndShowBlockquote(true); +} + +String * String::stripWhitespace() +{ + String *str = (String *)copy(); + + str->replaceOccurrencesOfString(MCSTR("\t"), MCSTR(" ")); + str->replaceOccurrencesOfString(MCSTR("\n"), MCSTR(" ")); + str->replaceOccurrencesOfString(MCSTR("\v"), MCSTR(" ")); + str->replaceOccurrencesOfString(MCSTR("\f"), MCSTR(" ")); + str->replaceOccurrencesOfString(MCSTR("\r"), MCSTR(" ")); + str->replaceOccurrencesOfString(s_unicode160, MCSTR(" ")); + str->replaceOccurrencesOfString(s_unicode133, MCSTR(" ")); + str->replaceOccurrencesOfString(s_unicode2028, MCSTR(" ")); + + while (str->replaceOccurrencesOfString(MCSTR(" "), MCSTR(" ")) > 0) { + /* do nothing */ + } + while (str->hasPrefix(MCSTR(" "))) { + str->deleteCharactersInRange(RangeMake(0, 1)); + } + while (str->hasSuffix(MCSTR(" "))) { + str->deleteCharactersInRange(RangeMake(str->length() - 1, 1)); + } + + str->autorelease(); + return str; +} + + +bool String::hasSuffix(String * suffix) +{ + if (mLength >= suffix->mLength) { + if (u_memcmp(mUnicodeChars + (mLength - suffix->mLength), + suffix->mUnicodeChars, suffix->mLength) == 0) { + return true; + } + } + return false; +} + +bool String::hasPrefix(String * prefix) +{ + if (mLength >= prefix->mLength) { + if (u_memcmp(prefix->mUnicodeChars, mUnicodeChars, prefix->mLength) == 0) { + return true; + } + } + return false; +} + +String * String::lastPathComponent() +{ + // TODO: Improve Windows compatibility. + if (mUnicodeChars == NULL) + return MCSTR(""); + UChar * component = u_strrchr(mUnicodeChars, '/'); + if (component == NULL) + return (String *) this->copy()->autorelease(); + return String::stringWithCharacters(component + 1); +} + +String * String::pathExtension() +{ + UChar * component = u_strrchr(mUnicodeChars, '.'); + if (component == NULL) + return MCSTR(""); + return String::stringWithCharacters(component + 1); +} + +Data * String::dataUsingEncoding(const char * charset) +{ + if (charset == NULL) { + charset = "utf-8"; + } + +#if __APPLE__ + Data * data; + + data = NULL; + CFStringEncoding encoding; + if (strcasecmp(charset, "mutf-7") == 0) { + encoding = kCFStringEncodingUTF7_IMAP; + } + else { + CFStringRef encodingName = CFStringCreateWithCString(NULL, charset, kCFStringEncodingUTF8); + encoding = CFStringConvertIANACharSetNameToEncoding(encodingName); + CFRelease(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); + } + + return data; +#else + UErrorCode err; + Data * data; + + err = U_ZERO_ERROR; + UConverter * converter = ucnv_open(charset, &err); + if (converter == NULL) { + MCLog("invalid charset %s %i", charset, err); + return NULL; + } + + err = U_ZERO_ERROR; + int32_t destLength = ucnv_fromUChars(converter, NULL, 0, mUnicodeChars, mLength, &err); + int32_t destCapacity = destLength + 1; + char * dest = (char *) malloc(destCapacity * sizeof(* dest)); + err = U_ZERO_ERROR; + destLength = ucnv_fromUChars(converter, dest, destCapacity, mUnicodeChars, mLength, &err); + dest[destLength] = 0; + + // Fix in case of bad conversion. + for(int32_t i = 0 ; i < destLength ; i ++) { + if (dest[i] == 0) { + dest[i] = ' '; + } + } + + data = Data::dataWithBytes(dest, destLength); + + free(dest); + + ucnv_close(converter); + + return data; +#endif +} + +const char * String::fileSystemRepresentation() +{ + return UTF8Characters(); +} + +String * String::stringWithFileSystemRepresentation(const char * filename) +{ + return stringWithUTF8Characters(filename); +} + +String * String::stringByAppendingPathComponent(String * component) +{ + // TODO: Improve Windows compatibility. + String * result = (String *) this->copy()->autorelease(); + if (result->length() > 0) { + UChar lastChar = result->unicodeCharacters()[result->length() - 1]; + if (lastChar != '/') { + result->appendUTF8Characters("/"); + } + } + result->appendString(component); + return result; +} + +String * String::stringByDeletingLastPathComponent() +{ + String * component = lastPathComponent(); + String * result = (String *) this->copy()->autorelease(); + result->deleteCharactersInRange(RangeMake(result->length() - component->length(), component->length())); + return result; +} + +Array * String::componentsSeparatedByString(String * separator) +{ + UChar * p; + Array * result; + + result = Array::array(); + p = mUnicodeChars; + while (1) { + UChar * location; + location = u_strstr(p, separator->unicodeCharacters()); + if (location == NULL) { + break; + } + + unsigned int length = (unsigned int) (location - p); + String * value = new String(p, length); + result->addObject(value); + value->release(); + + p = location + separator->length(); + } + unsigned int length = (unsigned int) (mLength - (p - mUnicodeChars)); + String * value = new String(p, length); + result->addObject(value); + value->release(); + + return result; +} + +int String::intValue() +{ + return (int) strtol(UTF8Characters(), NULL, 10); +} + +unsigned int String::unsignedIntValue() +{ + return (unsigned int) strtoul(UTF8Characters(), NULL, 10); +} + +long String::longValue() +{ + return strtol(UTF8Characters(), NULL, 10); +} + +unsigned long String::unsignedLongValue() +{ + return strtoul(UTF8Characters(), NULL, 10); +} + +long long String::longLongValue() +{ + return strtoll(UTF8Characters(), NULL, 10); +} + +unsigned long long String::unsignedLongLongValue() +{ + return strtoull(UTF8Characters(), NULL, 10); +} + +double String::doubleValue() +{ + return strtod(UTF8Characters(), NULL); + +} + +Data * String::mUTF7EncodedData() +{ + return dataUsingEncoding("mutf-7"); +} + +String * String::stringWithMUTF7Data(Data * data) +{ + return data->stringWithCharset("mutf-7"); +} + +String * String::mUTF7EncodedString() +{ + Data * data = mUTF7EncodedData(); + return data->stringWithCharset("ascii"); +} + +String * String::mUTF7DecodedString() +{ + Data * data = dataUsingEncoding("utf-8"); + return stringWithMUTF7Data(data); +} + +String * String::substringFromIndex(unsigned int idx) +{ + return substringWithRange(RangeMake(idx, length() - idx)); +} + +String * String::substringToIndex(unsigned int idx) +{ + return substringWithRange(RangeMake(0, idx)); +} + +String * String::substringWithRange(Range range) +{ + if (range.location > length()) { + return MCSTR(""); + } + + if (range.location + range.length > length()) { + range.length = length() - range.location; + } + + return stringWithCharacters(unicodeCharacters() + range.location, (unsigned int) range.length); +} + +static chash * uniquedStringHash = NULL; +static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + +static void initUniquedStringHash() +{ + uniquedStringHash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); +} + +String * String::uniquedStringWithUTF8Characters(const char * UTF8Characters) +{ + chashdatum key; + chashdatum value; + static pthread_once_t once = PTHREAD_ONCE_INIT; + int r; + + pthread_once(&once, initUniquedStringHash); + key.data = (void *) UTF8Characters; + key.len = (unsigned int) strlen(UTF8Characters); + pthread_mutex_lock(&lock); + r = chash_get(uniquedStringHash, &key, &value); + if (r == 0) { + pthread_mutex_unlock(&lock); + return (String *) value.data; + } + else { + value.data = new String(UTF8Characters); + value.len = 0; + chash_set(uniquedStringHash, &key, &value, NULL); + pthread_mutex_unlock(&lock); + return (String *) value.data; + } +} + +String * String::htmlEncodedString() +{ + String * htmlStr = String::string(); +#define kBufSz 2000 + + const char * inStr = UTF8Characters(); + const uint32_t kInStrSz = (const uint32_t) strlen(inStr); + int nInStrConsumed = 0; + + static char buf[kBufSz]; + + int outVal = -1; + int nBufConsumed; + int inStrSz; + do { + nBufConsumed = kBufSz-1; + inStrSz = kInStrSz - nInStrConsumed; + outVal = htmlEncodeEntities( (unsigned char*)buf, + &nBufConsumed, + (const unsigned char*)inStr+nInStrConsumed, + &inStrSz, + 0 ); + if (-2 == outVal || -1 == outVal) { + MCLog("Unable to encode html entities of %s", MCUTF8DESC(this)); + break; + } + buf[nBufConsumed] = '\0'; + htmlStr->appendUTF8Characters(buf); + nInStrConsumed += inStrSz; + } while (nInStrConsumed != kInStrSz); + + htmlStr->replaceOccurrencesOfString(MCSTR("\n"), MCSTR("
")); + + return htmlStr; +} + +String * String::cleanedHTMLString() +{ + return HTMLCleaner::cleanHTML(this); +} + +String * String::htmlMessageContent() +{ + String * str = this; + + Array * lines = str->componentsSeparatedByString(MCSTR("\n")); + + while (1) { + if (lines->count() == 0) { + break; + } + + if (((String *) lines->lastObject())->length() > 0) { + break; + } + + lines->removeLastObject(); + } + + String * localString; + int state; + localString = String::string(); + + String * quoted = NULL; + state = 0; + mc_foreacharray(String, line, lines) { + if (state == 0) { + if (line->hasPrefix(MCSTR(">"))) { + state = 1; + quoted = new String(); + int i = 1; + while (i < line->length()) { + if (line->characterAtIndex(i) != ' ') { + break; + } + i ++; + } + quoted->appendString(line->substringFromIndex(i)); + quoted->appendString(MCSTR("\n")); + } + else { + localString->appendString(line->htmlEncodedString()); + localString->appendString(MCSTR("
")); + } + } + else if (state == 1) { + if (line->hasPrefix(MCSTR(">"))) { + int i = 1; + while (i < line->length()) { + if (line->characterAtIndex(i) != ' ') { + break; + } + i ++; + } + quoted->appendString(line->substringFromIndex(i)); + quoted->appendString(MCSTR("\n")); + } + else { + if (quoted != NULL) { + localString->appendString(MCSTR("
")); + localString->appendString(quoted->htmlMessageContent()); + localString->appendString(MCSTR("
")); + MC_SAFE_RELEASE(quoted); + state = 0; + } + localString->appendString(line->htmlEncodedString()); + localString->appendString(MCSTR("
")); + } + } + } + + if (quoted != NULL) { + localString->appendString(MCSTR("
")); + localString->appendString(quoted->htmlMessageContent()); + localString->appendString(MCSTR("
")); + MC_SAFE_RELEASE(quoted); + } + + return localString; +} + +bool String::isEqualCaseInsensitive(String * otherString) +{ + return caseInsensitiveCompare(otherString) == 0; +} + +Data * String::decodedBase64Data() +{ + const char * utf8 = UTF8Characters(); + unsigned int encoded_len = (unsigned int) strlen(utf8); + int decoded_len = 0; + char * decoded = MCDecodeBase64(utf8, encoded_len, &decoded_len); + Data * result = Data::dataWithBytes(decoded, decoded_len); + free(decoded); + return result; +} + +HashMap * String::serializable() +{ + HashMap * result = Object::serializable(); + result->setObjectForKey(MCSTR("value"), this); + return result; +} + +void String::importSerializable(HashMap * serializable) +{ + String * value = (String *) serializable->objectForKey(MCSTR("value")); + setString(value); +} + +static void * createObject() +{ + return new String(); +} + +INITIALIZE(String) +{ + Object::registerObjectConstructor("mailcore::String", &createObject); + + UChar chars_160[1] = {160}; + s_unicode160 = new String(chars_160, 1); + UChar chars_133[1] = {133}; + s_unicode133 = new String(chars_133, 1); + UChar chars_2028[1] = {0x2028}; + s_unicode2028 = new String(chars_2028, 1); +} diff --git a/src/core/basetypes/MCValue.cc b/src/core/basetypes/MCValue.cc deleted file mode 100644 index 7f12db36..00000000 --- a/src/core/basetypes/MCValue.cc +++ /dev/null @@ -1,459 +0,0 @@ -#include "MCValue.h" -#include "MCValuePrivate.h" - -#include -#include - -#include "MCDefines.h" -#include "MCString.h" -#include "MCHash.h" -#include "MCUtils.h" -#include "MCHashMap.h" -#include "MCAssert.h" -#include "MCData.h" - -using namespace mailcore; - -Value::Value() -{ - mType = VALUE_TYPE_NONE; - memset(&mValue, 0, sizeof(mValue)); -} - -Value::Value(Value * other) -{ - memcpy(&mValue, &other->mValue, sizeof(mValue)); - mType = other->mType; - if (mType == VALUE_TYPE_DATA_VALUE) { - mValue.dataValue.data = (char *) malloc(mValue.dataValue.length); - memcpy(mValue.dataValue.data, other->mValue.dataValue.data, mValue.dataValue.length); - } -} - -Value::~Value() -{ - if (mType == VALUE_TYPE_DATA_VALUE) { - free(mValue.dataValue.data); - } -} - -String * Value::description() -{ - switch (mType) { - case VALUE_TYPE_BOOL_VALUE: - if (mValue.boolValue) { - return MCSTR("true"); - } - else { - return MCSTR("false"); - } - case VALUE_TYPE_CHAR_VALUE: - return String::stringWithUTF8Format("%i", (int) mValue.charValue); - case VALUE_TYPE_UNSIGNED_CHAR_VALUE: - return String::stringWithUTF8Format("%u", (unsigned int) mValue.unsignedCharValue); - case VALUE_TYPE_SHORT_VALUE: - return String::stringWithUTF8Format("%i", (int) mValue.shortValue); - case VALUE_TYPE_UNSIGNED_SHORT_VALUE: - return String::stringWithUTF8Format("%u", (unsigned int) mValue.unsignedShortValue); - case VALUE_TYPE_INT_VALUE: - return String::stringWithUTF8Format("%i", mValue.intValue); - case VALUE_TYPE_UNSIGNED_INT_VALUE: - return String::stringWithUTF8Format("%u", mValue.unsignedIntValue); - case VALUE_TYPE_LONG_VALUE: - return String::stringWithUTF8Format("%li", mValue.longValue); - case VALUE_TYPE_UNSIGNED_LONG_VALUE: - return String::stringWithUTF8Format("%lu", mValue.unsignedLongValue); - case VALUE_TYPE_LONG_LONG_VALUE: - return String::stringWithUTF8Format("%lli", mValue.longLongValue); - case VALUE_TYPE_UNSIGNED_LONG_LONG_VALUE: - return String::stringWithUTF8Format("%llu", mValue.unsignedLongLongValue); - case VALUE_TYPE_FLOAT_VALUE: - return String::stringWithUTF8Format("%f", (double) mValue.floatValue); - case VALUE_TYPE_DOUBLE_VALUE: - return String::stringWithUTF8Format("%f", mValue.doubleValue); - case VALUE_TYPE_POINTER_VALUE: - return String::stringWithUTF8Format("%p", mValue.pointerValue); - case VALUE_TYPE_DATA_VALUE: - return String::stringWithUTF8Format("", this); - default: - MCAssert(0); - return NULL; - } -} - -bool Value::isEqual(Object * otherObject) -{ - Value * otherValue = (Value *) otherObject; - if (otherValue->mType != mType) - return false; - if (mType == VALUE_TYPE_DATA_VALUE) { - if (mValue.dataValue.length != otherValue->mValue.dataValue.length) - return false; - if (memcmp(&otherValue->mValue.dataValue.data, &mValue.dataValue.data, mValue.dataValue.length) != 0) - return false; - } - else { - if (memcmp(&otherValue->mValue, &mValue, sizeof(mValue)) != 0) - return false; - } - return true; -} - -unsigned int Value::hash() -{ - return hashCompute((const char *) &mValue, sizeof(mValue)); -} - -Object * Value::copy() -{ - return new Value(this); -} - -Value * Value::valueWithBoolValue(bool value) -{ - Value * result = new Value(); - result->mType = VALUE_TYPE_BOOL_VALUE; - result->mValue.boolValue = value; - return (Value *) result->autorelease(); -} - -Value * Value::valueWithCharValue(char value) -{ - Value * result = new Value(); - result->mType = VALUE_TYPE_CHAR_VALUE; - result->mValue.charValue = value; - return (Value *) result->autorelease(); -} - -Value * Value::valueWithUnsignedCharValue(unsigned char value) -{ - Value * result = new Value(); - result->mType = VALUE_TYPE_UNSIGNED_CHAR_VALUE; - result->mValue.unsignedCharValue = value; - return (Value *) result->autorelease(); -} - -/////////////////////// - -Value * Value::valueWithIntValue(int value) -{ - Value * result = new Value(); - result->mType = VALUE_TYPE_INT_VALUE; - result->mValue.intValue = value; - return (Value *) result->autorelease(); -} - -Value * Value::valueWithUnsignedIntValue(unsigned int value) -{ - Value * result = new Value(); - result->mType = VALUE_TYPE_UNSIGNED_INT_VALUE; - result->mValue.unsignedIntValue = value; - return (Value *) result->autorelease(); -} - -Value * Value::valueWithLongValue(long value) -{ - Value * result = new Value(); - result->mType = VALUE_TYPE_LONG_VALUE; - result->mValue.longValue = value; - return (Value *) result->autorelease(); -} - -Value * Value::valueWithUnsignedLongValue(unsigned long value) -{ - Value * result = new Value(); - result->mType = VALUE_TYPE_UNSIGNED_LONG_VALUE; - result->mValue.unsignedLongValue = value; - return (Value *) result->autorelease(); -} - -Value * Value::valueWithLongLongValue(long long value) -{ - Value * result = new Value(); - result->mType = VALUE_TYPE_LONG_LONG_VALUE; - result->mValue.longLongValue = value; - return (Value *) result->autorelease(); -} - -Value * Value::valueWithUnsignedLongLongValue(unsigned long long value) -{ - Value * result = new Value(); - result->mType = VALUE_TYPE_UNSIGNED_LONG_LONG_VALUE; - result->mValue.unsignedLongLongValue = value; - return (Value *) result->autorelease(); -} - -Value * Value::valueWithFloatValue(float value) -{ - Value * result = new Value(); - result->mType = VALUE_TYPE_FLOAT_VALUE; - result->mValue.floatValue = value; - return (Value *) result->autorelease(); -} - -Value * Value::valueWithDoubleValue(double value) -{ - Value * result = new Value(); - result->mType = VALUE_TYPE_DOUBLE_VALUE; - result->mValue.doubleValue = value; - return (Value *) result->autorelease(); -} - -Value * Value::valueWithPointerValue(void * value) -{ - Value * result = new Value(); - result->mType = VALUE_TYPE_POINTER_VALUE; - result->mValue.pointerValue = value; - return (Value *) result->autorelease(); -} - -Value * Value::valueWithData(const char * value, int length) -{ - Value * result = new Value(); - result->mType = VALUE_TYPE_DATA_VALUE; - result->mValue.dataValue.data = (char *) malloc(length); - memcpy(result->mValue.dataValue.data, value, length); - result->mValue.dataValue.length = length; - return (Value *) result->autorelease(); -} - -bool Value::boolValue() -{ - return mValue.boolValue; -} - -char Value::charValue() -{ - return mValue.charValue; -} - -unsigned char Value::unsignedCharValue() -{ - return mValue.unsignedCharValue; -} - -short Value::shortValue() -{ - return mValue.shortValue; -} - -unsigned short Value::unsignedShortValue() -{ - return mValue.unsignedShortValue; -} - -int Value::intValue() -{ - return mValue.intValue; -} - -unsigned int Value::unsignedIntValue() -{ - return mValue.unsignedIntValue; -} - -long Value::longValue() -{ - return mValue.longValue; -} - -unsigned long Value::unsignedLongValue() -{ - return mValue.unsignedLongValue; -} - -long long Value::longLongValue() -{ - return mValue.longLongValue; -} - -unsigned long long Value::unsignedLongLongValue() -{ - return mValue.unsignedLongLongValue; -} - -float Value::floatValue() -{ - return mValue.floatValue; -} - -double Value::doubleValue() -{ - return mValue.doubleValue; -} - -void * Value::pointerValue() -{ - return mValue.pointerValue; -} - -void Value::dataValue(const char ** p_value, int * p_length) -{ - * p_value = mValue.dataValue.data; - * p_length = mValue.dataValue.length; -} - -int Value::type() -{ - return mType; -} - -HashMap * Value::serializable() -{ - HashMap * result = Object::serializable(); - String * type = NULL; - String * value = NULL; - switch (mType) { - case VALUE_TYPE_BOOL_VALUE: - type = MCSTR("b"); - if (mValue.boolValue) { - value = MCSTR("1"); - } - else { - value = MCSTR("0"); - } - break; - case VALUE_TYPE_CHAR_VALUE: - type = MCSTR("c"); - value = String::stringWithUTF8Format("%i", (int) mValue.charValue); - break; - case VALUE_TYPE_UNSIGNED_CHAR_VALUE: - type = MCSTR("uc"); - value = String::stringWithUTF8Format("%u", (unsigned int) mValue.unsignedCharValue); - break; - case VALUE_TYPE_SHORT_VALUE: - type = MCSTR("s"); - value = String::stringWithUTF8Format("%i", (int) mValue.shortValue); - break; - case VALUE_TYPE_UNSIGNED_SHORT_VALUE: - type = MCSTR("us"); - value = String::stringWithUTF8Format("%u", (unsigned int) mValue.unsignedShortValue); - break; - case VALUE_TYPE_INT_VALUE: - type = MCSTR("i"); - value = String::stringWithUTF8Format("%i", mValue.intValue); - break; - case VALUE_TYPE_UNSIGNED_INT_VALUE: - type = MCSTR("ui"); - value = String::stringWithUTF8Format("%u", mValue.unsignedIntValue); - break; - case VALUE_TYPE_LONG_VALUE: - type = MCSTR("l"); - value = String::stringWithUTF8Format("%li", mValue.longValue); - break; - case VALUE_TYPE_UNSIGNED_LONG_VALUE: - type = MCSTR("ul"); - value = String::stringWithUTF8Format("%lu", mValue.unsignedLongValue); - break; - case VALUE_TYPE_LONG_LONG_VALUE: - type = MCSTR("ll"); - value = String::stringWithUTF8Format("%lli", mValue.longLongValue); - break; - case VALUE_TYPE_UNSIGNED_LONG_LONG_VALUE: - type = MCSTR("ull"); - value = String::stringWithUTF8Format("%llu", mValue.unsignedLongLongValue); - break; - case VALUE_TYPE_FLOAT_VALUE: - type = MCSTR("f"); - value = String::stringWithUTF8Format("%f", (double) mValue.floatValue); - break; - case VALUE_TYPE_DOUBLE_VALUE: - type = MCSTR("lf"); - value = String::stringWithUTF8Format("%f", mValue.doubleValue); - break; - case VALUE_TYPE_POINTER_VALUE: - MCAssert(0); - break; - case VALUE_TYPE_DATA_VALUE: - type = MCSTR("data"); - value = Data::dataWithBytes(mValue.dataValue.data, mValue.dataValue.length)->base64String(); - break; - default: - MCAssert(0); - break; - } - result->setObjectForKey(MCSTR("type"), type); - result->setObjectForKey(MCSTR("value"), value); - return result; -} - -void Value::importSerializable(HashMap * serializable) -{ - String * type = (String *) serializable->objectForKey(MCSTR("type")); - String * value = (String *) serializable->objectForKey(MCSTR("value")); - if (type->isEqual(MCSTR("b"))) { - mType = VALUE_TYPE_BOOL_VALUE; - mValue.boolValue = (bool) value->intValue(); - } - else if (type->isEqual(MCSTR("c"))) { - mType = VALUE_TYPE_CHAR_VALUE; - mValue.charValue = value->intValue(); - } - else if (type->isEqual(MCSTR("uc"))) { - mType = VALUE_TYPE_UNSIGNED_CHAR_VALUE;; - mValue.unsignedCharValue = value->unsignedIntValue(); - } - else if (type->isEqual(MCSTR("s"))) { - mType = VALUE_TYPE_SHORT_VALUE; - mValue.shortValue = value->intValue(); - } - else if (type->isEqual(MCSTR("us"))) { - mType = VALUE_TYPE_UNSIGNED_SHORT_VALUE; - mValue.unsignedShortValue = value->unsignedIntValue(); - } - else if (type->isEqual(MCSTR("i"))) { - mType = VALUE_TYPE_INT_VALUE; - mValue.intValue = value->intValue(); - } - else if (type->isEqual(MCSTR("ui"))) { - mType = VALUE_TYPE_UNSIGNED_INT_VALUE; - mValue.unsignedIntValue = value->unsignedIntValue(); - } - else if (type->isEqual(MCSTR("l"))) { - mType = VALUE_TYPE_LONG_VALUE; - mValue.longValue = value->unsignedIntValue(); - } - else if (type->isEqual(MCSTR("ul"))) { - mType = VALUE_TYPE_UNSIGNED_INT_VALUE; - mValue.unsignedLongValue = value->unsignedIntValue(); - } - else if (type->isEqual(MCSTR("ll"))) { - mType = VALUE_TYPE_LONG_LONG_VALUE; - mValue.longLongValue = value->longLongValue(); - } - else if (type->isEqual(MCSTR("ull"))) { - mType = VALUE_TYPE_UNSIGNED_LONG_LONG_VALUE; - mValue.unsignedLongLongValue = value->unsignedLongLongValue(); - } - else if (type->isEqual(MCSTR("f"))) { - mType = VALUE_TYPE_FLOAT_VALUE; - mValue.floatValue = value->doubleValue(); - } - else if (type->isEqual(MCSTR("lf"))) { - mType = VALUE_TYPE_DOUBLE_VALUE; - mValue.doubleValue = value->doubleValue(); - } - else if (type->isEqual(MCSTR("p"))) { - MCAssert(0); - } - else if (type->isEqual(MCSTR("data"))) { - mType = VALUE_TYPE_DATA_VALUE; - Data * data = value->decodedBase64Data(); - mValue.dataValue.data = (char *) malloc(data->length()); - memcpy(mValue.dataValue.data, data->bytes(), data->length()); - mValue.dataValue.length = data->length(); - } - else { - MCAssert(0); - } -} - -void * Value::createObject() -{ - return new Value(); -} - -INITIALIZE(Value) -{ - Object::registerObjectConstructor("mailcore::Value", &Value::createObject); -} diff --git a/src/core/basetypes/MCValue.cpp b/src/core/basetypes/MCValue.cpp new file mode 100644 index 00000000..7f12db36 --- /dev/null +++ b/src/core/basetypes/MCValue.cpp @@ -0,0 +1,459 @@ +#include "MCValue.h" +#include "MCValuePrivate.h" + +#include +#include + +#include "MCDefines.h" +#include "MCString.h" +#include "MCHash.h" +#include "MCUtils.h" +#include "MCHashMap.h" +#include "MCAssert.h" +#include "MCData.h" + +using namespace mailcore; + +Value::Value() +{ + mType = VALUE_TYPE_NONE; + memset(&mValue, 0, sizeof(mValue)); +} + +Value::Value(Value * other) +{ + memcpy(&mValue, &other->mValue, sizeof(mValue)); + mType = other->mType; + if (mType == VALUE_TYPE_DATA_VALUE) { + mValue.dataValue.data = (char *) malloc(mValue.dataValue.length); + memcpy(mValue.dataValue.data, other->mValue.dataValue.data, mValue.dataValue.length); + } +} + +Value::~Value() +{ + if (mType == VALUE_TYPE_DATA_VALUE) { + free(mValue.dataValue.data); + } +} + +String * Value::description() +{ + switch (mType) { + case VALUE_TYPE_BOOL_VALUE: + if (mValue.boolValue) { + return MCSTR("true"); + } + else { + return MCSTR("false"); + } + case VALUE_TYPE_CHAR_VALUE: + return String::stringWithUTF8Format("%i", (int) mValue.charValue); + case VALUE_TYPE_UNSIGNED_CHAR_VALUE: + return String::stringWithUTF8Format("%u", (unsigned int) mValue.unsignedCharValue); + case VALUE_TYPE_SHORT_VALUE: + return String::stringWithUTF8Format("%i", (int) mValue.shortValue); + case VALUE_TYPE_UNSIGNED_SHORT_VALUE: + return String::stringWithUTF8Format("%u", (unsigned int) mValue.unsignedShortValue); + case VALUE_TYPE_INT_VALUE: + return String::stringWithUTF8Format("%i", mValue.intValue); + case VALUE_TYPE_UNSIGNED_INT_VALUE: + return String::stringWithUTF8Format("%u", mValue.unsignedIntValue); + case VALUE_TYPE_LONG_VALUE: + return String::stringWithUTF8Format("%li", mValue.longValue); + case VALUE_TYPE_UNSIGNED_LONG_VALUE: + return String::stringWithUTF8Format("%lu", mValue.unsignedLongValue); + case VALUE_TYPE_LONG_LONG_VALUE: + return String::stringWithUTF8Format("%lli", mValue.longLongValue); + case VALUE_TYPE_UNSIGNED_LONG_LONG_VALUE: + return String::stringWithUTF8Format("%llu", mValue.unsignedLongLongValue); + case VALUE_TYPE_FLOAT_VALUE: + return String::stringWithUTF8Format("%f", (double) mValue.floatValue); + case VALUE_TYPE_DOUBLE_VALUE: + return String::stringWithUTF8Format("%f", mValue.doubleValue); + case VALUE_TYPE_POINTER_VALUE: + return String::stringWithUTF8Format("%p", mValue.pointerValue); + case VALUE_TYPE_DATA_VALUE: + return String::stringWithUTF8Format("", this); + default: + MCAssert(0); + return NULL; + } +} + +bool Value::isEqual(Object * otherObject) +{ + Value * otherValue = (Value *) otherObject; + if (otherValue->mType != mType) + return false; + if (mType == VALUE_TYPE_DATA_VALUE) { + if (mValue.dataValue.length != otherValue->mValue.dataValue.length) + return false; + if (memcmp(&otherValue->mValue.dataValue.data, &mValue.dataValue.data, mValue.dataValue.length) != 0) + return false; + } + else { + if (memcmp(&otherValue->mValue, &mValue, sizeof(mValue)) != 0) + return false; + } + return true; +} + +unsigned int Value::hash() +{ + return hashCompute((const char *) &mValue, sizeof(mValue)); +} + +Object * Value::copy() +{ + return new Value(this); +} + +Value * Value::valueWithBoolValue(bool value) +{ + Value * result = new Value(); + result->mType = VALUE_TYPE_BOOL_VALUE; + result->mValue.boolValue = value; + return (Value *) result->autorelease(); +} + +Value * Value::valueWithCharValue(char value) +{ + Value * result = new Value(); + result->mType = VALUE_TYPE_CHAR_VALUE; + result->mValue.charValue = value; + return (Value *) result->autorelease(); +} + +Value * Value::valueWithUnsignedCharValue(unsigned char value) +{ + Value * result = new Value(); + result->mType = VALUE_TYPE_UNSIGNED_CHAR_VALUE; + result->mValue.unsignedCharValue = value; + return (Value *) result->autorelease(); +} + +/////////////////////// + +Value * Value::valueWithIntValue(int value) +{ + Value * result = new Value(); + result->mType = VALUE_TYPE_INT_VALUE; + result->mValue.intValue = value; + return (Value *) result->autorelease(); +} + +Value * Value::valueWithUnsignedIntValue(unsigned int value) +{ + Value * result = new Value(); + result->mType = VALUE_TYPE_UNSIGNED_INT_VALUE; + result->mValue.unsignedIntValue = value; + return (Value *) result->autorelease(); +} + +Value * Value::valueWithLongValue(long value) +{ + Value * result = new Value(); + result->mType = VALUE_TYPE_LONG_VALUE; + result->mValue.longValue = value; + return (Value *) result->autorelease(); +} + +Value * Value::valueWithUnsignedLongValue(unsigned long value) +{ + Value * result = new Value(); + result->mType = VALUE_TYPE_UNSIGNED_LONG_VALUE; + result->mValue.unsignedLongValue = value; + return (Value *) result->autorelease(); +} + +Value * Value::valueWithLongLongValue(long long value) +{ + Value * result = new Value(); + result->mType = VALUE_TYPE_LONG_LONG_VALUE; + result->mValue.longLongValue = value; + return (Value *) result->autorelease(); +} + +Value * Value::valueWithUnsignedLongLongValue(unsigned long long value) +{ + Value * result = new Value(); + result->mType = VALUE_TYPE_UNSIGNED_LONG_LONG_VALUE; + result->mValue.unsignedLongLongValue = value; + return (Value *) result->autorelease(); +} + +Value * Value::valueWithFloatValue(float value) +{ + Value * result = new Value(); + result->mType = VALUE_TYPE_FLOAT_VALUE; + result->mValue.floatValue = value; + return (Value *) result->autorelease(); +} + +Value * Value::valueWithDoubleValue(double value) +{ + Value * result = new Value(); + result->mType = VALUE_TYPE_DOUBLE_VALUE; + result->mValue.doubleValue = value; + return (Value *) result->autorelease(); +} + +Value * Value::valueWithPointerValue(void * value) +{ + Value * result = new Value(); + result->mType = VALUE_TYPE_POINTER_VALUE; + result->mValue.pointerValue = value; + return (Value *) result->autorelease(); +} + +Value * Value::valueWithData(const char * value, int length) +{ + Value * result = new Value(); + result->mType = VALUE_TYPE_DATA_VALUE; + result->mValue.dataValue.data = (char *) malloc(length); + memcpy(result->mValue.dataValue.data, value, length); + result->mValue.dataValue.length = length; + return (Value *) result->autorelease(); +} + +bool Value::boolValue() +{ + return mValue.boolValue; +} + +char Value::charValue() +{ + return mValue.charValue; +} + +unsigned char Value::unsignedCharValue() +{ + return mValue.unsignedCharValue; +} + +short Value::shortValue() +{ + return mValue.shortValue; +} + +unsigned short Value::unsignedShortValue() +{ + return mValue.unsignedShortValue; +} + +int Value::intValue() +{ + return mValue.intValue; +} + +unsigned int Value::unsignedIntValue() +{ + return mValue.unsignedIntValue; +} + +long Value::longValue() +{ + return mValue.longValue; +} + +unsigned long Value::unsignedLongValue() +{ + return mValue.unsignedLongValue; +} + +long long Value::longLongValue() +{ + return mValue.longLongValue; +} + +unsigned long long Value::unsignedLongLongValue() +{ + return mValue.unsignedLongLongValue; +} + +float Value::floatValue() +{ + return mValue.floatValue; +} + +double Value::doubleValue() +{ + return mValue.doubleValue; +} + +void * Value::pointerValue() +{ + return mValue.pointerValue; +} + +void Value::dataValue(const char ** p_value, int * p_length) +{ + * p_value = mValue.dataValue.data; + * p_length = mValue.dataValue.length; +} + +int Value::type() +{ + return mType; +} + +HashMap * Value::serializable() +{ + HashMap * result = Object::serializable(); + String * type = NULL; + String * value = NULL; + switch (mType) { + case VALUE_TYPE_BOOL_VALUE: + type = MCSTR("b"); + if (mValue.boolValue) { + value = MCSTR("1"); + } + else { + value = MCSTR("0"); + } + break; + case VALUE_TYPE_CHAR_VALUE: + type = MCSTR("c"); + value = String::stringWithUTF8Format("%i", (int) mValue.charValue); + break; + case VALUE_TYPE_UNSIGNED_CHAR_VALUE: + type = MCSTR("uc"); + value = String::stringWithUTF8Format("%u", (unsigned int) mValue.unsignedCharValue); + break; + case VALUE_TYPE_SHORT_VALUE: + type = MCSTR("s"); + value = String::stringWithUTF8Format("%i", (int) mValue.shortValue); + break; + case VALUE_TYPE_UNSIGNED_SHORT_VALUE: + type = MCSTR("us"); + value = String::stringWithUTF8Format("%u", (unsigned int) mValue.unsignedShortValue); + break; + case VALUE_TYPE_INT_VALUE: + type = MCSTR("i"); + value = String::stringWithUTF8Format("%i", mValue.intValue); + break; + case VALUE_TYPE_UNSIGNED_INT_VALUE: + type = MCSTR("ui"); + value = String::stringWithUTF8Format("%u", mValue.unsignedIntValue); + break; + case VALUE_TYPE_LONG_VALUE: + type = MCSTR("l"); + value = String::stringWithUTF8Format("%li", mValue.longValue); + break; + case VALUE_TYPE_UNSIGNED_LONG_VALUE: + type = MCSTR("ul"); + value = String::stringWithUTF8Format("%lu", mValue.unsignedLongValue); + break; + case VALUE_TYPE_LONG_LONG_VALUE: + type = MCSTR("ll"); + value = String::stringWithUTF8Format("%lli", mValue.longLongValue); + break; + case VALUE_TYPE_UNSIGNED_LONG_LONG_VALUE: + type = MCSTR("ull"); + value = String::stringWithUTF8Format("%llu", mValue.unsignedLongLongValue); + break; + case VALUE_TYPE_FLOAT_VALUE: + type = MCSTR("f"); + value = String::stringWithUTF8Format("%f", (double) mValue.floatValue); + break; + case VALUE_TYPE_DOUBLE_VALUE: + type = MCSTR("lf"); + value = String::stringWithUTF8Format("%f", mValue.doubleValue); + break; + case VALUE_TYPE_POINTER_VALUE: + MCAssert(0); + break; + case VALUE_TYPE_DATA_VALUE: + type = MCSTR("data"); + value = Data::dataWithBytes(mValue.dataValue.data, mValue.dataValue.length)->base64String(); + break; + default: + MCAssert(0); + break; + } + result->setObjectForKey(MCSTR("type"), type); + result->setObjectForKey(MCSTR("value"), value); + return result; +} + +void Value::importSerializable(HashMap * serializable) +{ + String * type = (String *) serializable->objectForKey(MCSTR("type")); + String * value = (String *) serializable->objectForKey(MCSTR("value")); + if (type->isEqual(MCSTR("b"))) { + mType = VALUE_TYPE_BOOL_VALUE; + mValue.boolValue = (bool) value->intValue(); + } + else if (type->isEqual(MCSTR("c"))) { + mType = VALUE_TYPE_CHAR_VALUE; + mValue.charValue = value->intValue(); + } + else if (type->isEqual(MCSTR("uc"))) { + mType = VALUE_TYPE_UNSIGNED_CHAR_VALUE;; + mValue.unsignedCharValue = value->unsignedIntValue(); + } + else if (type->isEqual(MCSTR("s"))) { + mType = VALUE_TYPE_SHORT_VALUE; + mValue.shortValue = value->intValue(); + } + else if (type->isEqual(MCSTR("us"))) { + mType = VALUE_TYPE_UNSIGNED_SHORT_VALUE; + mValue.unsignedShortValue = value->unsignedIntValue(); + } + else if (type->isEqual(MCSTR("i"))) { + mType = VALUE_TYPE_INT_VALUE; + mValue.intValue = value->intValue(); + } + else if (type->isEqual(MCSTR("ui"))) { + mType = VALUE_TYPE_UNSIGNED_INT_VALUE; + mValue.unsignedIntValue = value->unsignedIntValue(); + } + else if (type->isEqual(MCSTR("l"))) { + mType = VALUE_TYPE_LONG_VALUE; + mValue.longValue = value->unsignedIntValue(); + } + else if (type->isEqual(MCSTR("ul"))) { + mType = VALUE_TYPE_UNSIGNED_INT_VALUE; + mValue.unsignedLongValue = value->unsignedIntValue(); + } + else if (type->isEqual(MCSTR("ll"))) { + mType = VALUE_TYPE_LONG_LONG_VALUE; + mValue.longLongValue = value->longLongValue(); + } + else if (type->isEqual(MCSTR("ull"))) { + mType = VALUE_TYPE_UNSIGNED_LONG_LONG_VALUE; + mValue.unsignedLongLongValue = value->unsignedLongLongValue(); + } + else if (type->isEqual(MCSTR("f"))) { + mType = VALUE_TYPE_FLOAT_VALUE; + mValue.floatValue = value->doubleValue(); + } + else if (type->isEqual(MCSTR("lf"))) { + mType = VALUE_TYPE_DOUBLE_VALUE; + mValue.doubleValue = value->doubleValue(); + } + else if (type->isEqual(MCSTR("p"))) { + MCAssert(0); + } + else if (type->isEqual(MCSTR("data"))) { + mType = VALUE_TYPE_DATA_VALUE; + Data * data = value->decodedBase64Data(); + mValue.dataValue.data = (char *) malloc(data->length()); + memcpy(mValue.dataValue.data, data->bytes(), data->length()); + mValue.dataValue.length = data->length(); + } + else { + MCAssert(0); + } +} + +void * Value::createObject() +{ + return new Value(); +} + +INITIALIZE(Value) +{ + Object::registerObjectConstructor("mailcore::Value", &Value::createObject); +} diff --git a/src/core/imap/MCIMAPFolder.cc b/src/core/imap/MCIMAPFolder.cc deleted file mode 100644 index 513097e2..00000000 --- a/src/core/imap/MCIMAPFolder.cc +++ /dev/null @@ -1,70 +0,0 @@ -#include "MCIMAPFolder.h" - -using namespace mailcore; - -void IMAPFolder::init() -{ - mPath = NULL; - mDelimiter = 0; - mFlags = IMAPFolderFlagNone; -} - -IMAPFolder::IMAPFolder() -{ - init(); -} - -IMAPFolder::IMAPFolder(IMAPFolder * other) -{ - init(); - setPath(other->path()); - setDelimiter(other->delimiter()); - setFlags(other->flags()); -} - -IMAPFolder::~IMAPFolder() -{ - MC_SAFE_RELEASE(mPath); -} - -Object * IMAPFolder::copy() -{ - return new IMAPFolder(this); -} - -void IMAPFolder::setPath(String * path) -{ - MC_SAFE_REPLACE_COPY(String, mPath, path); -} - -String * IMAPFolder::path() -{ - return mPath; -} - -void IMAPFolder::setDelimiter(char delimiter) -{ - mDelimiter = delimiter; -} - -char IMAPFolder::delimiter() -{ - return mDelimiter; -} - -void IMAPFolder::setFlags(IMAPFolderFlag flags) -{ - mFlags = flags; -} - -IMAPFolderFlag IMAPFolder::flags() -{ - return mFlags; -} - -String * IMAPFolder::description() -{ - String * result = String::string(); - result->appendUTF8Format("<%s:%p %s>", className()->UTF8Characters(), this, MCUTF8(mPath)); - return result; -} diff --git a/src/core/imap/MCIMAPFolder.cpp b/src/core/imap/MCIMAPFolder.cpp new file mode 100644 index 00000000..513097e2 --- /dev/null +++ b/src/core/imap/MCIMAPFolder.cpp @@ -0,0 +1,70 @@ +#include "MCIMAPFolder.h" + +using namespace mailcore; + +void IMAPFolder::init() +{ + mPath = NULL; + mDelimiter = 0; + mFlags = IMAPFolderFlagNone; +} + +IMAPFolder::IMAPFolder() +{ + init(); +} + +IMAPFolder::IMAPFolder(IMAPFolder * other) +{ + init(); + setPath(other->path()); + setDelimiter(other->delimiter()); + setFlags(other->flags()); +} + +IMAPFolder::~IMAPFolder() +{ + MC_SAFE_RELEASE(mPath); +} + +Object * IMAPFolder::copy() +{ + return new IMAPFolder(this); +} + +void IMAPFolder::setPath(String * path) +{ + MC_SAFE_REPLACE_COPY(String, mPath, path); +} + +String * IMAPFolder::path() +{ + return mPath; +} + +void IMAPFolder::setDelimiter(char delimiter) +{ + mDelimiter = delimiter; +} + +char IMAPFolder::delimiter() +{ + return mDelimiter; +} + +void IMAPFolder::setFlags(IMAPFolderFlag flags) +{ + mFlags = flags; +} + +IMAPFolderFlag IMAPFolder::flags() +{ + return mFlags; +} + +String * IMAPFolder::description() +{ + String * result = String::string(); + result->appendUTF8Format("<%s:%p %s>", className()->UTF8Characters(), this, MCUTF8(mPath)); + return result; +} diff --git a/src/core/imap/MCIMAPFolderStatus.cc b/src/core/imap/MCIMAPFolderStatus.cc deleted file mode 100644 index d2cb2281..00000000 --- a/src/core/imap/MCIMAPFolderStatus.cc +++ /dev/null @@ -1,122 +0,0 @@ -// -// MCIMAPFolderStatus.cc -// mailcore2 -// -// Created by Sebastian on 6/11/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPFolderStatus.h" - -using namespace mailcore; - -void IMAPFolderStatus::init() -{ - mUnseenCount = 0; - mMessageCount = 0; - mRecentCount = 0; - mUidNext = 0; - mUidValidity = 0; - mHighestModSeqValue = 0; -} - -IMAPFolderStatus::IMAPFolderStatus() -{ - init(); -} - - -IMAPFolderStatus::IMAPFolderStatus(IMAPFolderStatus * other) -{ - init(); - setUnseenCount(other->unseenCount()); - setMessageCount(other->messageCount()); - setRecentCount(other->recentCount()); - setUidNext(other->uidNext()); - setUidValidity(other->uidValidity()); - setHighestModSeqValue(other->highestModSeqValue()); -} - -IMAPFolderStatus::~IMAPFolderStatus() -{ -} - -Object * IMAPFolderStatus::copy() -{ - return new IMAPFolderStatus(this); -} - -void IMAPFolderStatus::setUnseenCount(uint32_t unseen) -{ - mUnseenCount = unseen; -} - -uint32_t IMAPFolderStatus::unseenCount() -{ - return mUnseenCount; -} - -void IMAPFolderStatus::setMessageCount(uint32_t messages) -{ - mMessageCount = messages; -} - -uint32_t IMAPFolderStatus::messageCount() -{ - return mMessageCount; -} - -void IMAPFolderStatus::setRecentCount(uint32_t recent) -{ - mRecentCount = recent; -} - -uint32_t IMAPFolderStatus::recentCount() -{ - return mRecentCount; -} - -void IMAPFolderStatus::setUidNext(uint32_t uidNext) -{ - mUidNext = uidNext; -} - -uint32_t IMAPFolderStatus::uidNext() -{ - return mUidNext; -} - -void IMAPFolderStatus::setUidValidity(uint32_t uidValidity) -{ - mUidValidity = uidValidity; -} - -uint32_t IMAPFolderStatus::uidValidity() -{ - return mUidValidity; -} - -void IMAPFolderStatus::setHighestModSeqValue(uint64_t highestModSeqValue) -{ - mHighestModSeqValue = highestModSeqValue; -} - -uint64_t IMAPFolderStatus::highestModSeqValue() -{ - return mHighestModSeqValue; -} - -String * IMAPFolderStatus::description() -{ - String * result = String::string(); - result->appendUTF8Format("<%s:%p msg_count: %u, unseen_count: %u, recent_count: %u, uid_next: %u, uid_validity: %u, highestmodseqvalue :%llu>", - className()->UTF8Characters(), - this, - (unsigned int) messageCount(), - (unsigned int) unseenCount(), - (unsigned int) recentCount(), - (unsigned int) uidNext(), - (unsigned int) uidValidity(), - (unsigned long long) highestModSeqValue()); - return result; -} diff --git a/src/core/imap/MCIMAPFolderStatus.cpp b/src/core/imap/MCIMAPFolderStatus.cpp new file mode 100644 index 00000000..d2cb2281 --- /dev/null +++ b/src/core/imap/MCIMAPFolderStatus.cpp @@ -0,0 +1,122 @@ +// +// MCIMAPFolderStatus.cc +// mailcore2 +// +// Created by Sebastian on 6/11/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPFolderStatus.h" + +using namespace mailcore; + +void IMAPFolderStatus::init() +{ + mUnseenCount = 0; + mMessageCount = 0; + mRecentCount = 0; + mUidNext = 0; + mUidValidity = 0; + mHighestModSeqValue = 0; +} + +IMAPFolderStatus::IMAPFolderStatus() +{ + init(); +} + + +IMAPFolderStatus::IMAPFolderStatus(IMAPFolderStatus * other) +{ + init(); + setUnseenCount(other->unseenCount()); + setMessageCount(other->messageCount()); + setRecentCount(other->recentCount()); + setUidNext(other->uidNext()); + setUidValidity(other->uidValidity()); + setHighestModSeqValue(other->highestModSeqValue()); +} + +IMAPFolderStatus::~IMAPFolderStatus() +{ +} + +Object * IMAPFolderStatus::copy() +{ + return new IMAPFolderStatus(this); +} + +void IMAPFolderStatus::setUnseenCount(uint32_t unseen) +{ + mUnseenCount = unseen; +} + +uint32_t IMAPFolderStatus::unseenCount() +{ + return mUnseenCount; +} + +void IMAPFolderStatus::setMessageCount(uint32_t messages) +{ + mMessageCount = messages; +} + +uint32_t IMAPFolderStatus::messageCount() +{ + return mMessageCount; +} + +void IMAPFolderStatus::setRecentCount(uint32_t recent) +{ + mRecentCount = recent; +} + +uint32_t IMAPFolderStatus::recentCount() +{ + return mRecentCount; +} + +void IMAPFolderStatus::setUidNext(uint32_t uidNext) +{ + mUidNext = uidNext; +} + +uint32_t IMAPFolderStatus::uidNext() +{ + return mUidNext; +} + +void IMAPFolderStatus::setUidValidity(uint32_t uidValidity) +{ + mUidValidity = uidValidity; +} + +uint32_t IMAPFolderStatus::uidValidity() +{ + return mUidValidity; +} + +void IMAPFolderStatus::setHighestModSeqValue(uint64_t highestModSeqValue) +{ + mHighestModSeqValue = highestModSeqValue; +} + +uint64_t IMAPFolderStatus::highestModSeqValue() +{ + return mHighestModSeqValue; +} + +String * IMAPFolderStatus::description() +{ + String * result = String::string(); + result->appendUTF8Format("<%s:%p msg_count: %u, unseen_count: %u, recent_count: %u, uid_next: %u, uid_validity: %u, highestmodseqvalue :%llu>", + className()->UTF8Characters(), + this, + (unsigned int) messageCount(), + (unsigned int) unseenCount(), + (unsigned int) recentCount(), + (unsigned int) uidNext(), + (unsigned int) uidValidity(), + (unsigned long long) highestModSeqValue()); + return result; +} diff --git a/src/core/imap/MCIMAPIdentity.cc b/src/core/imap/MCIMAPIdentity.cc deleted file mode 100644 index 2e22d539..00000000 --- a/src/core/imap/MCIMAPIdentity.cc +++ /dev/null @@ -1,97 +0,0 @@ -// -// 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.cpp b/src/core/imap/MCIMAPIdentity.cpp new file mode 100644 index 00000000..2e22d539 --- /dev/null +++ b/src/core/imap/MCIMAPIdentity.cpp @@ -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/MCIMAPMessage.cc b/src/core/imap/MCIMAPMessage.cc deleted file mode 100644 index 430ecdaa..00000000 --- a/src/core/imap/MCIMAPMessage.cc +++ /dev/null @@ -1,324 +0,0 @@ -#include "MCIMAPMessage.h" - -#include "MCDefines.h" -#include "MCMessageHeader.h" -#include "MCIMAPPart.h" -#include "MCIMAPMessagePart.h" -#include "MCIMAPMultipart.h" -#include "MCHTMLRenderer.h" -#include "MCHTMLRendererCallback.h" - -using namespace mailcore; - -static AbstractPart * partForPartIDInPart(AbstractPart * part, String * partID); -static AbstractPart * partForPartIDInMultipart(AbstractMultipart * part, String * partID); -static AbstractPart * partForPartIDInMessagePart(AbstractMessagePart * part, String * partID); - -void IMAPMessage::init() -{ - mUid = 0; - mSequenceNumber = 0; - mFlags = MessageFlagNone; - mOriginalFlags = MessageFlagNone; - mCustomFlags = NULL; - mMainPart = NULL; - mGmailLabels = NULL; - mModSeqValue = 0; - mGmailThreadID = 0; - mGmailMessageID = 0; -} - -IMAPMessage::IMAPMessage() -{ - init(); -} - -IMAPMessage::IMAPMessage(IMAPMessage * other) : AbstractMessage(other) -{ - init(); - setUid(other->uid()); - setSequenceNumber(other->sequenceNumber()); - setFlags(other->flags()); - setOriginalFlags(other->originalFlags()); - setCustomFlags(other->customFlags()); - setMainPart((AbstractPart *) other->mainPart()->copy()->autorelease()); - setGmailLabels(other->gmailLabels()); - setGmailThreadID(other->gmailThreadID()); - setGmailMessageID(other->gmailMessageID()); -} - -IMAPMessage::~IMAPMessage() -{ - MC_SAFE_RELEASE(mMainPart); - MC_SAFE_RELEASE(mGmailLabels); - MC_SAFE_RELEASE(mCustomFlags); -} - -Object * IMAPMessage::copy() -{ - return new IMAPMessage(this); -} - -String * IMAPMessage::description() -{ - String * result = String::string(); - result->appendUTF8Format("<%s:%p %u %u\n", className()->UTF8Characters(), this, (unsigned int) uid(), (unsigned int) sequenceNumber()); - result->appendString(header()->description()); - if (mainPart() != NULL) { - result->appendString(mainPart()->description()); - result->appendUTF8Characters("\n"); - } - result->appendUTF8Characters(">"); - return result; -} - -uint32_t IMAPMessage::uid() -{ - return mUid; -} - -void IMAPMessage::setUid(uint32_t uid) -{ - mUid = uid; -} - -uint32_t IMAPMessage::sequenceNumber() -{ - return mSequenceNumber; -} - -void IMAPMessage::setSequenceNumber(uint32_t value) -{ - mSequenceNumber = value; -} - -uint32_t IMAPMessage::size() -{ - return mSize; -} - -void IMAPMessage::setSize(uint32_t size) -{ - mSize = size; -} - -void IMAPMessage::setFlags(MessageFlag flags) -{ - mFlags = flags; -} - -MessageFlag IMAPMessage::flags() -{ - return mFlags; -} - -void IMAPMessage::setOriginalFlags(MessageFlag flags) -{ - mOriginalFlags = flags; -} - -MessageFlag IMAPMessage::originalFlags() -{ - return mOriginalFlags; -} - -void IMAPMessage::setCustomFlags(Array * customFlags) -{ - MC_SAFE_REPLACE_COPY(Array, mCustomFlags, customFlags); -} - -Array * IMAPMessage::customFlags() -{ - return mCustomFlags; -} - -void IMAPMessage::setModSeqValue(uint64_t uid) -{ - mModSeqValue = uid; -} - -uint64_t IMAPMessage::modSeqValue() -{ - return mModSeqValue; -} - -void IMAPMessage::setMainPart(AbstractPart * mainPart) -{ - MC_SAFE_REPLACE_RETAIN(AbstractPart, mMainPart, mainPart); -} - -AbstractPart * IMAPMessage::mainPart() -{ - return mMainPart; -} - -void IMAPMessage::setGmailLabels(Array * labels) -{ - MC_SAFE_REPLACE_COPY(Array, mGmailLabels, labels); -} - -Array * IMAPMessage::gmailLabels() -{ - return mGmailLabels; -} - -void IMAPMessage::setGmailMessageID(uint64_t msgID) -{ - mGmailMessageID = msgID; -} - -uint64_t IMAPMessage::gmailMessageID() -{ - return mGmailMessageID; -} - -void IMAPMessage::setGmailThreadID(uint64_t threadID) -{ - mGmailThreadID = threadID; -} - -uint64_t IMAPMessage::gmailThreadID() -{ - return mGmailThreadID; -} - -AbstractPart * IMAPMessage::partForPartID(String * partID) -{ - return partForPartIDInPart(mainPart(), partID); -} - -static AbstractPart * partForPartIDInPart(AbstractPart * part, String * partID) -{ - switch (part->partType()) { - case PartTypeSingle: - if (partID->isEqual(((IMAPPart *) part)->partID())) { - return part; - } - return NULL; - case mailcore::PartTypeMultipartMixed: - case mailcore::PartTypeMultipartRelated: - case mailcore::PartTypeMultipartAlternative: - case mailcore::PartTypeMultipartSigned: - if (partID->isEqual(((IMAPMultipart *) part)->partID())) { - return part; - } - return partForPartIDInMultipart((AbstractMultipart *) part, partID); - case mailcore::PartTypeMessage: - if (partID->isEqual(((IMAPMessagePart *) part)->partID())) { - return part; - } - return partForPartIDInMessagePart((AbstractMessagePart *) part, partID); - default: - return NULL; - } -} - -static AbstractPart * partForPartIDInMessagePart(AbstractMessagePart * part, String * partID) -{ - return partForPartIDInPart(part->mainPart(), partID); -} - -static AbstractPart * partForPartIDInMultipart(AbstractMultipart * part, String * partID) -{ - for(unsigned int i = 0 ; i < part->parts()->count() ; i ++) { - mailcore::AbstractPart * subpart = (mailcore::AbstractPart *) part->parts()->objectAtIndex(i); - mailcore::AbstractPart * result = partForPartIDInPart(subpart, partID); - if (result != NULL) - return result; - } - return NULL; -} - -AbstractPart * IMAPMessage::partForContentID(String * contentID) -{ - return mainPart()->partForContentID(contentID); -} - -AbstractPart * IMAPMessage::partForUniqueID(String * uniqueID) -{ - return mainPart()->partForUniqueID(uniqueID); -} - -String * IMAPMessage::htmlRendering(String * folder, - HTMLRendererIMAPCallback * dataCallback, - HTMLRendererTemplateCallback * htmlCallback) -{ - return HTMLRenderer::htmlForIMAPMessage(folder, this, dataCallback, htmlCallback); -} - -HashMap * IMAPMessage::serializable() -{ - // sequenceNumber is not serialized. - HashMap * result = AbstractMessage::serializable(); - result->setObjectForKey(MCSTR("modSeqValue"), String::stringWithUTF8Format("%llu", (long long unsigned) modSeqValue())); - result->setObjectForKey(MCSTR("uid"), String::stringWithUTF8Format("%lu", (long unsigned) uid())); - result->setObjectForKey(MCSTR("size"), String::stringWithUTF8Format("%lu", (long unsigned) uid())); - result->setObjectForKey(MCSTR("flags"), String::stringWithUTF8Format("%u", (unsigned) flags())); - result->setObjectForKey(MCSTR("originalFlags"), String::stringWithUTF8Format("%u", (unsigned) originalFlags())); - if (customFlags() != NULL) { - result->setObjectForKey(MCSTR("customFlags"), customFlags()); - } - if (mMainPart != NULL) { - result->setObjectForKey(MCSTR("mainPart"), mMainPart->serializable()); - } - if (gmailLabels() != NULL) { - result->setObjectForKey(MCSTR("gmailLabels"), gmailLabels()); - } - if (gmailMessageID() != 0) { - result->setObjectForKey(MCSTR("gmailMessageID"), String::stringWithUTF8Format("%llu", (long long unsigned) gmailMessageID())); - } - if (gmailThreadID() != 0) { - result->setObjectForKey(MCSTR("gmailThreadID"), String::stringWithUTF8Format("%llu", (long long unsigned) gmailThreadID())); - } - return result; -} - -void IMAPMessage::importSerializable(HashMap * serializable) -{ - // sequenceNumber is not serialized. - AbstractMessage::importSerializable(serializable); - String * modSeq = (String *) serializable->objectForKey(MCSTR("modSeqValue")); - if (modSeq != NULL) { - setModSeqValue(modSeq->unsignedLongLongValue()); - } - String * uid = (String *) serializable->objectForKey(MCSTR("uid")); - if (uid != NULL) { - setUid((uint32_t) uid->unsignedLongValue()); - } - String * size = (String *) serializable->objectForKey(MCSTR("size")); - if (size != NULL) { - setSize((uint32_t) size->unsignedLongValue()); - } - String * flags = (String *) serializable->objectForKey(MCSTR("flags")); - if (flags != NULL) { - setFlags((MessageFlag) flags->unsignedIntValue()); - } - String * originalFlags = (String *) serializable->objectForKey(MCSTR("originalFlags")); - if (originalFlags != NULL) { - setFlags((MessageFlag) originalFlags->unsignedIntValue()); - } - String * customFlags = (String *) serializable->objectForKey(MCSTR("customFlags")); - if (customFlags != NULL) { - setCustomFlags((Array *) serializable->objectForKey(MCSTR("customFlags"))); - } - setMainPart((AbstractPart *) Object::objectWithSerializable((HashMap *) serializable->objectForKey(MCSTR("mainPart")))); - setGmailLabels((Array *) serializable->objectForKey(MCSTR("gmailLabels"))); - String * gmailMessageID = (String *) serializable->objectForKey(MCSTR("gmailMessageID")); - if (gmailMessageID != NULL) { - setGmailMessageID(gmailMessageID->unsignedLongLongValue()); - } - String * gmailThreadID = (String *) serializable->objectForKey(MCSTR("gmailThreadID")); - if (gmailThreadID != NULL) { - setGmailThreadID(gmailThreadID->unsignedLongLongValue()); - } -} - -static void * createObject() -{ - return new IMAPMessage(); -} - -INITIALIZE(IMAPMessage) -{ - Object::registerObjectConstructor("mailcore::IMAPMessage", &createObject); -} diff --git a/src/core/imap/MCIMAPMessage.cpp b/src/core/imap/MCIMAPMessage.cpp new file mode 100644 index 00000000..430ecdaa --- /dev/null +++ b/src/core/imap/MCIMAPMessage.cpp @@ -0,0 +1,324 @@ +#include "MCIMAPMessage.h" + +#include "MCDefines.h" +#include "MCMessageHeader.h" +#include "MCIMAPPart.h" +#include "MCIMAPMessagePart.h" +#include "MCIMAPMultipart.h" +#include "MCHTMLRenderer.h" +#include "MCHTMLRendererCallback.h" + +using namespace mailcore; + +static AbstractPart * partForPartIDInPart(AbstractPart * part, String * partID); +static AbstractPart * partForPartIDInMultipart(AbstractMultipart * part, String * partID); +static AbstractPart * partForPartIDInMessagePart(AbstractMessagePart * part, String * partID); + +void IMAPMessage::init() +{ + mUid = 0; + mSequenceNumber = 0; + mFlags = MessageFlagNone; + mOriginalFlags = MessageFlagNone; + mCustomFlags = NULL; + mMainPart = NULL; + mGmailLabels = NULL; + mModSeqValue = 0; + mGmailThreadID = 0; + mGmailMessageID = 0; +} + +IMAPMessage::IMAPMessage() +{ + init(); +} + +IMAPMessage::IMAPMessage(IMAPMessage * other) : AbstractMessage(other) +{ + init(); + setUid(other->uid()); + setSequenceNumber(other->sequenceNumber()); + setFlags(other->flags()); + setOriginalFlags(other->originalFlags()); + setCustomFlags(other->customFlags()); + setMainPart((AbstractPart *) other->mainPart()->copy()->autorelease()); + setGmailLabels(other->gmailLabels()); + setGmailThreadID(other->gmailThreadID()); + setGmailMessageID(other->gmailMessageID()); +} + +IMAPMessage::~IMAPMessage() +{ + MC_SAFE_RELEASE(mMainPart); + MC_SAFE_RELEASE(mGmailLabels); + MC_SAFE_RELEASE(mCustomFlags); +} + +Object * IMAPMessage::copy() +{ + return new IMAPMessage(this); +} + +String * IMAPMessage::description() +{ + String * result = String::string(); + result->appendUTF8Format("<%s:%p %u %u\n", className()->UTF8Characters(), this, (unsigned int) uid(), (unsigned int) sequenceNumber()); + result->appendString(header()->description()); + if (mainPart() != NULL) { + result->appendString(mainPart()->description()); + result->appendUTF8Characters("\n"); + } + result->appendUTF8Characters(">"); + return result; +} + +uint32_t IMAPMessage::uid() +{ + return mUid; +} + +void IMAPMessage::setUid(uint32_t uid) +{ + mUid = uid; +} + +uint32_t IMAPMessage::sequenceNumber() +{ + return mSequenceNumber; +} + +void IMAPMessage::setSequenceNumber(uint32_t value) +{ + mSequenceNumber = value; +} + +uint32_t IMAPMessage::size() +{ + return mSize; +} + +void IMAPMessage::setSize(uint32_t size) +{ + mSize = size; +} + +void IMAPMessage::setFlags(MessageFlag flags) +{ + mFlags = flags; +} + +MessageFlag IMAPMessage::flags() +{ + return mFlags; +} + +void IMAPMessage::setOriginalFlags(MessageFlag flags) +{ + mOriginalFlags = flags; +} + +MessageFlag IMAPMessage::originalFlags() +{ + return mOriginalFlags; +} + +void IMAPMessage::setCustomFlags(Array * customFlags) +{ + MC_SAFE_REPLACE_COPY(Array, mCustomFlags, customFlags); +} + +Array * IMAPMessage::customFlags() +{ + return mCustomFlags; +} + +void IMAPMessage::setModSeqValue(uint64_t uid) +{ + mModSeqValue = uid; +} + +uint64_t IMAPMessage::modSeqValue() +{ + return mModSeqValue; +} + +void IMAPMessage::setMainPart(AbstractPart * mainPart) +{ + MC_SAFE_REPLACE_RETAIN(AbstractPart, mMainPart, mainPart); +} + +AbstractPart * IMAPMessage::mainPart() +{ + return mMainPart; +} + +void IMAPMessage::setGmailLabels(Array * labels) +{ + MC_SAFE_REPLACE_COPY(Array, mGmailLabels, labels); +} + +Array * IMAPMessage::gmailLabels() +{ + return mGmailLabels; +} + +void IMAPMessage::setGmailMessageID(uint64_t msgID) +{ + mGmailMessageID = msgID; +} + +uint64_t IMAPMessage::gmailMessageID() +{ + return mGmailMessageID; +} + +void IMAPMessage::setGmailThreadID(uint64_t threadID) +{ + mGmailThreadID = threadID; +} + +uint64_t IMAPMessage::gmailThreadID() +{ + return mGmailThreadID; +} + +AbstractPart * IMAPMessage::partForPartID(String * partID) +{ + return partForPartIDInPart(mainPart(), partID); +} + +static AbstractPart * partForPartIDInPart(AbstractPart * part, String * partID) +{ + switch (part->partType()) { + case PartTypeSingle: + if (partID->isEqual(((IMAPPart *) part)->partID())) { + return part; + } + return NULL; + case mailcore::PartTypeMultipartMixed: + case mailcore::PartTypeMultipartRelated: + case mailcore::PartTypeMultipartAlternative: + case mailcore::PartTypeMultipartSigned: + if (partID->isEqual(((IMAPMultipart *) part)->partID())) { + return part; + } + return partForPartIDInMultipart((AbstractMultipart *) part, partID); + case mailcore::PartTypeMessage: + if (partID->isEqual(((IMAPMessagePart *) part)->partID())) { + return part; + } + return partForPartIDInMessagePart((AbstractMessagePart *) part, partID); + default: + return NULL; + } +} + +static AbstractPart * partForPartIDInMessagePart(AbstractMessagePart * part, String * partID) +{ + return partForPartIDInPart(part->mainPart(), partID); +} + +static AbstractPart * partForPartIDInMultipart(AbstractMultipart * part, String * partID) +{ + for(unsigned int i = 0 ; i < part->parts()->count() ; i ++) { + mailcore::AbstractPart * subpart = (mailcore::AbstractPart *) part->parts()->objectAtIndex(i); + mailcore::AbstractPart * result = partForPartIDInPart(subpart, partID); + if (result != NULL) + return result; + } + return NULL; +} + +AbstractPart * IMAPMessage::partForContentID(String * contentID) +{ + return mainPart()->partForContentID(contentID); +} + +AbstractPart * IMAPMessage::partForUniqueID(String * uniqueID) +{ + return mainPart()->partForUniqueID(uniqueID); +} + +String * IMAPMessage::htmlRendering(String * folder, + HTMLRendererIMAPCallback * dataCallback, + HTMLRendererTemplateCallback * htmlCallback) +{ + return HTMLRenderer::htmlForIMAPMessage(folder, this, dataCallback, htmlCallback); +} + +HashMap * IMAPMessage::serializable() +{ + // sequenceNumber is not serialized. + HashMap * result = AbstractMessage::serializable(); + result->setObjectForKey(MCSTR("modSeqValue"), String::stringWithUTF8Format("%llu", (long long unsigned) modSeqValue())); + result->setObjectForKey(MCSTR("uid"), String::stringWithUTF8Format("%lu", (long unsigned) uid())); + result->setObjectForKey(MCSTR("size"), String::stringWithUTF8Format("%lu", (long unsigned) uid())); + result->setObjectForKey(MCSTR("flags"), String::stringWithUTF8Format("%u", (unsigned) flags())); + result->setObjectForKey(MCSTR("originalFlags"), String::stringWithUTF8Format("%u", (unsigned) originalFlags())); + if (customFlags() != NULL) { + result->setObjectForKey(MCSTR("customFlags"), customFlags()); + } + if (mMainPart != NULL) { + result->setObjectForKey(MCSTR("mainPart"), mMainPart->serializable()); + } + if (gmailLabels() != NULL) { + result->setObjectForKey(MCSTR("gmailLabels"), gmailLabels()); + } + if (gmailMessageID() != 0) { + result->setObjectForKey(MCSTR("gmailMessageID"), String::stringWithUTF8Format("%llu", (long long unsigned) gmailMessageID())); + } + if (gmailThreadID() != 0) { + result->setObjectForKey(MCSTR("gmailThreadID"), String::stringWithUTF8Format("%llu", (long long unsigned) gmailThreadID())); + } + return result; +} + +void IMAPMessage::importSerializable(HashMap * serializable) +{ + // sequenceNumber is not serialized. + AbstractMessage::importSerializable(serializable); + String * modSeq = (String *) serializable->objectForKey(MCSTR("modSeqValue")); + if (modSeq != NULL) { + setModSeqValue(modSeq->unsignedLongLongValue()); + } + String * uid = (String *) serializable->objectForKey(MCSTR("uid")); + if (uid != NULL) { + setUid((uint32_t) uid->unsignedLongValue()); + } + String * size = (String *) serializable->objectForKey(MCSTR("size")); + if (size != NULL) { + setSize((uint32_t) size->unsignedLongValue()); + } + String * flags = (String *) serializable->objectForKey(MCSTR("flags")); + if (flags != NULL) { + setFlags((MessageFlag) flags->unsignedIntValue()); + } + String * originalFlags = (String *) serializable->objectForKey(MCSTR("originalFlags")); + if (originalFlags != NULL) { + setFlags((MessageFlag) originalFlags->unsignedIntValue()); + } + String * customFlags = (String *) serializable->objectForKey(MCSTR("customFlags")); + if (customFlags != NULL) { + setCustomFlags((Array *) serializable->objectForKey(MCSTR("customFlags"))); + } + setMainPart((AbstractPart *) Object::objectWithSerializable((HashMap *) serializable->objectForKey(MCSTR("mainPart")))); + setGmailLabels((Array *) serializable->objectForKey(MCSTR("gmailLabels"))); + String * gmailMessageID = (String *) serializable->objectForKey(MCSTR("gmailMessageID")); + if (gmailMessageID != NULL) { + setGmailMessageID(gmailMessageID->unsignedLongLongValue()); + } + String * gmailThreadID = (String *) serializable->objectForKey(MCSTR("gmailThreadID")); + if (gmailThreadID != NULL) { + setGmailThreadID(gmailThreadID->unsignedLongLongValue()); + } +} + +static void * createObject() +{ + return new IMAPMessage(); +} + +INITIALIZE(IMAPMessage) +{ + Object::registerObjectConstructor("mailcore::IMAPMessage", &createObject); +} diff --git a/src/core/imap/MCIMAPMessagePart.cc b/src/core/imap/MCIMAPMessagePart.cc deleted file mode 100644 index 20744ad2..00000000 --- a/src/core/imap/MCIMAPMessagePart.cc +++ /dev/null @@ -1,67 +0,0 @@ -#include "MCIMAPMessagePart.h" - -#include "MCDefines.h" - -using namespace mailcore; - -IMAPMessagePart::IMAPMessagePart() -{ - init(); -} - -IMAPMessagePart::IMAPMessagePart(IMAPMessagePart * other) : AbstractMessagePart(other) -{ - init(); - MC_SAFE_REPLACE_COPY(String, mPartID, other->mPartID); -} - -IMAPMessagePart::~IMAPMessagePart() -{ - MC_SAFE_RELEASE(mPartID); -} - -Object * IMAPMessagePart::copy() -{ - return new IMAPMessagePart(this); -} - -void IMAPMessagePart::init() -{ - mPartID = NULL; -} - -void IMAPMessagePart::setPartID(String * partID) -{ - MC_SAFE_REPLACE_COPY(String, mPartID, partID); -} - -String * IMAPMessagePart::partID() -{ - return mPartID; -} - -HashMap * IMAPMessagePart::serializable() -{ - HashMap * result = AbstractMessagePart::serializable(); - if (partID() != NULL) { - result->setObjectForKey(MCSTR("partID"), partID()); - } - return result; -} - -void IMAPMessagePart::importSerializable(HashMap * serializable) -{ - AbstractMessagePart::importSerializable(serializable); - String * partID = (String *) serializable->objectForKey(MCSTR("partID")); - setPartID(partID); -} - -static void * createObject() -{ - return new IMAPMessagePart(); -} - -INITIALIZE(IMAPMessagePart) -{ - Object::registerObjectConstructor("mailcore::IMAPMessagePart", &createObject); -} diff --git a/src/core/imap/MCIMAPMessagePart.cpp b/src/core/imap/MCIMAPMessagePart.cpp new file mode 100644 index 00000000..20744ad2 --- /dev/null +++ b/src/core/imap/MCIMAPMessagePart.cpp @@ -0,0 +1,67 @@ +#include "MCIMAPMessagePart.h" + +#include "MCDefines.h" + +using namespace mailcore; + +IMAPMessagePart::IMAPMessagePart() +{ + init(); +} + +IMAPMessagePart::IMAPMessagePart(IMAPMessagePart * other) : AbstractMessagePart(other) +{ + init(); + MC_SAFE_REPLACE_COPY(String, mPartID, other->mPartID); +} + +IMAPMessagePart::~IMAPMessagePart() +{ + MC_SAFE_RELEASE(mPartID); +} + +Object * IMAPMessagePart::copy() +{ + return new IMAPMessagePart(this); +} + +void IMAPMessagePart::init() +{ + mPartID = NULL; +} + +void IMAPMessagePart::setPartID(String * partID) +{ + MC_SAFE_REPLACE_COPY(String, mPartID, partID); +} + +String * IMAPMessagePart::partID() +{ + return mPartID; +} + +HashMap * IMAPMessagePart::serializable() +{ + HashMap * result = AbstractMessagePart::serializable(); + if (partID() != NULL) { + result->setObjectForKey(MCSTR("partID"), partID()); + } + return result; +} + +void IMAPMessagePart::importSerializable(HashMap * serializable) +{ + AbstractMessagePart::importSerializable(serializable); + String * partID = (String *) serializable->objectForKey(MCSTR("partID")); + setPartID(partID); +} + +static void * createObject() +{ + return new IMAPMessagePart(); +} + +INITIALIZE(IMAPMessagePart) +{ + Object::registerObjectConstructor("mailcore::IMAPMessagePart", &createObject); +} diff --git a/src/core/imap/MCIMAPMultipart.cc b/src/core/imap/MCIMAPMultipart.cc deleted file mode 100644 index d943c066..00000000 --- a/src/core/imap/MCIMAPMultipart.cc +++ /dev/null @@ -1,68 +0,0 @@ -#include "MCIMAPMultipart.h" - -#include "MCDefines.h" - -using namespace mailcore; - -IMAPMultipart::IMAPMultipart() -{ - init(); -} - -IMAPMultipart::IMAPMultipart(IMAPMultipart * other) : AbstractMultipart(other) -{ - init(); - MC_SAFE_REPLACE_COPY(String, mPartID, other->mPartID); -} - -IMAPMultipart::~IMAPMultipart() -{ - MC_SAFE_RELEASE(mPartID); -} - -Object * IMAPMultipart::copy() -{ - return new IMAPMultipart(this); -} - -void IMAPMultipart::init() -{ - mPartID = NULL; -} - -void IMAPMultipart::setPartID(String * partID) -{ - MC_SAFE_REPLACE_COPY(String, mPartID, partID); -} - -String * IMAPMultipart::partID() -{ - return mPartID; -} - -HashMap * IMAPMultipart::serializable() -{ - HashMap * result = AbstractMultipart::serializable(); - if (partID() != NULL) { - result->setObjectForKey(MCSTR("partID"), partID()); - } - return result; -} - -void IMAPMultipart::importSerializable(HashMap * serializable) -{ - AbstractMultipart::importSerializable(serializable); - String * partID = (String *) serializable->objectForKey(MCSTR("partID")); - setPartID(partID); -} - -static void * createObject() -{ - return new IMAPMultipart(); -} - -INITIALIZE(IMAPMultipart) -{ - Object::registerObjectConstructor("mailcore::IMAPMultipart", &createObject); -} - diff --git a/src/core/imap/MCIMAPMultipart.cpp b/src/core/imap/MCIMAPMultipart.cpp new file mode 100644 index 00000000..d943c066 --- /dev/null +++ b/src/core/imap/MCIMAPMultipart.cpp @@ -0,0 +1,68 @@ +#include "MCIMAPMultipart.h" + +#include "MCDefines.h" + +using namespace mailcore; + +IMAPMultipart::IMAPMultipart() +{ + init(); +} + +IMAPMultipart::IMAPMultipart(IMAPMultipart * other) : AbstractMultipart(other) +{ + init(); + MC_SAFE_REPLACE_COPY(String, mPartID, other->mPartID); +} + +IMAPMultipart::~IMAPMultipart() +{ + MC_SAFE_RELEASE(mPartID); +} + +Object * IMAPMultipart::copy() +{ + return new IMAPMultipart(this); +} + +void IMAPMultipart::init() +{ + mPartID = NULL; +} + +void IMAPMultipart::setPartID(String * partID) +{ + MC_SAFE_REPLACE_COPY(String, mPartID, partID); +} + +String * IMAPMultipart::partID() +{ + return mPartID; +} + +HashMap * IMAPMultipart::serializable() +{ + HashMap * result = AbstractMultipart::serializable(); + if (partID() != NULL) { + result->setObjectForKey(MCSTR("partID"), partID()); + } + return result; +} + +void IMAPMultipart::importSerializable(HashMap * serializable) +{ + AbstractMultipart::importSerializable(serializable); + String * partID = (String *) serializable->objectForKey(MCSTR("partID")); + setPartID(partID); +} + +static void * createObject() +{ + return new IMAPMultipart(); +} + +INITIALIZE(IMAPMultipart) +{ + Object::registerObjectConstructor("mailcore::IMAPMultipart", &createObject); +} + diff --git a/src/core/imap/MCIMAPNamespace.cc b/src/core/imap/MCIMAPNamespace.cc deleted file mode 100644 index 09037877..00000000 --- a/src/core/imap/MCIMAPNamespace.cc +++ /dev/null @@ -1,144 +0,0 @@ -#include "MCIMAPNamespace.h" - -#include "MCIMAPNamespaceItem.h" - -#include - -using namespace mailcore; - -void IMAPNamespace::init() -{ - mItems = NULL; -} - -IMAPNamespace::IMAPNamespace() -{ - init(); - mItems = new Array(); -} - -IMAPNamespace::IMAPNamespace(IMAPNamespace * other) -{ - init(); - mItems = (Array *) other->mItems->copy(); -} - -IMAPNamespace::~IMAPNamespace() -{ - MC_SAFE_RELEASE(mItems); -} - -String * IMAPNamespace::description() -{ - String * result = String::string(); - result->appendUTF8Format("<%s:%p %s>", MCUTF8(className()), this, - MCUTF8DESC(mItems)); - return result; -} - -Object * IMAPNamespace::copy() -{ - return new IMAPNamespace(this); -} - -IMAPNamespaceItem * IMAPNamespace::mainItem() -{ - if (mItems->count() == 0) - return NULL; - - return (IMAPNamespaceItem *) mItems->objectAtIndex(0); -} - -IMAPNamespaceItem * IMAPNamespace::itemForPath(String * path) -{ - for(unsigned int i = 0 ; i < mItems->count() ; i ++) { - IMAPNamespaceItem * item = (IMAPNamespaceItem *) mItems->objectAtIndex(i); - if (item->containsFolder(path)) - return item; - } - - return NULL; -} - -String * IMAPNamespace::mainPrefix() -{ - if (mItems->count() == 0) - return NULL; - - return mainItem()->prefix(); -} - -char IMAPNamespace::mainDelimiter() -{ - if (mItems->count() == 0) - return 0; - - return mainItem()->delimiter(); -} - -Array * IMAPNamespace::prefixes() -{ - Array * result = Array::array(); - for(unsigned int i = 0 ; i < mItems->count() ; i ++) { - IMAPNamespaceItem * item = (IMAPNamespaceItem *) mItems->objectAtIndex(i); - result->addObject(item->prefix()); - } - return result; -} - -String * IMAPNamespace::pathForComponents(Array * components) -{ - return mainItem()->pathForComponents(components); -} - -String * IMAPNamespace::pathForComponentsAndPrefix(Array * components, String * prefix) -{ - IMAPNamespaceItem * item = itemForPath(prefix); - if (item == NULL) - return NULL; - return item->pathForComponents(components); -} - -Array * IMAPNamespace::componentsFromPath(String * path) -{ - IMAPNamespaceItem * item = itemForPath(path); - if (item == NULL) - return NULL; - return item->componentsForPath(path); -} - -bool IMAPNamespace::containsFolderPath(String * path) -{ - return (itemForPath(path) != NULL); -} - -IMAPNamespace * IMAPNamespace::namespaceWithPrefix(String * prefix, char delimiter) -{ - IMAPNamespace * ns; - IMAPNamespaceItem * item; - - ns = new IMAPNamespace(); - item = new IMAPNamespaceItem(); - item->setDelimiter(delimiter); - item->setPrefix(prefix); - ns->mItems->addObject(item); - item->release(); - - return (IMAPNamespace *) ns->autorelease(); -} - -void IMAPNamespace::importIMAPNamespace(struct mailimap_namespace_item * item) -{ - clistiter * cur; - - for(cur = clist_begin(item->ns_data_list) ; cur != NULL ; cur = clist_next(cur)) { - IMAPNamespaceItem * item; - struct mailimap_namespace_info * info; - - info = (struct mailimap_namespace_info *) clist_content(cur); - item = new IMAPNamespaceItem(); - item->importIMAPNamespaceInfo(info); - mItems->addObject(item); - item->release(); - } -} diff --git a/src/core/imap/MCIMAPNamespace.cpp b/src/core/imap/MCIMAPNamespace.cpp new file mode 100644 index 00000000..09037877 --- /dev/null +++ b/src/core/imap/MCIMAPNamespace.cpp @@ -0,0 +1,144 @@ +#include "MCIMAPNamespace.h" + +#include "MCIMAPNamespaceItem.h" + +#include + +using namespace mailcore; + +void IMAPNamespace::init() +{ + mItems = NULL; +} + +IMAPNamespace::IMAPNamespace() +{ + init(); + mItems = new Array(); +} + +IMAPNamespace::IMAPNamespace(IMAPNamespace * other) +{ + init(); + mItems = (Array *) other->mItems->copy(); +} + +IMAPNamespace::~IMAPNamespace() +{ + MC_SAFE_RELEASE(mItems); +} + +String * IMAPNamespace::description() +{ + String * result = String::string(); + result->appendUTF8Format("<%s:%p %s>", MCUTF8(className()), this, + MCUTF8DESC(mItems)); + return result; +} + +Object * IMAPNamespace::copy() +{ + return new IMAPNamespace(this); +} + +IMAPNamespaceItem * IMAPNamespace::mainItem() +{ + if (mItems->count() == 0) + return NULL; + + return (IMAPNamespaceItem *) mItems->objectAtIndex(0); +} + +IMAPNamespaceItem * IMAPNamespace::itemForPath(String * path) +{ + for(unsigned int i = 0 ; i < mItems->count() ; i ++) { + IMAPNamespaceItem * item = (IMAPNamespaceItem *) mItems->objectAtIndex(i); + if (item->containsFolder(path)) + return item; + } + + return NULL; +} + +String * IMAPNamespace::mainPrefix() +{ + if (mItems->count() == 0) + return NULL; + + return mainItem()->prefix(); +} + +char IMAPNamespace::mainDelimiter() +{ + if (mItems->count() == 0) + return 0; + + return mainItem()->delimiter(); +} + +Array * IMAPNamespace::prefixes() +{ + Array * result = Array::array(); + for(unsigned int i = 0 ; i < mItems->count() ; i ++) { + IMAPNamespaceItem * item = (IMAPNamespaceItem *) mItems->objectAtIndex(i); + result->addObject(item->prefix()); + } + return result; +} + +String * IMAPNamespace::pathForComponents(Array * components) +{ + return mainItem()->pathForComponents(components); +} + +String * IMAPNamespace::pathForComponentsAndPrefix(Array * components, String * prefix) +{ + IMAPNamespaceItem * item = itemForPath(prefix); + if (item == NULL) + return NULL; + return item->pathForComponents(components); +} + +Array * IMAPNamespace::componentsFromPath(String * path) +{ + IMAPNamespaceItem * item = itemForPath(path); + if (item == NULL) + return NULL; + return item->componentsForPath(path); +} + +bool IMAPNamespace::containsFolderPath(String * path) +{ + return (itemForPath(path) != NULL); +} + +IMAPNamespace * IMAPNamespace::namespaceWithPrefix(String * prefix, char delimiter) +{ + IMAPNamespace * ns; + IMAPNamespaceItem * item; + + ns = new IMAPNamespace(); + item = new IMAPNamespaceItem(); + item->setDelimiter(delimiter); + item->setPrefix(prefix); + ns->mItems->addObject(item); + item->release(); + + return (IMAPNamespace *) ns->autorelease(); +} + +void IMAPNamespace::importIMAPNamespace(struct mailimap_namespace_item * item) +{ + clistiter * cur; + + for(cur = clist_begin(item->ns_data_list) ; cur != NULL ; cur = clist_next(cur)) { + IMAPNamespaceItem * item; + struct mailimap_namespace_info * info; + + info = (struct mailimap_namespace_info *) clist_content(cur); + item = new IMAPNamespaceItem(); + item->importIMAPNamespaceInfo(info); + mItems->addObject(item); + item->release(); + } +} diff --git a/src/core/imap/MCIMAPNamespaceItem.cc b/src/core/imap/MCIMAPNamespaceItem.cc deleted file mode 100644 index c985e915..00000000 --- a/src/core/imap/MCIMAPNamespaceItem.cc +++ /dev/null @@ -1,152 +0,0 @@ -#include "MCIMAPNamespaceItem.h" - -#include - -using namespace mailcore; - -static Array * encodedComponents(Array * components); -static Array * decodedComponents(Array * components); - -void IMAPNamespaceItem::init() -{ - mDelimiter = 0; - mPrefix = NULL; -} - -IMAPNamespaceItem::IMAPNamespaceItem() -{ - init(); -} - -IMAPNamespaceItem::IMAPNamespaceItem(IMAPNamespaceItem * other) -{ - init(); - setDelimiter(other->delimiter()); - setPrefix(other->prefix()); -} - -IMAPNamespaceItem::~IMAPNamespaceItem() -{ - MC_SAFE_RELEASE(mPrefix); -} - -String * IMAPNamespaceItem::description() -{ - return String::stringWithUTF8Format("<%s:%p %s %c>", - MCUTF8(className()), this, MCUTF8(prefix()), delimiter()); -} - -Object * IMAPNamespaceItem::copy() -{ - return new IMAPNamespaceItem(this); -} - -void IMAPNamespaceItem::setPrefix(String * prefix) -{ - MC_SAFE_REPLACE_COPY(String, mPrefix, prefix); -} - -String * IMAPNamespaceItem::prefix() -{ - return mPrefix; -} - -void IMAPNamespaceItem::setDelimiter(char delimiter) -{ - mDelimiter = delimiter; -} - -char IMAPNamespaceItem::delimiter() -{ - return mDelimiter; -} - -String * IMAPNamespaceItem::pathForComponents(Array * components) -{ - String * path; - String * prefix; - String * separator; - - components = encodedComponents(components); - if (mDelimiter == 0) { - separator = MCSTR(""); - } - else { - separator = String::stringWithUTF8Format("%c", mDelimiter); - } - path = components->componentsJoinedByString(separator); - - prefix = mPrefix; - if (prefix->length() > 0) { - if (!prefix->hasSuffix(String::stringWithUTF8Format("%c", mDelimiter))) { - prefix = prefix->stringByAppendingUTF8Format("%c", mDelimiter); - } - } - return prefix->stringByAppendingString(path); -} - -Array * IMAPNamespaceItem::componentsForPath(String * path) -{ - Array * components; - - if (path->hasPrefix(mPrefix)) { - path = path->substringFromIndex(mPrefix->length()); - } - if (mDelimiter == 0) { - return Array::arrayWithObject(path); - } - components = path->componentsSeparatedByString(String::stringWithUTF8Format("%c", mDelimiter)); - components = decodedComponents(components); - if (components->count() > 0) { - if (((String *) components->objectAtIndex(0))->length() == 0) { - components->removeObjectAtIndex(0); - } - } - - return components; -} - -bool IMAPNamespaceItem::containsFolder(String * folder) -{ - if (mPrefix->length() == 0) - return true; - return folder->hasPrefix(mPrefix); -} - -void IMAPNamespaceItem::importIMAPNamespaceInfo(struct mailimap_namespace_info * info) -{ - setPrefix(String::stringWithUTF8Characters(info->ns_prefix)); - setDelimiter(info->ns_delimiter); -} - -static Array * encodedComponents(Array * components) -{ - Array * result; - - result = Array::array(); - for(unsigned int i = 0 ; i < components->count() ; i ++) { - String * value = (String *) components->objectAtIndex(i); - result->addObject(value->mUTF7EncodedString()); - } - - return result; -} - -static Array * decodedComponents(Array * components) -{ - Array * result; - - result = Array::array(); - for(unsigned int i = 0 ; i < components->count() ; i ++) { - String * value = (String *) components->objectAtIndex(i); - String * decoded; - - decoded = value->mUTF7DecodedString(); - if (decoded == NULL) { - decoded = value; - } - result->addObject(decoded); - } - - return result; -} diff --git a/src/core/imap/MCIMAPNamespaceItem.cpp b/src/core/imap/MCIMAPNamespaceItem.cpp new file mode 100644 index 00000000..c985e915 --- /dev/null +++ b/src/core/imap/MCIMAPNamespaceItem.cpp @@ -0,0 +1,152 @@ +#include "MCIMAPNamespaceItem.h" + +#include + +using namespace mailcore; + +static Array * encodedComponents(Array * components); +static Array * decodedComponents(Array * components); + +void IMAPNamespaceItem::init() +{ + mDelimiter = 0; + mPrefix = NULL; +} + +IMAPNamespaceItem::IMAPNamespaceItem() +{ + init(); +} + +IMAPNamespaceItem::IMAPNamespaceItem(IMAPNamespaceItem * other) +{ + init(); + setDelimiter(other->delimiter()); + setPrefix(other->prefix()); +} + +IMAPNamespaceItem::~IMAPNamespaceItem() +{ + MC_SAFE_RELEASE(mPrefix); +} + +String * IMAPNamespaceItem::description() +{ + return String::stringWithUTF8Format("<%s:%p %s %c>", + MCUTF8(className()), this, MCUTF8(prefix()), delimiter()); +} + +Object * IMAPNamespaceItem::copy() +{ + return new IMAPNamespaceItem(this); +} + +void IMAPNamespaceItem::setPrefix(String * prefix) +{ + MC_SAFE_REPLACE_COPY(String, mPrefix, prefix); +} + +String * IMAPNamespaceItem::prefix() +{ + return mPrefix; +} + +void IMAPNamespaceItem::setDelimiter(char delimiter) +{ + mDelimiter = delimiter; +} + +char IMAPNamespaceItem::delimiter() +{ + return mDelimiter; +} + +String * IMAPNamespaceItem::pathForComponents(Array * components) +{ + String * path; + String * prefix; + String * separator; + + components = encodedComponents(components); + if (mDelimiter == 0) { + separator = MCSTR(""); + } + else { + separator = String::stringWithUTF8Format("%c", mDelimiter); + } + path = components->componentsJoinedByString(separator); + + prefix = mPrefix; + if (prefix->length() > 0) { + if (!prefix->hasSuffix(String::stringWithUTF8Format("%c", mDelimiter))) { + prefix = prefix->stringByAppendingUTF8Format("%c", mDelimiter); + } + } + return prefix->stringByAppendingString(path); +} + +Array * IMAPNamespaceItem::componentsForPath(String * path) +{ + Array * components; + + if (path->hasPrefix(mPrefix)) { + path = path->substringFromIndex(mPrefix->length()); + } + if (mDelimiter == 0) { + return Array::arrayWithObject(path); + } + components = path->componentsSeparatedByString(String::stringWithUTF8Format("%c", mDelimiter)); + components = decodedComponents(components); + if (components->count() > 0) { + if (((String *) components->objectAtIndex(0))->length() == 0) { + components->removeObjectAtIndex(0); + } + } + + return components; +} + +bool IMAPNamespaceItem::containsFolder(String * folder) +{ + if (mPrefix->length() == 0) + return true; + return folder->hasPrefix(mPrefix); +} + +void IMAPNamespaceItem::importIMAPNamespaceInfo(struct mailimap_namespace_info * info) +{ + setPrefix(String::stringWithUTF8Characters(info->ns_prefix)); + setDelimiter(info->ns_delimiter); +} + +static Array * encodedComponents(Array * components) +{ + Array * result; + + result = Array::array(); + for(unsigned int i = 0 ; i < components->count() ; i ++) { + String * value = (String *) components->objectAtIndex(i); + result->addObject(value->mUTF7EncodedString()); + } + + return result; +} + +static Array * decodedComponents(Array * components) +{ + Array * result; + + result = Array::array(); + for(unsigned int i = 0 ; i < components->count() ; i ++) { + String * value = (String *) components->objectAtIndex(i); + String * decoded; + + decoded = value->mUTF7DecodedString(); + if (decoded == NULL) { + decoded = value; + } + result->addObject(decoded); + } + + return result; +} diff --git a/src/core/imap/MCIMAPPart.cc b/src/core/imap/MCIMAPPart.cc deleted file mode 100644 index 21336aa3..00000000 --- a/src/core/imap/MCIMAPPart.cc +++ /dev/null @@ -1,369 +0,0 @@ -#include "MCWin32.h" // Should be included first. - -#include "MCIMAPPart.h" - -#include -#include - -#include "MCDefines.h" -#include "MCIMAPMessagePart.h" -#include "MCIMAPMultipart.h" -#include "MCMessageHeader.h" - -using namespace mailcore; - -void IMAPPart::init() -{ - mPartID = NULL; - mEncoding = Encoding8Bit; - mSize = 0; -} - -IMAPPart::IMAPPart() -{ - init(); -} - -IMAPPart::IMAPPart(IMAPPart * other) : AbstractPart(other) -{ - init(); - MC_SAFE_REPLACE_COPY(String, mPartID, other->mPartID); - mEncoding = other->mEncoding; - mSize = other->mSize; -} - -IMAPPart::~IMAPPart() -{ - MC_SAFE_RELEASE(mPartID); -} - -Object * IMAPPart::copy() -{ - return new IMAPPart(this); -} - -void IMAPPart::setPartID(String * partID) -{ - MC_SAFE_REPLACE_COPY(String, mPartID, partID); -} - -String * IMAPPart::partID() -{ - return mPartID; -} - -void IMAPPart::setSize(unsigned int size) -{ - mSize = size; -} - -unsigned int IMAPPart::size() -{ - return mSize; -} - -void IMAPPart::setEncoding(Encoding encoding) -{ - mEncoding = encoding; -} - -Encoding IMAPPart::encoding() -{ - return mEncoding; -} - -unsigned int IMAPPart::decodedSize() -{ - switch (mEncoding) { - case MAILIMAP_BODY_FLD_ENC_BASE64: - return mSize * 3 / 4; - - default: - return mSize; - } -} - -AbstractPart * IMAPPart::attachmentWithIMAPBody(struct mailimap_body * body) -{ - String * partID; - AbstractPart * result; - - partID = NULL; - if (body->bd_type == MAILIMAP_BODY_1PART) { - partID = MCSTR("1"); - } - result = attachmentWithIMAPBodyInternal(body, partID); - result->applyUniquePartID(); - - return result; -} - -AbstractPart * IMAPPart::attachmentWithIMAPBodyInternal(struct mailimap_body * body, String * partID) -{ - switch (body->bd_type) { - case MAILIMAP_BODY_1PART: - return attachmentWithIMAPBody1Part(body->bd_data.bd_body_1part, partID); - case MAILIMAP_BODY_MPART: - return attachmentWithIMAPBodyMultipart(body->bd_data.bd_body_mpart, partID); - } - - return NULL; -} - -AbstractPart * IMAPPart::attachmentWithIMAPBody1Part(struct mailimap_body_type_1part * body_1part, - String * partID) -{ - switch (body_1part->bd_type) { - case MAILIMAP_BODY_TYPE_1PART_BASIC: - { - IMAPPart * attachment; - - attachment = attachmentWithIMAPBody1PartBasic(body_1part->bd_data.bd_type_basic, - body_1part->bd_ext_1part); - attachment->setPartID(partID); - return attachment; - } - case MAILIMAP_BODY_TYPE_1PART_MSG: - { - return attachmentWithIMAPBody1PartMessage(body_1part->bd_data.bd_type_msg, - body_1part->bd_ext_1part, partID); - } - case MAILIMAP_BODY_TYPE_1PART_TEXT: - { - IMAPPart * attachment; - - attachment = attachmentWithIMAPBody1PartText(body_1part->bd_data.bd_type_text, - body_1part->bd_ext_1part); - attachment->setPartID(partID); - MCLog("attachment %s", MCUTF8(partID)); - return attachment; - } - } - - return NULL; -} - -IMAPMessagePart * IMAPPart::attachmentWithIMAPBody1PartMessage(struct mailimap_body_type_msg * message, - struct mailimap_body_ext_1part * extension, - String * partID) -{ - IMAPMessagePart * attachment; - AbstractPart * subAttachment; - String * nextPartID; - - nextPartID = NULL; - if (message->bd_body->bd_type == MAILIMAP_BODY_1PART) { - // msg or 1part - nextPartID = partID->stringByAppendingUTF8Format(".1"); - } - else if (message->bd_body->bd_type == MAILIMAP_BODY_MPART) { - // mpart - nextPartID = partID; - } - - attachment = new IMAPMessagePart(); - attachment->setPartID(partID); - attachment->header()->importIMAPEnvelope(message->bd_envelope); - attachment->importIMAPFields(message->bd_fields, extension); - - subAttachment = attachmentWithIMAPBodyInternal(message->bd_body, nextPartID); - attachment->setMainPart(subAttachment); - attachment->setMimeType(MCSTR("message/rfc822")); - - return (IMAPMessagePart *) attachment->autorelease(); -} - -void IMAPPart::importIMAPFields(struct mailimap_body_fields * fields, - struct mailimap_body_ext_1part * extension) -{ - AbstractPart::importIMAPFields(fields, extension); - - setSize(fields->bd_size); - if (fields->bd_encoding != NULL) { - bool isUUEncode; - - isUUEncode = false; - if (fields->bd_encoding->enc_type == MAILIMAP_BODY_FLD_ENC_OTHER) { - if (strcasecmp(fields->bd_encoding->enc_value, "x-uuencode") == 0) { - isUUEncode = true; - } - } - if (isUUEncode) { - setEncoding(EncodingUUEncode); - } - else { - setEncoding((Encoding) fields->bd_encoding->enc_type); - } - } -} - -IMAPPart * IMAPPart::attachmentWithIMAPBody1PartBasic(struct mailimap_body_type_basic * basic, - struct mailimap_body_ext_1part * extension) -{ - IMAPPart * attachment; - String * mimeType; - - attachment = new IMAPPart(); - attachment->importIMAPFields(basic->bd_fields, extension); - - mimeType = NULL; - switch (basic->bd_media_basic->med_type) { - case MAILIMAP_MEDIA_BASIC_APPLICATION: - mimeType = String::stringWithUTF8Format("application/%s", basic->bd_media_basic->med_subtype); - break; - case MAILIMAP_MEDIA_BASIC_AUDIO: - mimeType = String::stringWithUTF8Format("audio/%s", basic->bd_media_basic->med_subtype); - break; - case MAILIMAP_MEDIA_BASIC_IMAGE: - mimeType = String::stringWithUTF8Format("image/%s", basic->bd_media_basic->med_subtype); - break; - case MAILIMAP_MEDIA_BASIC_MESSAGE: - mimeType = String::stringWithUTF8Format("message/%s", basic->bd_media_basic->med_subtype); - break; - case MAILIMAP_MEDIA_BASIC_VIDEO: - mimeType = String::stringWithUTF8Format("video/%s", basic->bd_media_basic->med_subtype); - break; - case MAILIMAP_MEDIA_BASIC_OTHER: - mimeType = String::stringWithUTF8Format("%s/%s", basic->bd_media_basic->med_basic_type, basic->bd_media_basic->med_subtype); - break; - } - attachment->setMimeType(mimeType); - - return (IMAPPart *) attachment->autorelease(); -} - -IMAPPart * IMAPPart::attachmentWithIMAPBody1PartText(struct mailimap_body_type_text * text, - struct mailimap_body_ext_1part * extension) -{ - IMAPPart * attachment; - - attachment = new IMAPPart(); - attachment->importIMAPFields(text->bd_fields, extension); - attachment->setMimeType(String::stringWithUTF8Format("text/%s", text->bd_media_text)); - - return (IMAPPart *) attachment->autorelease(); -} - -IMAPMultipart * IMAPPart::attachmentWithIMAPBodyMultipart(struct mailimap_body_type_mpart * body_mpart, - String * partID) -{ - clistiter * cur; - IMAPMultipart * attachment; - unsigned int count; - Array * attachments; - - attachments = new Array(); - - count = 1; - for(cur = clist_begin(body_mpart->bd_list) ; cur != NULL ; cur = clist_next(cur)) { - struct mailimap_body * body; - AbstractPart * subResult; - String * nextPartID; - - if (partID == NULL) { - nextPartID = String::stringWithUTF8Format("%u", count); - } - else { - nextPartID = partID->stringByAppendingUTF8Format(".%u", count); - } - body = (struct mailimap_body *) clist_content(cur); - subResult = attachmentWithIMAPBodyInternal(body, nextPartID); - attachments->addObject(subResult); - - count ++; - } - - attachment = new IMAPMultipart(); - attachment->setPartID(partID); - if (strcasecmp(body_mpart->bd_media_subtype, "alternative") == 0) { - attachment->setPartType(PartTypeMultipartAlternative); - } - else if (strcasecmp(body_mpart->bd_media_subtype, "related") == 0) { - attachment->setPartType(PartTypeMultipartRelated); - } - attachment->setMimeType(String::stringWithUTF8Format("multipart/%s", body_mpart->bd_media_subtype)); - attachment->setParts(attachments); - - attachments->release(); - - return (IMAPMultipart *) attachment->autorelease(); -} - -HashMap * IMAPPart::serializable() -{ - HashMap * result = AbstractPart::serializable(); - if (partID() != NULL) { - result->setObjectForKey(MCSTR("partID"), partID()); - } - String * encodingString; - switch (encoding()) { - case Encoding7Bit: - encodingString = MCSTR("7bit"); - break; - case Encoding8Bit: - default: - encodingString = MCSTR("8bit"); - break; - case EncodingBinary: - encodingString = MCSTR("binary"); - break; - case EncodingBase64: - encodingString = MCSTR("base64"); - break; - case EncodingQuotedPrintable: - encodingString = MCSTR("quoted-printable"); - break; - case EncodingUUEncode: - encodingString = MCSTR("uuencode"); - break; - } - result->setObjectForKey(MCSTR("encoding"), encodingString); - String * sizeString = String::stringWithUTF8Format("%lu", size()); - result->setObjectForKey(MCSTR("size"), sizeString); - return result; -} - -void IMAPPart::importSerializable(HashMap * serializable) -{ - AbstractPart::importSerializable(serializable); - String * partID = (String *) serializable->objectForKey(MCSTR("partID")); - setPartID(partID); - String * encodingString = (String *) serializable->objectForKey(MCSTR("encoding")); - if (encodingString != NULL) { - Encoding encoding = Encoding8Bit; - if (encodingString->isEqual(MCSTR("7bit"))) { - encoding = Encoding7Bit; - } - else if (encodingString->isEqual(MCSTR("8bit"))) { - encoding = Encoding8Bit; - } - else if (encodingString->isEqual(MCSTR("binary"))) { - encoding = EncodingBinary; - } - else if (encodingString->isEqual(MCSTR("base64"))) { - encoding = EncodingBase64; - } - else if (encodingString->isEqual(MCSTR("quoted-printable"))) { - encoding = EncodingQuotedPrintable; - } - else if (encodingString->isEqual(MCSTR("uuencode"))) { - encoding = EncodingUUEncode; - } - setEncoding(encoding); - } - String * sizeString = (String *) serializable->objectForKey(MCSTR("size")); - if (sizeString != NULL) { - setSize(sizeString->unsignedIntValue()); - } -} - -static void * createObject() -{ - return new IMAPPart(); -} - -INITIALIZE(IMAPPart) -{ - Object::registerObjectConstructor("mailcore::IMAPPart", &createObject); -} - diff --git a/src/core/imap/MCIMAPPart.cpp b/src/core/imap/MCIMAPPart.cpp new file mode 100644 index 00000000..21336aa3 --- /dev/null +++ b/src/core/imap/MCIMAPPart.cpp @@ -0,0 +1,369 @@ +#include "MCWin32.h" // Should be included first. + +#include "MCIMAPPart.h" + +#include +#include + +#include "MCDefines.h" +#include "MCIMAPMessagePart.h" +#include "MCIMAPMultipart.h" +#include "MCMessageHeader.h" + +using namespace mailcore; + +void IMAPPart::init() +{ + mPartID = NULL; + mEncoding = Encoding8Bit; + mSize = 0; +} + +IMAPPart::IMAPPart() +{ + init(); +} + +IMAPPart::IMAPPart(IMAPPart * other) : AbstractPart(other) +{ + init(); + MC_SAFE_REPLACE_COPY(String, mPartID, other->mPartID); + mEncoding = other->mEncoding; + mSize = other->mSize; +} + +IMAPPart::~IMAPPart() +{ + MC_SAFE_RELEASE(mPartID); +} + +Object * IMAPPart::copy() +{ + return new IMAPPart(this); +} + +void IMAPPart::setPartID(String * partID) +{ + MC_SAFE_REPLACE_COPY(String, mPartID, partID); +} + +String * IMAPPart::partID() +{ + return mPartID; +} + +void IMAPPart::setSize(unsigned int size) +{ + mSize = size; +} + +unsigned int IMAPPart::size() +{ + return mSize; +} + +void IMAPPart::setEncoding(Encoding encoding) +{ + mEncoding = encoding; +} + +Encoding IMAPPart::encoding() +{ + return mEncoding; +} + +unsigned int IMAPPart::decodedSize() +{ + switch (mEncoding) { + case MAILIMAP_BODY_FLD_ENC_BASE64: + return mSize * 3 / 4; + + default: + return mSize; + } +} + +AbstractPart * IMAPPart::attachmentWithIMAPBody(struct mailimap_body * body) +{ + String * partID; + AbstractPart * result; + + partID = NULL; + if (body->bd_type == MAILIMAP_BODY_1PART) { + partID = MCSTR("1"); + } + result = attachmentWithIMAPBodyInternal(body, partID); + result->applyUniquePartID(); + + return result; +} + +AbstractPart * IMAPPart::attachmentWithIMAPBodyInternal(struct mailimap_body * body, String * partID) +{ + switch (body->bd_type) { + case MAILIMAP_BODY_1PART: + return attachmentWithIMAPBody1Part(body->bd_data.bd_body_1part, partID); + case MAILIMAP_BODY_MPART: + return attachmentWithIMAPBodyMultipart(body->bd_data.bd_body_mpart, partID); + } + + return NULL; +} + +AbstractPart * IMAPPart::attachmentWithIMAPBody1Part(struct mailimap_body_type_1part * body_1part, + String * partID) +{ + switch (body_1part->bd_type) { + case MAILIMAP_BODY_TYPE_1PART_BASIC: + { + IMAPPart * attachment; + + attachment = attachmentWithIMAPBody1PartBasic(body_1part->bd_data.bd_type_basic, + body_1part->bd_ext_1part); + attachment->setPartID(partID); + return attachment; + } + case MAILIMAP_BODY_TYPE_1PART_MSG: + { + return attachmentWithIMAPBody1PartMessage(body_1part->bd_data.bd_type_msg, + body_1part->bd_ext_1part, partID); + } + case MAILIMAP_BODY_TYPE_1PART_TEXT: + { + IMAPPart * attachment; + + attachment = attachmentWithIMAPBody1PartText(body_1part->bd_data.bd_type_text, + body_1part->bd_ext_1part); + attachment->setPartID(partID); + MCLog("attachment %s", MCUTF8(partID)); + return attachment; + } + } + + return NULL; +} + +IMAPMessagePart * IMAPPart::attachmentWithIMAPBody1PartMessage(struct mailimap_body_type_msg * message, + struct mailimap_body_ext_1part * extension, + String * partID) +{ + IMAPMessagePart * attachment; + AbstractPart * subAttachment; + String * nextPartID; + + nextPartID = NULL; + if (message->bd_body->bd_type == MAILIMAP_BODY_1PART) { + // msg or 1part + nextPartID = partID->stringByAppendingUTF8Format(".1"); + } + else if (message->bd_body->bd_type == MAILIMAP_BODY_MPART) { + // mpart + nextPartID = partID; + } + + attachment = new IMAPMessagePart(); + attachment->setPartID(partID); + attachment->header()->importIMAPEnvelope(message->bd_envelope); + attachment->importIMAPFields(message->bd_fields, extension); + + subAttachment = attachmentWithIMAPBodyInternal(message->bd_body, nextPartID); + attachment->setMainPart(subAttachment); + attachment->setMimeType(MCSTR("message/rfc822")); + + return (IMAPMessagePart *) attachment->autorelease(); +} + +void IMAPPart::importIMAPFields(struct mailimap_body_fields * fields, + struct mailimap_body_ext_1part * extension) +{ + AbstractPart::importIMAPFields(fields, extension); + + setSize(fields->bd_size); + if (fields->bd_encoding != NULL) { + bool isUUEncode; + + isUUEncode = false; + if (fields->bd_encoding->enc_type == MAILIMAP_BODY_FLD_ENC_OTHER) { + if (strcasecmp(fields->bd_encoding->enc_value, "x-uuencode") == 0) { + isUUEncode = true; + } + } + if (isUUEncode) { + setEncoding(EncodingUUEncode); + } + else { + setEncoding((Encoding) fields->bd_encoding->enc_type); + } + } +} + +IMAPPart * IMAPPart::attachmentWithIMAPBody1PartBasic(struct mailimap_body_type_basic * basic, + struct mailimap_body_ext_1part * extension) +{ + IMAPPart * attachment; + String * mimeType; + + attachment = new IMAPPart(); + attachment->importIMAPFields(basic->bd_fields, extension); + + mimeType = NULL; + switch (basic->bd_media_basic->med_type) { + case MAILIMAP_MEDIA_BASIC_APPLICATION: + mimeType = String::stringWithUTF8Format("application/%s", basic->bd_media_basic->med_subtype); + break; + case MAILIMAP_MEDIA_BASIC_AUDIO: + mimeType = String::stringWithUTF8Format("audio/%s", basic->bd_media_basic->med_subtype); + break; + case MAILIMAP_MEDIA_BASIC_IMAGE: + mimeType = String::stringWithUTF8Format("image/%s", basic->bd_media_basic->med_subtype); + break; + case MAILIMAP_MEDIA_BASIC_MESSAGE: + mimeType = String::stringWithUTF8Format("message/%s", basic->bd_media_basic->med_subtype); + break; + case MAILIMAP_MEDIA_BASIC_VIDEO: + mimeType = String::stringWithUTF8Format("video/%s", basic->bd_media_basic->med_subtype); + break; + case MAILIMAP_MEDIA_BASIC_OTHER: + mimeType = String::stringWithUTF8Format("%s/%s", basic->bd_media_basic->med_basic_type, basic->bd_media_basic->med_subtype); + break; + } + attachment->setMimeType(mimeType); + + return (IMAPPart *) attachment->autorelease(); +} + +IMAPPart * IMAPPart::attachmentWithIMAPBody1PartText(struct mailimap_body_type_text * text, + struct mailimap_body_ext_1part * extension) +{ + IMAPPart * attachment; + + attachment = new IMAPPart(); + attachment->importIMAPFields(text->bd_fields, extension); + attachment->setMimeType(String::stringWithUTF8Format("text/%s", text->bd_media_text)); + + return (IMAPPart *) attachment->autorelease(); +} + +IMAPMultipart * IMAPPart::attachmentWithIMAPBodyMultipart(struct mailimap_body_type_mpart * body_mpart, + String * partID) +{ + clistiter * cur; + IMAPMultipart * attachment; + unsigned int count; + Array * attachments; + + attachments = new Array(); + + count = 1; + for(cur = clist_begin(body_mpart->bd_list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_body * body; + AbstractPart * subResult; + String * nextPartID; + + if (partID == NULL) { + nextPartID = String::stringWithUTF8Format("%u", count); + } + else { + nextPartID = partID->stringByAppendingUTF8Format(".%u", count); + } + body = (struct mailimap_body *) clist_content(cur); + subResult = attachmentWithIMAPBodyInternal(body, nextPartID); + attachments->addObject(subResult); + + count ++; + } + + attachment = new IMAPMultipart(); + attachment->setPartID(partID); + if (strcasecmp(body_mpart->bd_media_subtype, "alternative") == 0) { + attachment->setPartType(PartTypeMultipartAlternative); + } + else if (strcasecmp(body_mpart->bd_media_subtype, "related") == 0) { + attachment->setPartType(PartTypeMultipartRelated); + } + attachment->setMimeType(String::stringWithUTF8Format("multipart/%s", body_mpart->bd_media_subtype)); + attachment->setParts(attachments); + + attachments->release(); + + return (IMAPMultipart *) attachment->autorelease(); +} + +HashMap * IMAPPart::serializable() +{ + HashMap * result = AbstractPart::serializable(); + if (partID() != NULL) { + result->setObjectForKey(MCSTR("partID"), partID()); + } + String * encodingString; + switch (encoding()) { + case Encoding7Bit: + encodingString = MCSTR("7bit"); + break; + case Encoding8Bit: + default: + encodingString = MCSTR("8bit"); + break; + case EncodingBinary: + encodingString = MCSTR("binary"); + break; + case EncodingBase64: + encodingString = MCSTR("base64"); + break; + case EncodingQuotedPrintable: + encodingString = MCSTR("quoted-printable"); + break; + case EncodingUUEncode: + encodingString = MCSTR("uuencode"); + break; + } + result->setObjectForKey(MCSTR("encoding"), encodingString); + String * sizeString = String::stringWithUTF8Format("%lu", size()); + result->setObjectForKey(MCSTR("size"), sizeString); + return result; +} + +void IMAPPart::importSerializable(HashMap * serializable) +{ + AbstractPart::importSerializable(serializable); + String * partID = (String *) serializable->objectForKey(MCSTR("partID")); + setPartID(partID); + String * encodingString = (String *) serializable->objectForKey(MCSTR("encoding")); + if (encodingString != NULL) { + Encoding encoding = Encoding8Bit; + if (encodingString->isEqual(MCSTR("7bit"))) { + encoding = Encoding7Bit; + } + else if (encodingString->isEqual(MCSTR("8bit"))) { + encoding = Encoding8Bit; + } + else if (encodingString->isEqual(MCSTR("binary"))) { + encoding = EncodingBinary; + } + else if (encodingString->isEqual(MCSTR("base64"))) { + encoding = EncodingBase64; + } + else if (encodingString->isEqual(MCSTR("quoted-printable"))) { + encoding = EncodingQuotedPrintable; + } + else if (encodingString->isEqual(MCSTR("uuencode"))) { + encoding = EncodingUUEncode; + } + setEncoding(encoding); + } + String * sizeString = (String *) serializable->objectForKey(MCSTR("size")); + if (sizeString != NULL) { + setSize(sizeString->unsignedIntValue()); + } +} + +static void * createObject() +{ + return new IMAPPart(); +} + +INITIALIZE(IMAPPart) +{ + Object::registerObjectConstructor("mailcore::IMAPPart", &createObject); +} + diff --git a/src/core/imap/MCIMAPSearchExpression.cc b/src/core/imap/MCIMAPSearchExpression.cc deleted file mode 100644 index b3467e59..00000000 --- a/src/core/imap/MCIMAPSearchExpression.cc +++ /dev/null @@ -1,406 +0,0 @@ -#include "MCIMAPSearchExpression.h" - -using namespace mailcore; - -void IMAPSearchExpression::init() -{ - mKind = IMAPSearchKindNone; - mHeader = NULL; - mValue = NULL; - mLongNumber = 0; - mUids = NULL; - mLeftExpression = NULL; - mRightExpression = NULL; -} - -IMAPSearchExpression::IMAPSearchExpression() -{ - init(); -} - -IMAPSearchExpression::IMAPSearchExpression(IMAPSearchExpression * other) -{ - init(); - mKind = other->mKind; - mLongNumber = other->mLongNumber; - MC_SAFE_REPLACE_COPY(String, mHeader, other->mHeader); - MC_SAFE_REPLACE_COPY(String, mValue, other->mValue); - MC_SAFE_REPLACE_COPY(IndexSet, mUids, other->mUids); - MC_SAFE_REPLACE_COPY(IMAPSearchExpression, mLeftExpression, other->mLeftExpression); - MC_SAFE_REPLACE_COPY(IMAPSearchExpression, mRightExpression, other->mRightExpression); -} - -IMAPSearchExpression::~IMAPSearchExpression() -{ - MC_SAFE_RELEASE(mHeader); - MC_SAFE_RELEASE(mValue); - MC_SAFE_RELEASE(mUids); - MC_SAFE_RELEASE(mLeftExpression); - MC_SAFE_RELEASE(mRightExpression); -} - -String * IMAPSearchExpression::description() -{ - switch (mKind) { - default: - case IMAPSearchKindNone: - return String::stringWithUTF8Format("<%s:%p None>", MCUTF8(className()), this); - case IMAPSearchKindAll: - return String::stringWithUTF8Format("<%s:%p ALL>", MCUTF8(className()), this); - case IMAPSearchKindFrom: - return String::stringWithUTF8Format("<%s:%p From %s>", MCUTF8(className()), this, - MCUTF8(mValue->description())); - case IMAPSearchKindTo: - return String::stringWithUTF8Format("<%s:%p To %s>", MCUTF8(className()), this, - MCUTF8(mValue->description())); - case IMAPSearchKindCc: - return String::stringWithUTF8Format("<%s:%p Cc %s>", MCUTF8(className()), this, - MCUTF8(mValue->description())); - case IMAPSearchKindBcc: - return String::stringWithUTF8Format("<%s:%p Bcc %s>", MCUTF8(className()), this, - MCUTF8(mValue->description())); - case IMAPSearchKindRecipient: - return String::stringWithUTF8Format("<%s:%p Recipient %s>", MCUTF8(className()), this, - MCUTF8(mValue->description())); - case IMAPSearchKindSubject: - return String::stringWithUTF8Format("<%s:%p Subject %s>", MCUTF8(className()), this, - MCUTF8(mValue->description())); - case IMAPSearchKindUIDs: - return String::stringWithUTF8Format("<%s:%p UIDs %s>", MCUTF8(className()), this, - MCUTF8(mUids->description())); - case IMAPSearchKindContent: - return String::stringWithUTF8Format("<%s:%p Content %s>", MCUTF8(className()), this, - MCUTF8(mValue->description())); - case IMAPSearchKindHeader: - return String::stringWithUTF8Format("<%s:%p Header %s %s>", MCUTF8(className()), this, - MCUTF8(mHeader->description()), MCUTF8(mValue->description())); - case IMAPSearchKindGmailThreadID: - return String::stringWithUTF8Format("<%s:%p X-GM-THRID %llu>", MCUTF8(className()), this, - mLongNumber); - case IMAPSearchKindOr: - return String::stringWithUTF8Format("<%s:%p Or %s %s>", MCUTF8(className()), this, - MCUTF8(mLeftExpression->description()), MCUTF8(mRightExpression->description())); - case IMAPSearchKindAnd: - return String::stringWithUTF8Format("<%s:%p And %s %s>", MCUTF8(className()), this, - MCUTF8(mLeftExpression->description()), MCUTF8(mRightExpression->description())); - } -} - -Object * IMAPSearchExpression::copy() -{ - return new IMAPSearchExpression(this); -} - -IMAPSearchExpression * IMAPSearchExpression::searchFrom(String * value) -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindFrom; - MC_SAFE_REPLACE_COPY(String, expr->mValue, value); - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchTo(String * value) -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindTo; - MC_SAFE_REPLACE_COPY(String, expr->mValue, value); - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchCc(String * value) -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindCc; - MC_SAFE_REPLACE_COPY(String, expr->mValue, value); - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchBcc(String * value) -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindBcc; - MC_SAFE_REPLACE_COPY(String, expr->mValue, value); - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchRecipient(String * value) -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindRecipient; - MC_SAFE_REPLACE_COPY(String, expr->mValue, value); - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchAll() -{ - IMAPSearchExpression *expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindAll; - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchSubject(String * value) -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindSubject; - MC_SAFE_REPLACE_COPY(String, expr->mValue, value); - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchContent(String * value) -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindContent; - MC_SAFE_REPLACE_COPY(String, expr->mValue, value); - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchBody(String * value) -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindBody; - MC_SAFE_REPLACE_COPY(String, expr->mValue, value); - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchUIDs(IndexSet * uids) -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindUIDs; - MC_SAFE_REPLACE_COPY(IndexSet, expr->mUids, uids); - return (IMAPSearchExpression *) expr->autorelease(); -} - - -IMAPSearchExpression * IMAPSearchExpression::searchHeader(String * header, String * value) -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindHeader; - MC_SAFE_REPLACE_COPY(String, expr->mHeader, header); - MC_SAFE_REPLACE_COPY(String, expr->mValue, value); - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchRead() -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindRead; - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchUnread() -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindUnread; - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchFlagged() -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindFlagged; - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchUnflagged() -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindUnflagged; - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchAnswered() -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindAnswered; - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchUnanswered() -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindUnanswered; - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchDraft() -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindDraft; - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchUndraft() -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindUndraft; - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchDeleted() -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindDeleted; - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchSpam() -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindSpam; - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchBeforeDate(time_t date) -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindBeforeDate; - expr->mLongNumber = (uint64_t) date; - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchOnDate(time_t date) -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindOnDate; - expr->mLongNumber = (uint64_t) date; - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchSinceDate(time_t date) -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindSinceDate; - expr->mLongNumber = (uint64_t) date; - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchBeforeReceivedDate(time_t date) -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindBeforeReceivedDate; - expr->mLongNumber = (uint64_t) date; - return (IMAPSearchExpression *) expr->autorelease(); -} -IMAPSearchExpression * IMAPSearchExpression::searchOnReceivedDate(time_t date) -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindOnReceivedDate; - expr->mLongNumber = (uint64_t) date; - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchSinceReceivedDate(time_t date) -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindSinceReceivedDate; - expr->mLongNumber = (uint64_t) date; - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchSizeLarger(uint32_t size) -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindSizeLarger; - expr->mLongNumber = size; - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchSizeSmaller(uint32_t size) -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindSizeSmaller; - expr->mLongNumber = size; - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchGmailThreadID(uint64_t number) -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindGmailThreadID; - expr->mLongNumber = number; - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchGmailMessageID(uint64_t number) -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindGmailMessageID; - expr->mLongNumber = number; - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchGmailRaw(String * searchExpr) -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindGmailRaw; - MC_SAFE_REPLACE_COPY(String, expr->mValue, searchExpr); - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchAnd(IMAPSearchExpression * left, IMAPSearchExpression * right) -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindAnd; - MC_SAFE_REPLACE_RETAIN(IMAPSearchExpression, expr->mLeftExpression, left); - MC_SAFE_REPLACE_RETAIN(IMAPSearchExpression, expr->mRightExpression, right); - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchOr(IMAPSearchExpression * left, IMAPSearchExpression * right) -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindOr; - MC_SAFE_REPLACE_RETAIN(IMAPSearchExpression, expr->mLeftExpression, left); - MC_SAFE_REPLACE_RETAIN(IMAPSearchExpression, expr->mRightExpression, right); - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchExpression * IMAPSearchExpression::searchNot(IMAPSearchExpression * notExpr) -{ - IMAPSearchExpression * expr = new IMAPSearchExpression(); - expr->mKind = IMAPSearchKindNot; - MC_SAFE_REPLACE_RETAIN(IMAPSearchExpression, expr->mLeftExpression, notExpr); - return (IMAPSearchExpression *) expr->autorelease(); -} - -IMAPSearchKind IMAPSearchExpression::kind() -{ - return mKind; -} - -String * IMAPSearchExpression::header() -{ - return mHeader; -} - -String * IMAPSearchExpression::value() -{ - return mValue; -} - -uint64_t IMAPSearchExpression::longNumber() -{ - return mLongNumber; -} - -time_t IMAPSearchExpression::date() -{ - return (time_t) mLongNumber; -} - -IndexSet * IMAPSearchExpression::uids() -{ - return mUids; -} - -IMAPSearchExpression * IMAPSearchExpression::leftExpression() -{ - return mLeftExpression; -} - -IMAPSearchExpression * IMAPSearchExpression::rightExpression() -{ - return mRightExpression; -} - - diff --git a/src/core/imap/MCIMAPSearchExpression.cpp b/src/core/imap/MCIMAPSearchExpression.cpp new file mode 100644 index 00000000..b3467e59 --- /dev/null +++ b/src/core/imap/MCIMAPSearchExpression.cpp @@ -0,0 +1,406 @@ +#include "MCIMAPSearchExpression.h" + +using namespace mailcore; + +void IMAPSearchExpression::init() +{ + mKind = IMAPSearchKindNone; + mHeader = NULL; + mValue = NULL; + mLongNumber = 0; + mUids = NULL; + mLeftExpression = NULL; + mRightExpression = NULL; +} + +IMAPSearchExpression::IMAPSearchExpression() +{ + init(); +} + +IMAPSearchExpression::IMAPSearchExpression(IMAPSearchExpression * other) +{ + init(); + mKind = other->mKind; + mLongNumber = other->mLongNumber; + MC_SAFE_REPLACE_COPY(String, mHeader, other->mHeader); + MC_SAFE_REPLACE_COPY(String, mValue, other->mValue); + MC_SAFE_REPLACE_COPY(IndexSet, mUids, other->mUids); + MC_SAFE_REPLACE_COPY(IMAPSearchExpression, mLeftExpression, other->mLeftExpression); + MC_SAFE_REPLACE_COPY(IMAPSearchExpression, mRightExpression, other->mRightExpression); +} + +IMAPSearchExpression::~IMAPSearchExpression() +{ + MC_SAFE_RELEASE(mHeader); + MC_SAFE_RELEASE(mValue); + MC_SAFE_RELEASE(mUids); + MC_SAFE_RELEASE(mLeftExpression); + MC_SAFE_RELEASE(mRightExpression); +} + +String * IMAPSearchExpression::description() +{ + switch (mKind) { + default: + case IMAPSearchKindNone: + return String::stringWithUTF8Format("<%s:%p None>", MCUTF8(className()), this); + case IMAPSearchKindAll: + return String::stringWithUTF8Format("<%s:%p ALL>", MCUTF8(className()), this); + case IMAPSearchKindFrom: + return String::stringWithUTF8Format("<%s:%p From %s>", MCUTF8(className()), this, + MCUTF8(mValue->description())); + case IMAPSearchKindTo: + return String::stringWithUTF8Format("<%s:%p To %s>", MCUTF8(className()), this, + MCUTF8(mValue->description())); + case IMAPSearchKindCc: + return String::stringWithUTF8Format("<%s:%p Cc %s>", MCUTF8(className()), this, + MCUTF8(mValue->description())); + case IMAPSearchKindBcc: + return String::stringWithUTF8Format("<%s:%p Bcc %s>", MCUTF8(className()), this, + MCUTF8(mValue->description())); + case IMAPSearchKindRecipient: + return String::stringWithUTF8Format("<%s:%p Recipient %s>", MCUTF8(className()), this, + MCUTF8(mValue->description())); + case IMAPSearchKindSubject: + return String::stringWithUTF8Format("<%s:%p Subject %s>", MCUTF8(className()), this, + MCUTF8(mValue->description())); + case IMAPSearchKindUIDs: + return String::stringWithUTF8Format("<%s:%p UIDs %s>", MCUTF8(className()), this, + MCUTF8(mUids->description())); + case IMAPSearchKindContent: + return String::stringWithUTF8Format("<%s:%p Content %s>", MCUTF8(className()), this, + MCUTF8(mValue->description())); + case IMAPSearchKindHeader: + return String::stringWithUTF8Format("<%s:%p Header %s %s>", MCUTF8(className()), this, + MCUTF8(mHeader->description()), MCUTF8(mValue->description())); + case IMAPSearchKindGmailThreadID: + return String::stringWithUTF8Format("<%s:%p X-GM-THRID %llu>", MCUTF8(className()), this, + mLongNumber); + case IMAPSearchKindOr: + return String::stringWithUTF8Format("<%s:%p Or %s %s>", MCUTF8(className()), this, + MCUTF8(mLeftExpression->description()), MCUTF8(mRightExpression->description())); + case IMAPSearchKindAnd: + return String::stringWithUTF8Format("<%s:%p And %s %s>", MCUTF8(className()), this, + MCUTF8(mLeftExpression->description()), MCUTF8(mRightExpression->description())); + } +} + +Object * IMAPSearchExpression::copy() +{ + return new IMAPSearchExpression(this); +} + +IMAPSearchExpression * IMAPSearchExpression::searchFrom(String * value) +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindFrom; + MC_SAFE_REPLACE_COPY(String, expr->mValue, value); + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchTo(String * value) +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindTo; + MC_SAFE_REPLACE_COPY(String, expr->mValue, value); + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchCc(String * value) +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindCc; + MC_SAFE_REPLACE_COPY(String, expr->mValue, value); + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchBcc(String * value) +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindBcc; + MC_SAFE_REPLACE_COPY(String, expr->mValue, value); + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchRecipient(String * value) +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindRecipient; + MC_SAFE_REPLACE_COPY(String, expr->mValue, value); + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchAll() +{ + IMAPSearchExpression *expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindAll; + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchSubject(String * value) +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindSubject; + MC_SAFE_REPLACE_COPY(String, expr->mValue, value); + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchContent(String * value) +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindContent; + MC_SAFE_REPLACE_COPY(String, expr->mValue, value); + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchBody(String * value) +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindBody; + MC_SAFE_REPLACE_COPY(String, expr->mValue, value); + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchUIDs(IndexSet * uids) +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindUIDs; + MC_SAFE_REPLACE_COPY(IndexSet, expr->mUids, uids); + return (IMAPSearchExpression *) expr->autorelease(); +} + + +IMAPSearchExpression * IMAPSearchExpression::searchHeader(String * header, String * value) +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindHeader; + MC_SAFE_REPLACE_COPY(String, expr->mHeader, header); + MC_SAFE_REPLACE_COPY(String, expr->mValue, value); + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchRead() +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindRead; + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchUnread() +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindUnread; + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchFlagged() +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindFlagged; + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchUnflagged() +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindUnflagged; + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchAnswered() +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindAnswered; + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchUnanswered() +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindUnanswered; + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchDraft() +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindDraft; + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchUndraft() +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindUndraft; + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchDeleted() +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindDeleted; + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchSpam() +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindSpam; + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchBeforeDate(time_t date) +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindBeforeDate; + expr->mLongNumber = (uint64_t) date; + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchOnDate(time_t date) +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindOnDate; + expr->mLongNumber = (uint64_t) date; + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchSinceDate(time_t date) +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindSinceDate; + expr->mLongNumber = (uint64_t) date; + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchBeforeReceivedDate(time_t date) +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindBeforeReceivedDate; + expr->mLongNumber = (uint64_t) date; + return (IMAPSearchExpression *) expr->autorelease(); +} +IMAPSearchExpression * IMAPSearchExpression::searchOnReceivedDate(time_t date) +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindOnReceivedDate; + expr->mLongNumber = (uint64_t) date; + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchSinceReceivedDate(time_t date) +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindSinceReceivedDate; + expr->mLongNumber = (uint64_t) date; + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchSizeLarger(uint32_t size) +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindSizeLarger; + expr->mLongNumber = size; + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchSizeSmaller(uint32_t size) +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindSizeSmaller; + expr->mLongNumber = size; + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchGmailThreadID(uint64_t number) +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindGmailThreadID; + expr->mLongNumber = number; + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchGmailMessageID(uint64_t number) +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindGmailMessageID; + expr->mLongNumber = number; + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchGmailRaw(String * searchExpr) +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindGmailRaw; + MC_SAFE_REPLACE_COPY(String, expr->mValue, searchExpr); + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchAnd(IMAPSearchExpression * left, IMAPSearchExpression * right) +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindAnd; + MC_SAFE_REPLACE_RETAIN(IMAPSearchExpression, expr->mLeftExpression, left); + MC_SAFE_REPLACE_RETAIN(IMAPSearchExpression, expr->mRightExpression, right); + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchOr(IMAPSearchExpression * left, IMAPSearchExpression * right) +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindOr; + MC_SAFE_REPLACE_RETAIN(IMAPSearchExpression, expr->mLeftExpression, left); + MC_SAFE_REPLACE_RETAIN(IMAPSearchExpression, expr->mRightExpression, right); + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchExpression * IMAPSearchExpression::searchNot(IMAPSearchExpression * notExpr) +{ + IMAPSearchExpression * expr = new IMAPSearchExpression(); + expr->mKind = IMAPSearchKindNot; + MC_SAFE_REPLACE_RETAIN(IMAPSearchExpression, expr->mLeftExpression, notExpr); + return (IMAPSearchExpression *) expr->autorelease(); +} + +IMAPSearchKind IMAPSearchExpression::kind() +{ + return mKind; +} + +String * IMAPSearchExpression::header() +{ + return mHeader; +} + +String * IMAPSearchExpression::value() +{ + return mValue; +} + +uint64_t IMAPSearchExpression::longNumber() +{ + return mLongNumber; +} + +time_t IMAPSearchExpression::date() +{ + return (time_t) mLongNumber; +} + +IndexSet * IMAPSearchExpression::uids() +{ + return mUids; +} + +IMAPSearchExpression * IMAPSearchExpression::leftExpression() +{ + return mLeftExpression; +} + +IMAPSearchExpression * IMAPSearchExpression::rightExpression() +{ + return mRightExpression; +} + + diff --git a/src/core/imap/MCIMAPSession.cc b/src/core/imap/MCIMAPSession.cc deleted file mode 100755 index f286cc52..00000000 --- a/src/core/imap/MCIMAPSession.cc +++ /dev/null @@ -1,3940 +0,0 @@ -#include "MCWin32.h" // Should be included first. - -#include "MCIMAPSession.h" - -#include -#include -#include - -#include "MCDefines.h" -#include "MCIMAPSearchExpression.h" -#include "MCIMAPFolder.h" -#include "MCIMAPMessage.h" -#include "MCIMAPPart.h" -#include "MCMessageHeader.h" -#include "MCAbstractPart.h" -#include "MCIMAPProgressCallback.h" -#include "MCIMAPNamespace.h" -#include "MCIMAPSyncResult.h" -#include "MCIMAPFolderStatus.h" -#include "MCConnectionLogger.h" -#include "MCConnectionLoggerUtils.h" -#include "MCHTMLRenderer.h" -#include "MCString.h" -#include "MCUtils.h" -#include "MCHTMLRendererIMAPDataCallback.h" -#include "MCHTMLBodyRendererTemplateCallback.h" -#include "MCCertificateUtils.h" -#include "MCIMAPIdentity.h" -#include "MCLibetpan.h" - -using namespace mailcore; - -enum { - STATE_DISCONNECTED, - STATE_CONNECTED, - STATE_LOGGEDIN, - STATE_SELECTED, -}; - -String * mailcore::IMAPNamespacePersonal = NULL; -String * mailcore::IMAPNamespaceOther = NULL; -String * mailcore::IMAPNamespaceShared = NULL; - -static Array * resultsWithError(int r, clist * list, ErrorCode * pError); - -INITIALIZE(IMAPSEssion) -{ - AutoreleasePool * pool = new AutoreleasePool(); - IMAPNamespacePersonal = (String *) MCSTR("IMAPNamespacePersonal")->retain(); - IMAPNamespaceOther = (String *) MCSTR("IMAPNamespaceOther")->retain(); - IMAPNamespaceShared = (String *) MCSTR("IMAPNamespaceShared")->retain(); - - pool->release(); -} - -#define MAX_IDLE_DELAY (28 * 60) - -#define LOCK() pthread_mutex_lock(&mIdleLock) -#define UNLOCK() pthread_mutex_unlock(&mIdleLock) - -static struct mailimap_flag_list * flags_to_lep(MessageFlag value) -{ - struct mailimap_flag_list * flag_list; - - flag_list = mailimap_flag_list_new_empty(); - - if ((value & MessageFlagSeen) != 0) { - mailimap_flag_list_add(flag_list, mailimap_flag_new_seen()); - } - - if ((value & MessageFlagFlagged) != 0) { - mailimap_flag_list_add(flag_list, mailimap_flag_new_flagged()); - } - - if ((value & MessageFlagDeleted) != 0) { - mailimap_flag_list_add(flag_list, mailimap_flag_new_deleted()); - } - - if ((value & MessageFlagAnswered) != 0) { - mailimap_flag_list_add(flag_list, mailimap_flag_new_answered()); - } - - if ((value & MessageFlagDraft) != 0) { - mailimap_flag_list_add(flag_list, mailimap_flag_new_draft()); - } - - if ((value & MessageFlagForwarded) != 0) { - mailimap_flag_list_add(flag_list, mailimap_flag_new_flag_keyword(strdup("$Forwarded"))); - } - - if ((value & MessageFlagMDNSent) != 0) { - mailimap_flag_list_add(flag_list, mailimap_flag_new_flag_keyword(strdup("$MDNSent"))); - } - - if ((value & MessageFlagSubmitPending) != 0) { - mailimap_flag_list_add(flag_list, mailimap_flag_new_flag_keyword(strdup("$SubmitPending"))); - } - - if ((value & MessageFlagSubmitted) != 0) { - mailimap_flag_list_add(flag_list, mailimap_flag_new_flag_keyword(strdup("$Submitted"))); - } - - return flag_list; -} - -static MessageFlag flag_from_lep(struct mailimap_flag * flag) -{ - switch (flag->fl_type) { - case MAILIMAP_FLAG_ANSWERED: - return MessageFlagAnswered; - case MAILIMAP_FLAG_FLAGGED: - return MessageFlagFlagged; - case MAILIMAP_FLAG_DELETED: - return MessageFlagDeleted; - case MAILIMAP_FLAG_SEEN: - return MessageFlagSeen; - case MAILIMAP_FLAG_DRAFT: - return MessageFlagDraft; - case MAILIMAP_FLAG_KEYWORD: - if (strcasecmp(flag->fl_data.fl_keyword, "$Forwarded") == 0) { - return MessageFlagForwarded; - } - else if (strcasecmp(flag->fl_data.fl_keyword, "$MDNSent") == 0) { - return MessageFlagMDNSent; - } - else if (strcasecmp(flag->fl_data.fl_keyword, "$SubmitPending") == 0) { - return MessageFlagSubmitPending; - } - else if (strcasecmp(flag->fl_data.fl_keyword, "$Submitted") == 0) { - return MessageFlagSubmitted; - } - } - - return MessageFlagNone; -} - -static MessageFlag flags_from_lep_att_dynamic(struct mailimap_msg_att_dynamic * att_dynamic) -{ - if (att_dynamic->att_list == NULL) - return MessageFlagNone; - - MessageFlag flags; - clistiter * iter; - - flags = MessageFlagNone; - for(iter = clist_begin(att_dynamic->att_list) ;iter != NULL ; iter = clist_next(iter)) { - struct mailimap_flag_fetch * flag_fetch; - struct mailimap_flag * flag; - - flag_fetch = (struct mailimap_flag_fetch *) clist_content(iter); - if (flag_fetch->fl_type != MAILIMAP_FLAG_FETCH_OTHER) { - continue; - } - - flag = flag_fetch->fl_flag; - flags = (MessageFlag) (flags | flag_from_lep(flag)); - } - - return flags; -} - -static bool isKnownCustomFlag(const char * keyword) -{ - return !(strcmp(keyword, "$MDNSent") != 0 && strcmp(keyword, "$Forwarded") != 0 && strcmp(keyword, "$SubmitPending") != 0 && strcmp(keyword, "$Submitted") != 0); -} - -static Array * custom_flags_from_lep_att_dynamic(struct mailimap_msg_att_dynamic * att_dynamic) -{ - if (att_dynamic->att_list == NULL) - return NULL; - - clistiter * iter; - bool hasCustomFlags = false; - - for (iter = clist_begin(att_dynamic->att_list); iter != NULL; iter = clist_next(iter)) { - struct mailimap_flag_fetch * flag_fetch; - struct mailimap_flag * flag; - - flag_fetch = (struct mailimap_flag_fetch *) clist_content(iter); - if (flag_fetch->fl_type != MAILIMAP_FLAG_FETCH_OTHER) { - continue; - } - - flag = flag_fetch->fl_flag; - if (flag->fl_type == MAILIMAP_FLAG_KEYWORD) { - if (!isKnownCustomFlag(flag->fl_data.fl_keyword)) { - hasCustomFlags = true; - } - } - } - - if (!hasCustomFlags) - return NULL; - - Array * result = Array::array(); - for (iter = clist_begin(att_dynamic->att_list); iter != NULL; iter = clist_next(iter)) { - struct mailimap_flag_fetch * flag_fetch; - struct mailimap_flag * flag; - - flag_fetch = (struct mailimap_flag_fetch *) clist_content(iter); - if (flag_fetch->fl_type != MAILIMAP_FLAG_FETCH_OTHER) { - continue; - } - - flag = flag_fetch->fl_flag; - if (flag->fl_type == MAILIMAP_FLAG_KEYWORD) { - if (!isKnownCustomFlag(flag->fl_data.fl_keyword)) { - String * customFlag; - customFlag = String::stringWithUTF8Characters(flag->fl_data.fl_keyword); - result->addObject(customFlag); - } - } - } - - return result; -} - -#pragma mark set conversion - -static Array * arrayFromSet(struct mailimap_set * imap_set) -{ - Array * result; - clistiter * iter; - - result = Array::array(); - for(iter = clist_begin(imap_set->set_list) ; iter != NULL ; iter = clist_next(iter)) { - struct mailimap_set_item * item; - unsigned long i; - - item = (struct mailimap_set_item *) clist_content(iter); - for(i = item->set_first ; i <= item->set_last ; i ++) { - Value * nb; - - nb = Value::valueWithUnsignedLongValue(i); - result->addObject(nb); - } - } - - return result; -} - -static clist * splitSet(struct mailimap_set * set, unsigned int splitCount) -{ - struct mailimap_set * current_set; - clist * result; - unsigned int count; - - result = clist_new(); - - current_set = NULL; - count = 0; - for(clistiter * iter = clist_begin(set->set_list) ; iter != NULL ; iter = clist_next(iter)) { - struct mailimap_set_item * item; - - if (current_set == NULL) { - current_set = mailimap_set_new_empty(); - } - - item = (struct mailimap_set_item *) clist_content(iter); - mailimap_set_add_interval(current_set, item->set_first, item->set_last); - count ++; - - if (count >= splitCount) { - clist_append(result, current_set); - current_set = NULL; - count = 0; - } - } - if (current_set != NULL) { - clist_append(result, current_set); - } - - return result; -} - -static struct mailimap_set * setFromIndexSet(IndexSet * indexSet) -{ - struct mailimap_set * imap_set; - - imap_set = mailimap_set_new_empty(); - for(unsigned int i = 0 ; i < indexSet->rangesCount() ; i ++) { - uint64_t left = RangeLeftBound(indexSet->allRanges()[i]); - uint64_t right = RangeRightBound(indexSet->allRanges()[i]); - if (right == UINT64_MAX) { - right = 0; - } - mailimap_set_add_interval(imap_set, (uint32_t) left, (uint32_t) right); - } - - return imap_set; -} - -static IndexSet * indexSetFromSet(struct mailimap_set * imap_set) -{ - IndexSet * indexSet = IndexSet::indexSet(); - for(clistiter * cur = clist_begin(imap_set->set_list) ; cur != NULL ; cur = clist_next(cur)) { - struct mailimap_set_item * item = (struct mailimap_set_item *) clist_content(cur); - if (item->set_last == 0) { - indexSet->addRange(RangeMake(item->set_first, UINT64_MAX)); - } - else { - indexSet->addRange(RangeMake(item->set_first, item->set_last - item->set_first)); - } - } - return indexSet; -} - -void IMAPSession::init() -{ - mHostname = NULL; - mPort = 0; - mUsername = NULL; - mPassword = NULL; - mOAuth2Token = NULL; - mAuthType = AuthTypeSASLNone; - mConnectionType = ConnectionTypeClear; - mCheckCertificateEnabled = true; - mVoIPEnabled = true; - mDelimiter = 0; - - mBodyProgressEnabled = true; - mIdleEnabled = false; - mXListEnabled = false; - mQResyncEnabled = false; - mCondstoreEnabled = false; - mIdentityEnabled = false; - mNamespaceEnabled = false; - mCompressionEnabled = false; - mIsGmail = false; - mAllowsNewPermanentFlags = 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); - mCanIdle = true; - mState = STATE_DISCONNECTED; - mImap = NULL; - mProgressCallback = NULL; - mProgressItemsCount = 0; - mConnectionLogger = NULL; - mAutomaticConfigurationEnabled = true; - mAutomaticConfigurationDone = false; - mShouldDisconnect = false; - mLoginResponse = NULL; - mGmailUserDisplayName = NULL; -} - -IMAPSession::IMAPSession() -{ - init(); -} - -IMAPSession::~IMAPSession() -{ - MC_SAFE_RELEASE(mGmailUserDisplayName); - MC_SAFE_RELEASE(mLoginResponse); - MC_SAFE_RELEASE(mClientIdentity); - MC_SAFE_RELEASE(mServerIdentity); - 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); - pthread_mutex_destroy(&mIdleLock); -} - -void IMAPSession::setHostname(String * hostname) -{ - MC_SAFE_REPLACE_COPY(String, mHostname, hostname); -} - -String * IMAPSession::hostname() -{ - return mHostname; -} - -void IMAPSession::setPort(unsigned int port) -{ - mPort = port; -} - -unsigned int IMAPSession::port() -{ - return mPort; -} - -void IMAPSession::setUsername(String * username) -{ - MC_SAFE_REPLACE_COPY(String, mUsername, username); -} - -String * IMAPSession::username() -{ - return mUsername; -} - -void IMAPSession::setPassword(String * password) -{ - MC_SAFE_REPLACE_COPY(String, mPassword, password); -} - -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; -} - -AuthType IMAPSession::authType() -{ - return mAuthType; -} - -void IMAPSession::setConnectionType(ConnectionType connectionType) -{ - mConnectionType = connectionType; -} - -ConnectionType IMAPSession::connectionType() -{ - return mConnectionType; -} - -void IMAPSession::setTimeout(time_t timeout) -{ - mTimeout = timeout; -} - -time_t IMAPSession::timeout() -{ - return mTimeout; -} - -void IMAPSession::setCheckCertificateEnabled(bool enabled) -{ - mCheckCertificateEnabled = enabled; -} - -bool IMAPSession::isCheckCertificateEnabled() -{ - return mCheckCertificateEnabled; -} - -void IMAPSession::setVoIPEnabled(bool enabled) -{ - mVoIPEnabled = enabled; -} - -bool IMAPSession::isVoIPEnabled() -{ - return mVoIPEnabled; -} - -static bool hasError(int errorCode) -{ - return ((errorCode != MAILIMAP_NO_ERROR) && (errorCode != MAILIMAP_NO_ERROR_AUTHENTICATED) && - (errorCode != MAILIMAP_NO_ERROR_NON_AUTHENTICATED)); -} - -bool IMAPSession::checkCertificate() -{ - if (!isCheckCertificateEnabled()) - return true; - return mailcore::checkCertificate(mImap->imap_stream, hostname()); -} - -void IMAPSession::body_progress(size_t current, size_t maximum, void * context) -{ - IMAPSession * session; - - session = (IMAPSession *) context; - session->bodyProgress((unsigned int) current, (unsigned int) maximum); -} - -void IMAPSession::items_progress(size_t current, size_t maximum, void * context) -{ - IMAPSession * session; - - session = (IMAPSession *) context; - session->itemsProgress((unsigned int) current, (unsigned int) maximum); -} - -static void logger(mailimap * imap, int log_type, const char * buffer, size_t size, void * context) -{ - IMAPSession * session = (IMAPSession *) context; - - if (session->connectionLogger() == NULL) - 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()->log(session, type, data); - } - else { - session->connectionLogger()->log(session, type, NULL); - } -} - -void IMAPSession::setup() -{ - MCAssert(mImap == NULL); - - mImap = mailimap_new(0, NULL); - mailimap_set_timeout(mImap, timeout()); - mailimap_set_progress_callback(mImap, body_progress, IMAPSession::items_progress, this); - mailimap_set_logger(mImap, logger, this); -} - -void IMAPSession::unsetup() -{ - mailimap * imap; - - LOCK(); - imap = mImap; - mImap = NULL; - mCanIdle = false; - UNLOCK(); - - if (imap != NULL) { - if (imap->imap_stream != NULL) { - mailstream_close(imap->imap_stream); - imap->imap_stream = NULL; - } - mailimap_free(imap); - imap = NULL; - } - - mState = STATE_DISCONNECTED; -} - -void IMAPSession::connect(ErrorCode * pError) -{ - int r; - - setup(); - - MCLog("connect %s", MCUTF8DESC(this)); - - MCAssert(mState == STATE_DISCONNECTED); - - switch (mConnectionType) { - case ConnectionTypeStartTLS: - MCLog("STARTTLS connect"); - r = mailimap_socket_connect_voip(mImap, MCUTF8(mHostname), mPort, isVoIPEnabled()); - if (hasError(r)) { - * pError = ErrorConnection; - goto close; - } - - r = mailimap_socket_starttls(mImap); - if (hasError(r)) { - MCLog("no TLS %i", r); - * pError = ErrorTLSNotAvailable; - goto close; - } - break; - - case ConnectionTypeTLS: - r = mailimap_ssl_connect_voip(mImap, MCUTF8(mHostname), mPort, isVoIPEnabled()); - MCLog("ssl connect %s %u %u", MCUTF8(mHostname), mPort, r); - if (hasError(r)) { - MCLog("connect error %i", r); - * pError = ErrorConnection; - goto close; - } - if (!checkCertificate()) { - MCLog("ssl connect certificate ERROR %d", r); - * pError = ErrorCertificate; - goto close; - } - - break; - - default: - MCLog("socket connect %s %u", MCUTF8(mHostname), mPort); - r = mailimap_socket_connect_voip(mImap, MCUTF8(mHostname), mPort, isVoIPEnabled()); - MCLog("socket connect %i", r); - if (hasError(r)) { - MCLog("connect error %i", r); - * pError = ErrorConnection; - goto close; - } - break; - } - - mailstream_low * low; - String * identifierString; - char * identifier; - - low = mailstream_get_low(mImap->imap_stream); - identifierString = String::stringWithUTF8Format("%s@%s:%u", MCUTF8(mUsername), MCUTF8(mHostname), mPort); - identifier = strdup(identifierString->UTF8Characters()); - mailstream_low_set_identifier(low, identifier); - - if (mImap->imap_response != NULL) { - MC_SAFE_REPLACE_RETAIN(String, mWelcomeString, String::stringWithUTF8Characters(mImap->imap_response)); - mYahooServer = (mWelcomeString->locationOfString(MCSTR("yahoo.com")) != -1); - } - - 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"); - return; - -close: - unsetup(); -} - -void IMAPSession::connectIfNeeded(ErrorCode * pError) -{ - if (mShouldDisconnect) { - disconnect(); - mShouldDisconnect = false; - } - - if (mState == STATE_DISCONNECTED) { - connect(pError); - } - else { - * pError = ErrorNone; - } -} - -void IMAPSession::loginIfNeeded(ErrorCode * pError) -{ - connectIfNeeded(pError); - if (* pError != ErrorNone) - return; - - if (mState == STATE_CONNECTED) { - login(pError); - } - else { - * pError = ErrorNone; - } -} - -void IMAPSession::login(ErrorCode * pError) -{ - int r; - - MCLog("login"); - - 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); - utf8password = MCUTF8(mPassword); - if (utf8username == NULL) { - utf8username = ""; - } - if (utf8password == NULL) { - utf8password = ""; - } - - switch (mAuthType) { - case 0: - default: - r = mailimap_login(mImap, utf8username, utf8password); - break; - - case AuthTypeSASLCRAMMD5: - r = mailimap_authenticate(mImap, "CRAM-MD5", - MCUTF8(mHostname), - NULL, - NULL, - utf8username, utf8username, - utf8password, NULL); - break; - - case AuthTypeSASLPlain: - r = mailimap_authenticate(mImap, "PLAIN", - MCUTF8(mHostname), - NULL, - NULL, - utf8username, utf8username, - utf8password, NULL); - break; - - case AuthTypeSASLGSSAPI: - // needs to be tested - r = mailimap_authenticate(mImap, "GSSAPI", - MCUTF8(mHostname), - NULL, - NULL, - utf8username, utf8username, - utf8password, NULL /* realm */); - break; - - case AuthTypeSASLDIGESTMD5: - r = mailimap_authenticate(mImap, "DIGEST-MD5", - MCUTF8(mHostname), - NULL, - NULL, - utf8username, utf8username, - utf8password, NULL); - break; - - case AuthTypeSASLLogin: - r = mailimap_authenticate(mImap, "LOGIN", - MCUTF8(mHostname), - NULL, - NULL, - utf8username, utf8username, - utf8password, NULL); - break; - - case AuthTypeSASLSRP: - r = mailimap_authenticate(mImap, "SRP", - MCUTF8(mHostname), - NULL, - NULL, - utf8username, utf8username, - utf8password, NULL); - break; - - case AuthTypeSASLNTLM: - r = mailimap_authenticate(mImap, "NTLM", - MCUTF8(mHostname), - NULL, - NULL, - utf8username, utf8username, - utf8password, NULL/* realm */); - break; - - case AuthTypeSASLKerberosV4: - r = mailimap_authenticate(mImap, "KERBEROS_V4", - MCUTF8(mHostname), - NULL, - NULL, - utf8username, utf8username, - utf8password, NULL/* realm */); - break; - - case AuthTypeXOAuth2: - case AuthTypeXOAuth2Outlook: - r = mailimap_oauth2_authenticate(mImap, utf8username, MCUTF8(mOAuth2Token)); - break; - } - if (r == MAILIMAP_ERROR_STREAM) { - mShouldDisconnect = true; - * pError = ErrorConnection; - return; - } - else if (r == MAILIMAP_ERROR_PARSE) { - * pError = ErrorParse; - return; - } - else if (hasError(r)) { - String * response; - - response = MCSTR(""); - if (mImap->imap_response != NULL) { - response = String::stringWithUTF8Characters(mImap->imap_response); - } - if (response->locationOfString(MCSTR("not enabled for IMAP use")) != -1) { - * pError = ErrorGmailIMAPNotEnabled; - } - else if (response->locationOfString(MCSTR("bandwidth limits")) != -1) { - * pError = ErrorGmailExceededBandwidthLimit; - } - else if (response->locationOfString(MCSTR("Too many simultaneous connections")) != -1) { - * pError = ErrorGmailTooManySimultaneousConnections; - } - else if (response->locationOfString(MCSTR("Maximum number of connections")) != -1) { - * pError = ErrorGmailTooManySimultaneousConnections; - } - else if (response->locationOfString(MCSTR("Application-specific password required")) != -1) { - * pError = ErrorGmailApplicationSpecificPasswordRequired; - } - else if (response->locationOfString(MCSTR("http://me.com/move")) != -1) { - * pError = ErrorMobileMeMoved; - } - else if (response->locationOfString(MCSTR("OCF12")) != -1) { - * pError = ErrorYahooUnavailable; - } - else { - * pError = ErrorAuthentication; - } - return; - } - - String * loginResponse = MCSTR(""); - if (mIsGmail) { - if (mImap->imap_response != NULL) { - loginResponse = String::stringWithUTF8Characters(mImap->imap_response); - - int location = loginResponse->locationOfString(MCSTR(" authenticated (Success)")); - if (location != -1) { - String * emailAndName = loginResponse->substringToIndex(location); - location = emailAndName->locationOfString(MCSTR(" ")); - MC_SAFE_RELEASE(mGmailUserDisplayName); - mGmailUserDisplayName = emailAndName->substringFromIndex(location + 1); - mGmailUserDisplayName->retain(); - } - } - } - MC_SAFE_REPLACE_COPY(String, mLoginResponse, loginResponse); - - 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()) { - bool hasDefaultNamespace = false; - if (isNamespaceEnabled()) { - HashMap * result = fetchNamespace(pError); - if (* pError != ErrorNone) { - MCLog("fetch namespace failed"); - return; - } - IMAPNamespace * personalNamespace = (IMAPNamespace *) result->objectForKey(IMAPNamespacePersonal); - if (personalNamespace != NULL) { - setDefaultNamespace(personalNamespace); - mDelimiter = defaultNamespace()->mainDelimiter(); - hasDefaultNamespace = true; - } - } - - if (!hasDefaultNamespace) { - 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(MCSTR(""), folder->delimiter()); - setDefaultNamespace(defaultNamespace); - } - - if (isIdentityEnabled()) { - IMAPIdentity * serverIdentity = identity(clientIdentity(), pError); - if (* pError != ErrorNone) { - // Ignore identity errors - MCLog("fetch identity failed"); - } - else { - 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"); -} - -void IMAPSession::selectIfNeeded(String * folder, ErrorCode * pError) -{ - loginIfNeeded(pError); - if (* pError != ErrorNone) - return; - - if (mState == STATE_SELECTED) { - MCAssert(mCurrentFolder != NULL); - if (mCurrentFolder->caseInsensitiveCompare(folder) != 0) { - select(folder, pError); - } - } - else if (mState == STATE_LOGGEDIN) { - select(folder, pError); - } - else { - * pError = ErrorNone; - } -} - -static uint64_t get_mod_sequence_value(mailimap * session) -{ - uint64_t mod_sequence_value; - clistiter * cur; - - mod_sequence_value = 0; - for(cur = clist_begin(session->imap_response_info->rsp_extension_list) ; cur != NULL ; cur = clist_next(cur)) { - struct mailimap_extension_data * ext_data; - struct mailimap_condstore_resptextcode * resptextcode; - - ext_data = (struct mailimap_extension_data *) clist_content(cur); - if (ext_data->ext_extension->ext_id != MAILIMAP_EXTENSION_CONDSTORE) { - continue; - } - if (ext_data->ext_type != MAILIMAP_CONDSTORE_TYPE_RESP_TEXT_CODE) { - continue; - } - - resptextcode = (struct mailimap_condstore_resptextcode *) ext_data->ext_data; - switch (resptextcode->cs_type) { - case MAILIMAP_CONDSTORE_RESPTEXTCODE_HIGHESTMODSEQ: - mod_sequence_value = resptextcode->cs_data.cs_modseq_value; - break; - case MAILIMAP_CONDSTORE_RESPTEXTCODE_NOMODSEQ: - mod_sequence_value = 0; - break; - } - } - - return mod_sequence_value; -} - -void IMAPSession::select(String * folder, ErrorCode * pError) -{ - int r; - - MCLog("select"); - MCAssert(mState == STATE_LOGGEDIN || mState == STATE_SELECTED); - - 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; - } - else if (r == MAILIMAP_ERROR_PARSE) { - * pError = ErrorParse; - return; - } - else if (hasError(r)) { - * pError = ErrorNonExistantFolder; - mState = STATE_LOGGEDIN; - MC_SAFE_RELEASE(mCurrentFolder); - return; - } - - MC_SAFE_REPLACE_COPY(String, mCurrentFolder, folder); - - if (mImap->imap_selection_info != NULL) { - mUIDValidity = mImap->imap_selection_info->sel_uidvalidity; - mUIDNext = mImap->imap_selection_info->sel_uidnext; - if (mImap->imap_selection_info->sel_has_exists) { - mFolderMsgCount = (unsigned int) (mImap->imap_selection_info->sel_exists); - } else { - mFolderMsgCount = -1; - } - - if (mImap->imap_selection_info->sel_first_unseen) { - mFirstUnseenUid = mImap->imap_selection_info->sel_first_unseen; - } else { - mFirstUnseenUid = 0; - } - - if (mImap->imap_selection_info->sel_perm_flags) { - clistiter * cur; - - struct mailimap_flag_perm * perm_flag; - for(cur = clist_end(mImap->imap_selection_info->sel_perm_flags) ; cur != NULL ; - cur = clist_previous(cur)) { - perm_flag = (struct mailimap_flag_perm *)clist_content(cur); - mAllowsNewPermanentFlags = perm_flag->fl_type == MAILIMAP_FLAG_PERM_ALL; - if (mAllowsNewPermanentFlags) { - break; - } - } - } - - mModSequenceValue = get_mod_sequence_value(mImap); - } - - mState = STATE_SELECTED; - * pError = ErrorNone; - MCLog("select ok"); -} - - - - - -IMAPFolderStatus * IMAPSession::folderStatus(String * folder, ErrorCode * pError) -{ - int r; - - MCLog("status"); - MCAssert(mState == STATE_LOGGEDIN || mState == STATE_SELECTED); - - struct mailimap_mailbox_data_status * status; - - struct mailimap_status_att_list * status_att_list; - - status_att_list = mailimap_status_att_list_new_empty(); - mailimap_status_att_list_add(status_att_list, MAILIMAP_STATUS_ATT_UNSEEN); - mailimap_status_att_list_add(status_att_list, MAILIMAP_STATUS_ATT_MESSAGES); - mailimap_status_att_list_add(status_att_list, MAILIMAP_STATUS_ATT_RECENT); - mailimap_status_att_list_add(status_att_list, MAILIMAP_STATUS_ATT_UIDNEXT); - mailimap_status_att_list_add(status_att_list, MAILIMAP_STATUS_ATT_UIDVALIDITY); - if (mCondstoreEnabled) { - mailimap_status_att_list_add(status_att_list, MAILIMAP_STATUS_ATT_HIGHESTMODSEQ); - } - - r = mailimap_status(mImap, MCUTF8(folder), status_att_list, &status); - - IMAPFolderStatus * fs; - fs = new IMAPFolderStatus(); - fs->autorelease(); - - MCLog("status error : %i", r); - if (r == MAILIMAP_ERROR_STREAM) { - mShouldDisconnect = true; - * pError = ErrorConnection; - MCLog("status error : %s %i", MCUTF8DESC(this), * pError); - return fs; - } - else if (r == MAILIMAP_ERROR_PARSE) { - * pError = ErrorParse; - return fs; - } - else if (hasError(r)) { - * pError = ErrorNonExistantFolder; - return fs; - } - - clistiter * cur; - - - if (status != NULL) { - - struct mailimap_status_info * status_info; - for(cur = clist_begin(status->st_info_list) ; cur != NULL ; - cur = clist_next(cur)) { - - status_info = (struct mailimap_status_info *) clist_content(cur); - - switch (status_info->st_att) { - case MAILIMAP_STATUS_ATT_UNSEEN: - fs->setUnseenCount(status_info->st_value); - break; - case MAILIMAP_STATUS_ATT_MESSAGES: - fs->setMessageCount(status_info->st_value); - break; - case MAILIMAP_STATUS_ATT_RECENT: - fs->setRecentCount(status_info->st_value); - break; - case MAILIMAP_STATUS_ATT_UIDNEXT: - fs->setUidNext(status_info->st_value); - break; - case MAILIMAP_STATUS_ATT_UIDVALIDITY: - fs->setUidValidity(status_info->st_value); - break; - case MAILIMAP_STATUS_ATT_EXTENSION: { - struct mailimap_extension_data * ext_data = status_info->st_ext_data; - if (ext_data->ext_extension == &mailimap_extension_condstore) { - struct mailimap_condstore_status_info * status_info = (struct mailimap_condstore_status_info *) ext_data->ext_data; - fs->setHighestModSeqValue(status_info->cs_highestmodseq_value); - } - break; - } - } - } - - - } - - mailimap_status_att_list_free(status_att_list); - - - return fs; -} - -void IMAPSession::noop(ErrorCode * pError) -{ - int r; - - if (mImap == NULL) - return; - - MCLog("connect"); - loginIfNeeded(pError); - if (* pError != ErrorNone) { - return; - } - if (mImap->imap_stream != NULL) { - r = mailimap_noop(mImap); - if (r == MAILIMAP_ERROR_STREAM) { - * pError = ErrorConnection; - } - if (r == MAILIMAP_ERROR_NOOP) { - * pError = ErrorNoop; - } - } -} - -#pragma mark mailbox flags conversion - -static struct { - const char * name; - int flag; -} mb_keyword_flag[] = { - {"Inbox", IMAPFolderFlagInbox}, - {"AllMail", IMAPFolderFlagAllMail}, - {"Sent", IMAPFolderFlagSentMail}, - {"Spam", IMAPFolderFlagSpam}, - {"Starred", IMAPFolderFlagStarred}, - {"Trash", IMAPFolderFlagTrash}, - {"Important", IMAPFolderFlagImportant}, - {"Drafts", IMAPFolderFlagDrafts}, - {"Archive", IMAPFolderFlagArchive}, - {"All", IMAPFolderFlagAll}, - {"Junk", IMAPFolderFlagJunk}, - {"Flagged", IMAPFolderFlagFlagged}, -}; - -static int imap_mailbox_flags_to_flags(struct mailimap_mbx_list_flags * imap_flags) -{ - int flags; - clistiter * cur; - - flags = 0; - if (imap_flags->mbf_type == MAILIMAP_MBX_LIST_FLAGS_SFLAG) { - switch (imap_flags->mbf_sflag) { - case MAILIMAP_MBX_LIST_SFLAG_MARKED: - flags |= IMAPFolderFlagMarked; - break; - case MAILIMAP_MBX_LIST_SFLAG_NOSELECT: - flags |= IMAPFolderFlagNoSelect; - break; - case MAILIMAP_MBX_LIST_SFLAG_UNMARKED: - flags |= IMAPFolderFlagUnmarked; - break; - } - } - - for(cur = clist_begin(imap_flags->mbf_oflags) ; cur != NULL ; - cur = clist_next(cur)) { - struct mailimap_mbx_list_oflag * oflag; - - oflag = (struct mailimap_mbx_list_oflag *) clist_content(cur); - - switch (oflag->of_type) { - case MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS: - flags |= IMAPFolderFlagNoInferiors; - break; - - case MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT: - for(unsigned int i = 0 ; i < sizeof(mb_keyword_flag) / sizeof(mb_keyword_flag[0]) ; i ++) { - if (strcasecmp(mb_keyword_flag[i].name, oflag->of_flag_ext) == 0) { - flags |= mb_keyword_flag[i].flag; - } - } - break; - } - } - - return flags; -} - -static Array * resultsWithError(int r, clist * list, ErrorCode * pError) -{ - clistiter * cur; - Array * result; - - result = Array::array(); - if (r == MAILIMAP_ERROR_STREAM) { - * pError = ErrorConnection; - return NULL; - } - else if (r == MAILIMAP_ERROR_PARSE) { - * pError = ErrorParse; - return NULL; - } - else if (hasError(r)) { - * pError = ErrorNonExistantFolder; - return NULL; - } - - for(cur = clist_begin(list) ; cur != NULL ; cur = cur->next) { - struct mailimap_mailbox_list * mb_list; - IMAPFolderFlag flags; - IMAPFolder * folder; - String * path; - - mb_list = (struct mailimap_mailbox_list *) cur->data; - - flags = IMAPFolderFlagNone; - if (mb_list->mb_flag != NULL) - flags = (IMAPFolderFlag) imap_mailbox_flags_to_flags(mb_list->mb_flag); - - folder = new IMAPFolder(); - path = String::stringWithUTF8Characters(mb_list->mb_name); - if (path->uppercaseString()->isEqual(MCSTR("INBOX"))) { - folder->setPath(MCSTR("INBOX")); - } - else { - folder->setPath(path); - } - folder->setDelimiter(mb_list->mb_delimiter); - folder->setFlags(flags); - - result->addObject(folder); - - folder->release(); - } - - mailimap_list_result_free(list); - - * pError = ErrorNone; - return result; -} - -// Deprecated -char IMAPSession::fetchDelimiterIfNeeded(char defaultDelimiter, ErrorCode * pError) -{ - int r; - clist * imap_folders; - IMAPFolder * folder; - Array * folders; - - if (defaultDelimiter != 0) - return defaultDelimiter; - - r = mailimap_list(mImap, "", "", &imap_folders); - folders = resultsWithError(r, imap_folders, pError); - if (* pError == ErrorConnection) - mShouldDisconnect = true; - if (* pError != ErrorNone) - return 0; - - if (folders->count() > 0) { - folder = (IMAPFolder *) folders->objectAtIndex(0); - } - else { - folder = NULL; - } - if (folder == NULL) - return 0; - - * pError = ErrorNone; - return folder->delimiter(); -} - -Array * /* IMAPFolder */ IMAPSession::fetchSubscribedFolders(ErrorCode * pError) -{ - int r; - clist * imap_folders; - - MCLog("fetch subscribed"); - loginIfNeeded(pError); - if (* pError != ErrorNone) - return NULL; - - if (mDelimiter == 0) { - char delimiter; - - delimiter = fetchDelimiterIfNeeded(mDelimiter, pError); - if (* pError != ErrorNone) - return NULL; - - //setDelimiter(delimiter); - mDelimiter = delimiter; - } - - String * prefix; - prefix = defaultNamespace()->mainPrefix(); - if (prefix == NULL) { - prefix = MCSTR(""); - } - if (prefix->length() > 0) { - 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); - 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; - - loginIfNeeded(pError); - if (* pError != ErrorNone) - return NULL; - - if (mDelimiter == 0) { - char delimiter; - - delimiter = fetchDelimiterIfNeeded(mDelimiter, pError); - if (* pError != ErrorNone) - return NULL; - - //setDelimiter(delimiter); - mDelimiter = delimiter; - } - - String * prefix = NULL; - if (defaultNamespace()) { - prefix = defaultNamespace()->mainPrefix(); - } - if (prefix == NULL) { - prefix = MCSTR(""); - } - if (prefix->length() > 0) { - if (!prefix->hasSuffix(String::stringWithUTF8Format("%c", mDelimiter))) { - prefix = prefix->stringByAppendingUTF8Format("%c", mDelimiter); - } - } - - if (mXListEnabled) { - r = mailimap_xlist(mImap, MCUTF8(prefix), "*", &imap_folders); - } - else { - r = mailimap_list(mImap, MCUTF8(prefix), "*", &imap_folders); - } - Array * result = resultsWithError(r, imap_folders, pError); - if (* pError == ErrorConnection) - mShouldDisconnect = true; - - if (result != NULL) { - bool hasInbox = false; - mc_foreacharray(IMAPFolder, folder, result) { - if (folder->path()->isEqual(MCSTR("INBOX"))) { - hasInbox = true; - } - } - - if (!hasInbox) { - r = mailimap_list(mImap, "", "INBOX", &imap_folders); - Array * inboxResult = resultsWithError(r, imap_folders, pError); - if (* pError == ErrorConnection) - mShouldDisconnect = true; - result->addObjectsFromArray(inboxResult); - } - } - - return result; -} - -void IMAPSession::renameFolder(String * folder, String * otherName, ErrorCode * pError) -{ - int r; - - selectIfNeeded(MCSTR("INBOX"), pError); - if (* pError != ErrorNone) - return; - - r = mailimap_rename(mImap, MCUTF8(folder), MCUTF8(otherName)); - if (r == MAILIMAP_ERROR_STREAM) { - mShouldDisconnect = true; - * pError = ErrorConnection; - return; - } - else if (r == MAILIMAP_ERROR_PARSE) { - * pError = ErrorParse; - return; - } - else if (hasError(r)) { - * pError = ErrorRename; - return; - } - * pError = ErrorNone; -} - -void IMAPSession::deleteFolder(String * folder, ErrorCode * pError) -{ - int r; - - selectIfNeeded(MCSTR("INBOX"), pError); - if (* pError != ErrorNone) - return; - - r = mailimap_delete(mImap, MCUTF8(folder)); - if (r == MAILIMAP_ERROR_STREAM) { - mShouldDisconnect = true; - * pError = ErrorConnection; - return; - } - else if (r == MAILIMAP_ERROR_PARSE) { - * pError = ErrorParse; - return; - } - else if (hasError(r)) { - * pError = ErrorDelete; - return; - } - * pError = ErrorNone; -} - -void IMAPSession::createFolder(String * folder, ErrorCode * pError) -{ - int r; - - selectIfNeeded(MCSTR("INBOX"), pError); - if (* pError != ErrorNone) - return; - - r = mailimap_create(mImap, MCUTF8(folder)); - if (r == MAILIMAP_ERROR_STREAM) { - mShouldDisconnect = true; - * pError = ErrorConnection; - return; - } - else if (r == MAILIMAP_ERROR_PARSE) { - * pError = ErrorParse; - return; - } - else if (hasError(r)) { - * pError = ErrorCreate; - return; - } - - * pError = ErrorNone; - subscribeFolder(folder, pError); -} - -void IMAPSession::subscribeFolder(String * folder, ErrorCode * pError) -{ - int r; - - selectIfNeeded(MCSTR("INBOX"), pError); - if (* pError != ErrorNone) - return; - - r = mailimap_subscribe(mImap, MCUTF8(folder)); - if (r == MAILIMAP_ERROR_STREAM) { - mShouldDisconnect = true; - * pError = ErrorConnection; - return; - } - else if (r == MAILIMAP_ERROR_PARSE) { - * pError = ErrorParse; - return; - } - else if (hasError(r)) { - * pError = ErrorSubscribe; - return; - } - * pError = ErrorNone; -} - -void IMAPSession::unsubscribeFolder(String * folder, ErrorCode * pError) -{ - int r; - - selectIfNeeded(MCSTR("INBOX"), pError); - if (* pError != ErrorNone) - return; - - r = mailimap_unsubscribe(mImap, MCUTF8(folder)); - if (r == MAILIMAP_ERROR_STREAM) { - mShouldDisconnect = true; - * pError = ErrorConnection; - return; - } - else if (r == MAILIMAP_ERROR_PARSE) { - * pError = ErrorParse; - return; - } - else if (hasError(r)) { - * pError = ErrorSubscribe; - return; - } - * pError = ErrorNone; -} - -void IMAPSession::appendMessage(String * folder, Data * messageData, MessageFlag flags, - IMAPProgressCallback * progressCallback, uint32_t * createdUID, ErrorCode * pError) -{ - this->appendMessageWithCustomFlags(folder, messageData, flags, NULL, progressCallback, createdUID, pError); -} - -void IMAPSession::appendMessageWithCustomFlags(String * folder, Data * messageData, MessageFlag flags, Array * customFlags, - IMAPProgressCallback * progressCallback, uint32_t * createdUID, ErrorCode * pError) -{ - this->appendMessageWithCustomFlagsAndDate(folder, messageData, flags, NULL, (time_t) -1, progressCallback, createdUID, pError); -} - -void IMAPSession::appendMessageWithCustomFlagsAndDate(String * folder, Data * messageData, MessageFlag flags, Array * customFlags, time_t date, - IMAPProgressCallback * progressCallback, uint32_t * createdUID, ErrorCode * pError) -{ - int r; - struct mailimap_flag_list * flag_list; - uint32_t uidvalidity; - uint32_t uidresult; - - selectIfNeeded(folder, pError); - if (* pError != ErrorNone) - return; - - mProgressCallback = progressCallback; - bodyProgress(0, messageData->length()); - - flag_list = NULL; - flag_list = flags_to_lep(flags); - if (customFlags != NULL) { - for (unsigned int i = 0 ; i < customFlags->count() ; i ++) { - struct mailimap_flag * f; - String * customFlag = (String *) customFlags->objectAtIndex(i); - - f = mailimap_flag_new_flag_keyword(strdup(customFlag->UTF8Characters())); - mailimap_flag_list_add(flag_list, f); - } - } - struct mailimap_date_time * imap_date = NULL; - if (date != (time_t) -1) { - imap_date = imapDateFromTimestamp(date); - } - r = mailimap_uidplus_append(mImap, MCUTF8(folder), flag_list, imap_date, messageData->bytes(), messageData->length(), - &uidvalidity, &uidresult); - if (imap_date != NULL) { - mailimap_date_time_free(imap_date); - } - mailimap_flag_list_free(flag_list); - - bodyProgress(messageData->length(), messageData->length()); - mProgressCallback = NULL; - - if (r == MAILIMAP_ERROR_STREAM) { - mShouldDisconnect = true; - * pError = ErrorConnection; - return; - } - else if (r == MAILIMAP_ERROR_PARSE) { - * pError = ErrorParse; - return; - } - else if (hasError(r)) { - * pError = ErrorAppend; - return; - } - - * createdUID = uidresult; - * pError = ErrorNone; -} - -void IMAPSession::copyMessages(String * folder, IndexSet * uidSet, String * destFolder, - HashMap ** pUidMapping, ErrorCode * pError) -{ - int r; - struct mailimap_set * set; - struct mailimap_set * src_uid; - struct mailimap_set * dest_uid; - uint32_t uidvalidity; - clist * setList; - IndexSet * uidSetResult; - HashMap * uidMapping = NULL; - - selectIfNeeded(folder, pError); - if (* pError != ErrorNone) - return; - - set = setFromIndexSet(uidSet); - if (clist_count(set->set_list) == 0) { - mailimap_set_free(set); - return; - } - - setList = splitSet(set, 10); - uidSetResult = NULL; - - for(clistiter * iter = clist_begin(setList) ; iter != NULL ; iter = clist_next(iter)) { - struct mailimap_set * current_set; - - current_set = (struct mailimap_set *) clist_content(iter); - - 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; - } - else if (r == MAILIMAP_ERROR_PARSE) { - * pError = ErrorParse; - goto release; - } - else if (hasError(r)) { - * pError = ErrorCopy; - goto release; - } - - if ((src_uid != NULL) && (dest_uid != NULL)) { - if (uidMapping == NULL) { - uidMapping = HashMap::hashMap(); - } - - Array * srcUidsArray = arrayFromSet(src_uid); - Array * destUidsArray = arrayFromSet(dest_uid); - - for(int i = 0 ; i < srcUidsArray->count() && i < destUidsArray->count() ; i ++) { - uidMapping->setObjectForKey(srcUidsArray->objectAtIndex(i), destUidsArray->objectAtIndex(i)); - } - } - - if (src_uid != NULL) { - mailimap_set_free(src_uid); - } - - if (dest_uid != NULL) { - mailimap_set_free(dest_uid); - } - } - if (pUidMapping != NULL) { - * pUidMapping = uidMapping; - } - * pError = ErrorNone; - - release: - - for(clistiter * iter = clist_begin(setList) ; iter != NULL ; iter = clist_next(iter)) { - struct mailimap_set * current_set; - - current_set = (struct mailimap_set *) clist_content(iter); - mailimap_set_free(current_set); - } - clist_free(setList); - mailimap_set_free(set); -} - -void IMAPSession::expunge(String * folder, ErrorCode * pError) -{ - int r; - - selectIfNeeded(folder, pError); - if (* pError != ErrorNone) - return; - - r = mailimap_expunge(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 = ErrorExpunge; - return; - } - * pError = ErrorNone; -} - -static int -fetch_imap(mailimap * imap, bool identifier_is_uid, uint32_t identifier, - struct mailimap_fetch_type * fetch_type, - char ** result, size_t * result_len) -{ - int r; - struct mailimap_msg_att * msg_att; - struct mailimap_msg_att_item * msg_att_item; - clist * fetch_result; - struct mailimap_set * set; - char * text; - size_t text_length; - clistiter * cur; - - set = mailimap_set_new_single(identifier); - if (identifier_is_uid) { - r = mailimap_uid_fetch(imap, set, fetch_type, &fetch_result); - } - else { - r = mailimap_fetch(imap, set, fetch_type, &fetch_result); - } - - mailimap_set_free(set); - - switch (r) { - case MAILIMAP_NO_ERROR: - break; - default: - return r; - } - - if (clist_isempty(fetch_result)) { - mailimap_fetch_list_free(fetch_result); - return MAILIMAP_ERROR_FETCH; - } - - msg_att = (struct mailimap_msg_att *) clist_begin(fetch_result)->data; - - text = NULL; - text_length = 0; - - for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; - cur = clist_next(cur)) { - msg_att_item = (struct mailimap_msg_att_item *) clist_content(cur); - - if (msg_att_item->att_type != MAILIMAP_MSG_ATT_ITEM_STATIC) { - continue; - } - - if (msg_att_item->att_data.att_static->att_type != - MAILIMAP_MSG_ATT_BODY_SECTION) { - continue; - } - - text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part; - msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL; - text_length = msg_att_item->att_data.att_static->att_data.att_body_section->sec_length; - } - - mailimap_fetch_list_free(fetch_result); - - if (text == NULL) - return MAILIMAP_ERROR_FETCH; - - * result = text; - * result_len = text_length; - - return MAILIMAP_NO_ERROR; -} - -HashMap * IMAPSession::fetchMessageNumberUIDMapping(String * folder, uint32_t fromUID, uint32_t toUID, - ErrorCode * pError) -{ - struct mailimap_set * imap_set; - struct mailimap_fetch_type * fetch_type; - clist * fetch_result; - HashMap * result; - struct mailimap_fetch_att * fetch_att; - int r; - clistiter * iter; - - selectIfNeeded(folder, pError); - if (* pError != ErrorNone) - return NULL; - - result = HashMap::hashMap(); - - imap_set = mailimap_set_new_interval(fromUID, toUID); - fetch_type = mailimap_fetch_type_new_fetch_att_list_empty(); - fetch_att = mailimap_fetch_att_new_uid(); - mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); - - r = mailimap_uid_fetch(mImap, imap_set, fetch_type, &fetch_result); - mailimap_fetch_type_free(fetch_type); - mailimap_set_free(imap_set); - - if (r == MAILIMAP_ERROR_STREAM) { - MCLog("error stream"); - mShouldDisconnect = true; - * pError = ErrorConnection; - return NULL; - } - else if (r == MAILIMAP_ERROR_PARSE) { - MCLog("error parse"); - * pError = ErrorParse; - return NULL; - } - else if (hasError(r)) { - MCLog("error fetch"); - * pError = ErrorFetch; - return NULL; - } - - for(iter = clist_begin(fetch_result) ; iter != NULL ; iter = clist_next(iter)) { - struct mailimap_msg_att * msg_att; - clistiter * item_iter; - uint32_t uid; - - msg_att = (struct mailimap_msg_att *) clist_content(iter); - uid = 0; - for(item_iter = clist_begin(msg_att->att_list) ; item_iter != NULL ; item_iter = clist_next(item_iter)) { - struct mailimap_msg_att_item * att_item; - - att_item = (struct mailimap_msg_att_item *) clist_content(item_iter); - if (att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { - struct mailimap_msg_att_static * att_static; - - att_static = att_item->att_data.att_static; - if (att_static->att_type == MAILIMAP_MSG_ATT_UID) { - uid = att_static->att_data.att_uid; - } - } - } - - if (uid < fromUID) { - uid = 0; - } - - if (uid != 0) { - result->setObjectForKey(Value::valueWithUnsignedLongValue(msg_att->att_number), - Value::valueWithUnsignedLongValue(uid)); - } - } - - mailimap_fetch_list_free(fetch_result); - * pError = ErrorNone; - - return result; -} - -struct msg_att_handler_data { - IMAPSession * self; - bool fetchByUID; - Array * result; - String * folder; - IMAPMessagesRequestKind requestKind; - uint32_t mLastFetchedSequenceNumber; - HashMap * mapping; - bool needsHeader; - bool needsBody; - bool needsFlags; - bool needsGmailLabels; - bool needsGmailMessageID; - bool needsGmailThreadID; - uint32_t startUid; -}; - -static void msg_att_handler(struct mailimap_msg_att * msg_att, void * context) -{ - clistiter * item_iter; - uint32_t uid; - IMAPMessage * msg; - bool hasHeader; - bool hasBody; - bool hasFlags; - bool hasGmailLabels; - bool hasGmailMessageID; - bool hasGmailThreadID; - struct msg_att_handler_data * msg_att_context; - // struct - IMAPSession * self; - bool fetchByUID; - Array * result; - String * folder; - IMAPMessagesRequestKind requestKind; - uint32_t mLastFetchedSequenceNumber; - HashMap * mapping; - bool needsHeader; - bool needsBody; - bool needsFlags; - bool needsGmailLabels; - bool needsGmailMessageID; - bool needsGmailThreadID; - uint32_t startUid; - - msg_att_context = (struct msg_att_handler_data *) context; - self = msg_att_context->self; - fetchByUID = msg_att_context->fetchByUID; - result = msg_att_context->result; - folder = msg_att_context->folder; - requestKind = msg_att_context->requestKind; - mLastFetchedSequenceNumber = msg_att_context->mLastFetchedSequenceNumber; - mapping = msg_att_context->mapping; - needsHeader = msg_att_context->needsHeader; - needsBody = msg_att_context->needsBody; - needsFlags = msg_att_context->needsFlags; - needsGmailLabels = msg_att_context->needsGmailLabels; - needsGmailMessageID = msg_att_context->needsGmailMessageID; - needsGmailThreadID = msg_att_context->needsGmailThreadID; - startUid = msg_att_context->startUid; - - hasHeader = false; - hasBody = false; - hasFlags = false; - hasGmailLabels = false; - hasGmailMessageID = false; - hasGmailThreadID = false; - - msg = new IMAPMessage(); - - uid = 0; - mLastFetchedSequenceNumber = msg_att->att_number; - if (mapping != NULL) { - uid = (uint32_t) ((Value *) mapping->objectForKey(Value::valueWithUnsignedLongValue(msg_att->att_number)))->longLongValue(); - } - msg->setSequenceNumber(msg_att->att_number); - for(item_iter = clist_begin(msg_att->att_list) ; item_iter != NULL ; item_iter = clist_next(item_iter)) { - struct mailimap_msg_att_item * att_item; - - att_item = (struct mailimap_msg_att_item *) clist_content(item_iter); - if (att_item->att_type == MAILIMAP_MSG_ATT_ITEM_DYNAMIC) { - MessageFlag flags; - - flags = flags_from_lep_att_dynamic(att_item->att_data.att_dyn); - msg->setFlags(flags); - msg->setOriginalFlags(flags); - hasFlags = true; - - Array * customFlags; - customFlags = custom_flags_from_lep_att_dynamic(att_item->att_data.att_dyn); - msg->setCustomFlags(customFlags); - } - else if (att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { - struct mailimap_msg_att_static * att_static; - - att_static = att_item->att_data.att_static; - if (att_static->att_type == MAILIMAP_MSG_ATT_UID) { - uid = att_static->att_data.att_uid; - } - else if (att_static->att_type == MAILIMAP_MSG_ATT_ENVELOPE) { - struct mailimap_envelope * env; - - MCLog("parse envelope %lu", (unsigned long) uid); - env = att_static->att_data.att_env; - msg->header()->importIMAPEnvelope(env); - hasHeader = true; - } - else if (att_static->att_type == MAILIMAP_MSG_ATT_BODY_SECTION) { - if ((requestKind & IMAPMessagesRequestKindFullHeaders) != 0 || - (requestKind & IMAPMessagesRequestKindExtraHeaders) != 0) { - char * bytes; - size_t length; - - bytes = att_static->att_data.att_body_section->sec_body_part; - length = att_static->att_data.att_body_section->sec_length; - - msg->header()->importHeadersData(Data::dataWithBytes(bytes, (unsigned int) length)); - hasHeader = true; - } - else { - char * references; - size_t ref_size; - - // references - references = att_static->att_data.att_body_section->sec_body_part; - ref_size = att_static->att_data.att_body_section->sec_length; - - msg->header()->importIMAPReferences(Data::dataWithBytes(references, (unsigned int) ref_size)); - } - } - else if (att_static->att_type == MAILIMAP_MSG_ATT_BODYSTRUCTURE) { - AbstractPart * mainPart; - - // bodystructure - mainPart = IMAPPart::attachmentWithIMAPBody(att_static->att_data.att_body); - msg->setMainPart(mainPart); - hasBody = true; - } - } - else if (att_item->att_type == MAILIMAP_MSG_ATT_ITEM_EXTENSION) { - struct mailimap_extension_data * ext_data; - - ext_data = att_item->att_data.att_extension_data; - if (ext_data->ext_extension == &mailimap_extension_condstore) { - struct mailimap_condstore_fetch_mod_resp * fetch_data; - - fetch_data = (struct mailimap_condstore_fetch_mod_resp *) ext_data->ext_data; - msg->setModSeqValue(fetch_data->cs_modseq_value); - } - else if (ext_data->ext_extension == &mailimap_extension_xgmlabels) { - struct mailimap_msg_att_xgmlabels * cLabels; - Array * labels; - clistiter * cur; - - labels = new Array(); - hasGmailLabels = true; - cLabels = (struct mailimap_msg_att_xgmlabels *) ext_data->ext_data; - for(cur = clist_begin(cLabels->att_labels) ; cur != NULL ; cur = clist_next(cur)) { - char * cLabel; - String * label; - - cLabel = (char *) clist_content(cur); - label = String::stringWithUTF8Characters(cLabel); - labels->addObject(label); - } - if (labels->count() > 0) { - msg->setGmailLabels(labels); - } - labels->release(); - } - else if (ext_data->ext_extension == &mailimap_extension_xgmthrid) { - uint64_t * threadID; - - threadID = (uint64_t *) ext_data->ext_data; - msg->setGmailThreadID(*threadID); - hasGmailThreadID = true; - } - else if (ext_data->ext_extension == &mailimap_extension_xgmmsgid) { - uint64_t * msgID; - - msgID = (uint64_t *) ext_data->ext_data; - msg->setGmailMessageID(*msgID); - hasGmailMessageID = true; - } - } - } - for(item_iter = clist_begin(msg_att->att_list) ; item_iter != NULL ; item_iter = clist_next(item_iter)) { - struct mailimap_msg_att_item * att_item; - - att_item = (struct mailimap_msg_att_item *) clist_content(item_iter); - if (att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { - struct mailimap_msg_att_static * att_static; - - att_static = att_item->att_data.att_static; - if (att_static->att_type == MAILIMAP_MSG_ATT_INTERNALDATE) { - msg->header()->importIMAPInternalDate(att_static->att_data.att_internal_date); - } else if (att_static->att_type == MAILIMAP_MSG_ATT_RFC822_SIZE) { - msg->setSize(att_static->att_data.att_rfc822_size); - } - } - } - - if (fetchByUID) { - if (uid < startUid) { - uid = 0; - } - } - - if (needsBody && !hasBody) { - msg->release(); - return; - } - if (needsHeader && !hasHeader) { - msg->release(); - return; - } - if (needsFlags && !hasFlags) { - msg->release(); - return; - } - if (needsGmailThreadID && !hasGmailThreadID) { - msg->release(); - return; - } - if (needsGmailMessageID && !hasGmailMessageID) { - msg->release(); - return; - } - if (uid != 0) { - msg->setUid(uid); - } - else { - msg->release(); - return; - } - - result->addObject(msg); - msg->release(); - - msg_att_context->mLastFetchedSequenceNumber = mLastFetchedSequenceNumber; -} - -IMAPSyncResult * IMAPSession::fetchMessages(String * folder, IMAPMessagesRequestKind requestKind, bool fetchByUID, - struct mailimap_set * imapset, uint64_t modseq, HashMap * mapping, uint32_t startUid, - IMAPProgressCallback * progressCallback, Array * extraHeaders, ErrorCode * pError) -{ - struct mailimap_fetch_type * fetch_type; - clist * fetch_result; - struct mailimap_qresync_vanished * vanished; - struct mailimap_fetch_att * fetch_att; - int r; - bool needsHeader; - bool needsBody; - bool needsFlags; - bool needsGmailLabels; - bool needsGmailMessageID; - bool needsGmailThreadID; - Array * messages; - IndexSet * vanishedMessages; - - selectIfNeeded(folder, pError); - if (* pError != ErrorNone) - return NULL; - - if (mNeedsMboxMailWorkaround && ((requestKind & IMAPMessagesRequestKindHeaders) != 0)) { - requestKind = (IMAPMessagesRequestKind) (requestKind & ~IMAPMessagesRequestKindHeaders); - requestKind = (IMAPMessagesRequestKind) (requestKind | IMAPMessagesRequestKindFullHeaders); - } - if (extraHeaders != NULL) { - requestKind = (IMAPMessagesRequestKind) (requestKind | IMAPMessagesRequestKindExtraHeaders); - } - - if ((requestKind & IMAPMessagesRequestKindHeaders) != 0) { - mProgressItemsCount = 0; - mProgressCallback = progressCallback; - } - - messages = Array::array(); - - needsHeader = false; - needsBody = false; - needsFlags = false; - needsGmailLabels = false; - needsGmailMessageID = false; - needsGmailThreadID = false; - clist * hdrlist = clist_new(); - - fetch_type = mailimap_fetch_type_new_fetch_att_list_empty(); - fetch_att = mailimap_fetch_att_new_uid(); - mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); - if ((requestKind & IMAPMessagesRequestKindFlags) != 0) { - MCLog("request flags"); - fetch_att = mailimap_fetch_att_new_flags(); - mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); - needsFlags = true; - } - if ((requestKind & IMAPMessagesRequestKindGmailLabels) != 0) { - MCLog("request flags"); - fetch_att = mailimap_fetch_att_new_xgmlabels(); - mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); - needsGmailLabels = true; - } - if ((requestKind & IMAPMessagesRequestKindGmailThreadID) != 0) { - fetch_att = mailimap_fetch_att_new_xgmthrid(); - mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); - needsGmailThreadID = true; - } - if ((requestKind & IMAPMessagesRequestKindGmailMessageID) != 0) { - fetch_att = mailimap_fetch_att_new_xgmmsgid(); - mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); - needsGmailMessageID = true; - } - if ((requestKind & IMAPMessagesRequestKindFullHeaders) != 0) { - char * header; - - MCLog("request envelope"); - - // most important header - header = strdup("Date"); - clist_append(hdrlist, header); - header = strdup("Subject"); - clist_append(hdrlist, header); - header = strdup("From"); - clist_append(hdrlist, header); - header = strdup("Sender"); - clist_append(hdrlist, header); - header = strdup("Reply-To"); - clist_append(hdrlist, header); - header = strdup("To"); - clist_append(hdrlist, header); - header = strdup("Cc"); - clist_append(hdrlist, header); - header = strdup("Message-ID"); - clist_append(hdrlist, header); - header = strdup("References"); - clist_append(hdrlist, header); - header = strdup("In-Reply-To"); - clist_append(hdrlist, header); - } - if ((requestKind & IMAPMessagesRequestKindHeaders) != 0) { - char * header; - - MCLog("request envelope"); - // envelope - fetch_att = mailimap_fetch_att_new_envelope(); - mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); - - // references header - header = strdup("References"); - clist_append(hdrlist, header); - if ((requestKind & IMAPMessagesRequestKindHeaderSubject) != 0) { - header = strdup("Subject"); - clist_append(hdrlist, header); - } - } - if ((requestKind & IMAPMessagesRequestKindSize) != 0) { - // message structure - MCLog("request size"); - fetch_att = mailimap_fetch_att_new_rfc822_size(); - mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); - } - - if ((requestKind & IMAPMessagesRequestKindStructure) != 0) { - // message structure - MCLog("request bodystructure"); - fetch_att = mailimap_fetch_att_new_bodystructure(); - mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); - needsBody = true; - } - if ((requestKind & IMAPMessagesRequestKindInternalDate) != 0) { - // internal date - fetch_att = mailimap_fetch_att_new_internaldate(); - mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); - } - if ((requestKind & IMAPMessagesRequestKindExtraHeaders) != 0) { - // custom header request - char * header; - - if (extraHeaders && extraHeaders->count() > 0) { - for (unsigned int i = 0; i < extraHeaders->count(); i++) { - String * headerString = (String *)extraHeaders->objectAtIndex(i); - header = strdup(headerString->UTF8Characters()); - clist_append(hdrlist, header); - } - } - } - - if (clist_begin(hdrlist) != NULL) { - struct mailimap_header_list * imap_hdrlist; - struct mailimap_section * section; - - imap_hdrlist = mailimap_header_list_new(hdrlist); - section = mailimap_section_new_header_fields(imap_hdrlist); - fetch_att = mailimap_fetch_att_new_body_peek_section(section); - mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); - needsHeader = true; - } - else { - clist_free(hdrlist); - } - - struct msg_att_handler_data msg_att_data; - - memset(&msg_att_data, 0, sizeof(msg_att_data)); - msg_att_data.self = this; - msg_att_data.fetchByUID = fetchByUID; - msg_att_data.result = messages; - msg_att_data.folder = folder; - msg_att_data.requestKind = requestKind; - msg_att_data.mLastFetchedSequenceNumber = mLastFetchedSequenceNumber; - msg_att_data.mapping = mapping; - msg_att_data.needsHeader = needsHeader; - msg_att_data.needsBody = needsBody; - msg_att_data.needsFlags = needsFlags; - msg_att_data.needsGmailLabels = needsGmailLabels; - msg_att_data.startUid = startUid; - msg_att_data.needsGmailMessageID = needsGmailMessageID; - msg_att_data.needsGmailThreadID = needsGmailThreadID; - mailimap_set_msg_att_handler(mImap, msg_att_handler, &msg_att_data); - - mBodyProgressEnabled = false; - vanished = NULL; - - if (fetchByUID) { - if ((modseq != 0) && (mCondstoreEnabled || mQResyncEnabled)) { - if (mQResyncEnabled) { - r = mailimap_uid_fetch_qresync(mImap, imapset, fetch_type, modseq, - &fetch_result, &vanished); - } - else { /* condstore */ - r = mailimap_uid_fetch_changedsince(mImap, imapset, fetch_type, modseq, - &fetch_result); - } - } - else { - r = mailimap_uid_fetch(mImap, imapset, fetch_type, &fetch_result); - } - } else { - if ((modseq != 0) && (mCondstoreEnabled || mQResyncEnabled)) { - if (mQResyncEnabled) { - r = mailimap_fetch_qresync(mImap, imapset, fetch_type, modseq, - &fetch_result, &vanished); - } - else { /* condstore */ - r = mailimap_fetch_changedsince(mImap, imapset, fetch_type, modseq, - &fetch_result); - } - } - else { - r = mailimap_fetch(mImap, imapset, fetch_type, &fetch_result); - } - } - - vanishedMessages = NULL; - if (vanished != NULL) { - vanishedMessages = indexSetFromSet(vanished->qr_known_uids); - } - - mBodyProgressEnabled = true; - - mProgressCallback = NULL; - - mLastFetchedSequenceNumber = msg_att_data.mLastFetchedSequenceNumber; - - mailimap_fetch_type_free(fetch_type); - - mailimap_set_msg_att_handler(mImap, NULL, NULL); - - if (r == MAILIMAP_ERROR_STREAM) { - MCLog("error stream"); - mShouldDisconnect = true; - * pError = ErrorConnection; - return NULL; - } - else if (r == MAILIMAP_ERROR_PARSE) { - MCLog("error parse"); - * pError = ErrorParse; - return NULL; - } - else if (hasError(r)) { - MCLog("error fetch"); - * pError = ErrorFetch; - return NULL; - } - - IMAPSyncResult * result; - result = new IMAPSyncResult(); - result->setModifiedOrAddedMessages(messages); - result->setVanishedMessages(vanishedMessages); - result->autorelease(); - - if ((requestKind & IMAPMessagesRequestKindHeaders) != 0) { - if (messages->count() == 0) { - unsigned int count; - - count = clist_count(fetch_result); - if (count > 0) { - requestKind = (IMAPMessagesRequestKind) (requestKind & ~IMAPMessagesRequestKindHeaders); - requestKind = (IMAPMessagesRequestKind) (requestKind | IMAPMessagesRequestKindFullHeaders); - - result = fetchMessages(folder, requestKind, fetchByUID, - imapset, modseq, NULL, startUid, progressCallback, extraHeaders, pError); - if (result != NULL) { - if (result->modifiedOrAddedMessages() != NULL) { - if (result->modifiedOrAddedMessages()->count() > 0) { - mNeedsMboxMailWorkaround = true; - } - } - } - } - } - } - - mailimap_fetch_list_free(fetch_result); - * pError = ErrorNone; - - return result; -} - -Array * IMAPSession::fetchMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, - IndexSet * uids, IMAPProgressCallback * progressCallback, ErrorCode * pError) -{ - return fetchMessagesByUIDWithExtraHeaders(folder, requestKind, uids, progressCallback, NULL, pError); -} - - -Array * IMAPSession::fetchMessagesByUIDWithExtraHeaders(String * folder, IMAPMessagesRequestKind requestKind, - IndexSet * uids, IMAPProgressCallback * progressCallback, - Array * extraHeaders, ErrorCode * pError) -{ - struct mailimap_set * imapset = setFromIndexSet(uids); - IMAPSyncResult * syncResult = fetchMessages(folder, requestKind, true, imapset, 0, NULL, 0, - progressCallback, extraHeaders, pError); - if (syncResult == NULL) { - mailimap_set_free(imapset); - return NULL; - } - Array * result = syncResult->modifiedOrAddedMessages(); - result->retain()->autorelease(); - mailimap_set_free(imapset); - return result; -} - -Array * IMAPSession::fetchMessagesByNumber(String * folder, IMAPMessagesRequestKind requestKind, - IndexSet * numbers, IMAPProgressCallback * progressCallback, - ErrorCode * pError) -{ - return fetchMessagesByNumberWithExtraHeaders(folder, requestKind, numbers, progressCallback, NULL, pError); -} - -Array * IMAPSession::fetchMessagesByNumberWithExtraHeaders(String * folder, IMAPMessagesRequestKind requestKind, - IndexSet * numbers, IMAPProgressCallback * progressCallback, - Array * extraHeaders, ErrorCode * pError) -{ - struct mailimap_set * imapset = setFromIndexSet(numbers); - IMAPSyncResult * syncResult = fetchMessages(folder, requestKind, false, imapset, 0, NULL, 0, - progressCallback, extraHeaders, pError); - if (syncResult == NULL) { - mailimap_set_free(imapset); - return NULL; - } - Array * result = syncResult->modifiedOrAddedMessages(); - result->retain()->autorelease(); - mailimap_set_free(imapset); - return result; -} - -static int fetch_rfc822(mailimap * session, bool identifier_is_uid, - uint32_t identifier, char ** result, size_t * result_len) -{ - struct mailimap_section * section; - struct mailimap_fetch_att * fetch_att; - struct mailimap_fetch_type * fetch_type; - - section = mailimap_section_new(NULL); - fetch_att = mailimap_fetch_att_new_body_peek_section(section); - fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); - int r = fetch_imap(session, identifier_is_uid, identifier, - fetch_type, result, result_len); - mailimap_fetch_type_free(fetch_type); - - return r; - -#if 0 - int r; - clist * fetch_list; - struct mailimap_section * section; - struct mailimap_fetch_att * fetch_att; - struct mailimap_fetch_type * fetch_type; - struct mailimap_set * set; - struct mailimap_msg_att * msg_att; - struct mailimap_msg_att_item * item; - int res; - clistiter * cur; - - section = mailimap_section_new(NULL); - fetch_att = mailimap_fetch_att_new_body_peek_section(section); - fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); - - set = mailimap_set_new_single(identifier); - - if (identifier_is_uid) { - r = mailimap_uid_fetch(session, set, fetch_type, &fetch_list); - } - else { - r = mailimap_fetch(session, set, fetch_type, &fetch_list); - } - - mailimap_set_free(set); - mailimap_fetch_type_free(fetch_type); - - if (r != MAILIMAP_NO_ERROR) { - res = r; - goto err; - } - - if (clist_isempty(fetch_list)) { - res = MAILIMAP_ERROR_FETCH; - goto free; - } - - msg_att = (struct mailimap_msg_att *) clist_begin(fetch_list)->data; - - for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; cur = clist_next(cur)) { - item = (struct mailimap_msg_att_item *) clist_content(cur); - - if (item->att_type != MAILIMAP_MSG_ATT_ITEM_STATIC) { - continue; - } - if (item->att_data.att_static->att_type != MAILIMAP_MSG_ATT_BODY_SECTION) { - continue; - } - - * result = item->att_data.att_static->att_data.att_body_section->sec_body_part; - item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL; - mailimap_fetch_list_free(fetch_list); - - return MAILIMAP_NO_ERROR; - } - - res = MAILIMAP_ERROR_FETCH; - -free: - mailimap_fetch_list_free(fetch_list); -err: - return res; -#endif -} - -Data * IMAPSession::fetchMessageByUID(String * folder, uint32_t uid, - IMAPProgressCallback * progressCallback, ErrorCode * pError) -{ - return fetchMessage(folder, true, uid, progressCallback, pError); -} - -Data * IMAPSession::fetchMessageByNumber(String * folder, uint32_t number, - IMAPProgressCallback * progressCallback, ErrorCode * pError) -{ - return fetchMessage(folder, false, number, progressCallback, pError); -} - -Data * IMAPSession::fetchMessage(String * folder, bool identifier_is_uid, uint32_t identifier, - IMAPProgressCallback * progressCallback, ErrorCode * pError) -{ - char * rfc822; - size_t rfc822_len; - int r; - Data * data; - - selectIfNeeded(folder, pError); - if (* pError != ErrorNone) - return NULL; - - mProgressItemsCount = 0; - mProgressCallback = progressCallback; - - rfc822 = NULL; - r = fetch_rfc822(mImap, identifier_is_uid, identifier, &rfc822, &rfc822_len); - if (r == MAILIMAP_NO_ERROR) { - size_t len; - - len = 0; - if (rfc822 != NULL) { - len = strlen(rfc822); - } - bodyProgress((unsigned int) len, (unsigned int) len); - } - mProgressCallback = NULL; - - if (r == MAILIMAP_ERROR_STREAM) { - mShouldDisconnect = true; - * pError = ErrorConnection; - return NULL; - } - else if (r == MAILIMAP_ERROR_PARSE) { - * pError = ErrorParse; - return NULL; - } - else if (hasError(r)) { - * pError = ErrorFetch; - return NULL; - } - - if (rfc822 == NULL) { - data = Data::data(); - } - else { - data = Data::dataWithBytes(rfc822, (unsigned int) rfc822_len); - } - - mailimap_nstring_free(rfc822); - * pError = ErrorNone; - - return data; -} - -Data * IMAPSession::fetchMessageAttachment(String * folder, bool identifier_is_uid, - uint32_t identifier, String * partID, - Encoding encoding, IMAPProgressCallback * progressCallback, ErrorCode * pError) -{ - struct mailimap_fetch_type * fetch_type; - struct mailimap_fetch_att * fetch_att; - struct mailimap_section * section; - struct mailimap_section_part * section_part; - clist * sec_list; - Array * partIDArray; - int r; - char * text; - size_t text_length; - Data * data; - - selectIfNeeded(folder, pError); - if (* pError != ErrorNone) - return NULL; - - mProgressItemsCount = 0; - mProgressCallback = progressCallback; - bodyProgress(0, 0); - - partIDArray = partID->componentsSeparatedByString(MCSTR(".")); - sec_list = clist_new(); - for(unsigned int i = 0 ; i < partIDArray->count() ; i ++) { - uint32_t * value; - String * element; - - element = (String *) partIDArray->objectAtIndex(i); - value = (uint32_t *) malloc(sizeof(* value)); - * value = element->intValue(); - clist_append(sec_list, value); - } - section_part = mailimap_section_part_new(sec_list); - section = mailimap_section_new_part(section_part); - fetch_att = mailimap_fetch_att_new_body_peek_section(section); - fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); - - r = fetch_imap(mImap, identifier_is_uid, identifier, fetch_type, &text, &text_length); - mailimap_fetch_type_free(fetch_type); - - mProgressCallback = NULL; - - MCLog("had error : %i", r); - if (r == MAILIMAP_ERROR_STREAM) { - mShouldDisconnect = true; - * pError = ErrorConnection; - return NULL; - } - else if (r == MAILIMAP_ERROR_PARSE) { - * pError = ErrorParse; - return NULL; - } - else if (hasError(r)) { - * pError = ErrorFetch; - return NULL; - } - - data = Data::dataWithBytes(text, (unsigned int) text_length); - data = data->decodedDataUsingEncoding(encoding); - - mailimap_nstring_free(text); - * pError = ErrorNone; - - return data; -} - -Data * IMAPSession::fetchMessageAttachmentByUID(String * folder, uint32_t uid, String * partID, - Encoding encoding, IMAPProgressCallback * progressCallback, ErrorCode * pError) -{ - return fetchMessageAttachment(folder, true, uid, partID, encoding, progressCallback, pError); -} - -Data * IMAPSession::fetchMessageAttachmentByNumber(String * folder, uint32_t number, String * partID, - Encoding encoding, IMAPProgressCallback * progressCallback, ErrorCode * pError) -{ - return fetchMessageAttachment(folder, false, number, partID, encoding, progressCallback, pError); -} - -IndexSet * IMAPSession::search(String * folder, IMAPSearchKind kind, String * searchString, ErrorCode * pError) -{ - IMAPSearchExpression * expr; - - expr = NULL; - switch (kind) { - case IMAPSearchKindAll: - { - expr = IMAPSearchExpression::searchAll(); - break; - } - case IMAPSearchKindFrom: - { - expr = IMAPSearchExpression::searchFrom(searchString); - break; - } - case IMAPSearchKindTo: - { - expr = IMAPSearchExpression::searchTo(searchString); - break; - } - case IMAPSearchKindCc: - { - expr = IMAPSearchExpression::searchCc(searchString); - break; - } - case IMAPSearchKindBcc: - { - expr = IMAPSearchExpression::searchBcc(searchString); - break; - } - case IMAPSearchKindRecipient: - { - expr = IMAPSearchExpression::searchRecipient(searchString); - break; - } - case IMAPSearchKindSubject: - { - expr = IMAPSearchExpression::searchSubject(searchString); - break; - } - case IMAPSearchKindContent: - { - expr = IMAPSearchExpression::searchContent(searchString); - break; - } - default: - { - MCAssert(0); - break; - } - } - return search(folder, expr, pError); -} - -static struct mailimap_search_key * searchKeyFromSearchExpression(IMAPSearchExpression * expression) -{ - switch (expression->kind()) { - case IMAPSearchKindAll: - { - return mailimap_search_key_new_all(); - } - case IMAPSearchKindFrom: - { - return mailimap_search_key_new_from(strdup(expression->value()->UTF8Characters())); - } - case IMAPSearchKindTo: - { - return mailimap_search_key_new_to(strdup(expression->value()->UTF8Characters())); - } - case IMAPSearchKindCc: - { - return mailimap_search_key_new_cc(strdup(expression->value()->UTF8Characters())); - } - case IMAPSearchKindBcc: - { - return mailimap_search_key_new_bcc(strdup(expression->value()->UTF8Characters())); - } - case IMAPSearchKindRecipient: - { - struct mailimap_search_key * to_search; - struct mailimap_search_key * cc_search; - struct mailimap_search_key * bcc_search; - struct mailimap_search_key * or_search1; - struct mailimap_search_key * or_search2; - - to_search = mailimap_search_key_new_to(strdup(expression->value()->UTF8Characters())); - cc_search = mailimap_search_key_new_cc(strdup(expression->value()->UTF8Characters())); - bcc_search = mailimap_search_key_new_bcc(strdup(expression->value()->UTF8Characters())); - - or_search1 = mailimap_search_key_new_or(to_search, cc_search); - or_search2 = mailimap_search_key_new_or(or_search1, bcc_search); - - return or_search2; - } - case IMAPSearchKindSubject: - { - return mailimap_search_key_new_subject(strdup(expression->value()->UTF8Characters())); - } - case IMAPSearchKindContent: - { - return mailimap_search_key_new_text(strdup(expression->value()->UTF8Characters())); - } - case IMAPSearchKindBody: - { - return mailimap_search_key_new_body(strdup(expression->value()->UTF8Characters())); - } - case IMAPSearchKindUIDs: - { - return mailimap_search_key_new_uid(setFromIndexSet(expression->uids())); - } - case IMAPSearchKindHeader: - { - return mailimap_search_key_new_header(strdup(expression->header()->UTF8Characters()), strdup(expression->value()->UTF8Characters())); - } - case IMAPSearchKindBeforeDate: - { - time_t date = expression->date(); - struct tm timeinfo; - localtime_r(&date, &timeinfo); - return mailimap_search_key_new_sentbefore(mailimap_date_new(timeinfo.tm_mday, timeinfo.tm_mon+1, timeinfo.tm_year+1900)); - } - case IMAPSearchKindOnDate: - { - time_t date = expression->date(); - struct tm timeinfo; - localtime_r(&date, &timeinfo); - return mailimap_search_key_new_senton(mailimap_date_new(timeinfo.tm_mday, timeinfo.tm_mon+1, timeinfo.tm_year+1900)); - } - case IMAPSearchKindSinceDate: - { - time_t date = expression->date(); - struct tm timeinfo; - localtime_r(&date, &timeinfo); - return mailimap_search_key_new_sentsince(mailimap_date_new(timeinfo.tm_mday, timeinfo.tm_mon+1, timeinfo.tm_year+1900)); - } - case IMAPSearchKindBeforeReceivedDate: - { - time_t date = expression->date(); - struct tm timeinfo; - localtime_r(&date, &timeinfo); - return mailimap_search_key_new_before(mailimap_date_new(timeinfo.tm_mday, timeinfo.tm_mon+1, timeinfo.tm_year+1900)); - } - case IMAPSearchKindOnReceivedDate: - { - time_t date = expression->date(); - struct tm timeinfo; - localtime_r(&date, &timeinfo); - return mailimap_search_key_new_on(mailimap_date_new(timeinfo.tm_mday, timeinfo.tm_mon+1, timeinfo.tm_year+1900)); - } - case IMAPSearchKindSinceReceivedDate: - { - time_t date = expression->date(); - struct tm timeinfo; - localtime_r(&date, &timeinfo); - return mailimap_search_key_new_since(mailimap_date_new(timeinfo.tm_mday, timeinfo.tm_mon+1, timeinfo.tm_year+1900)); - } - case IMAPSearchKindGmailThreadID: - { - return mailimap_search_key_new_xgmthrid(expression->longNumber()); - } - case IMAPSearchKindGmailMessageID: - { - return mailimap_search_key_new_xgmmsgid(expression->longNumber()); - } - case IMAPSearchKindRead: - { - return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SEEN, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, 0, - NULL, NULL, NULL, NULL, NULL, - NULL, 0, NULL, NULL, NULL); - } - case IMAPSearchKindUnread: - { - return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UNSEEN, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, 0, - NULL, NULL, NULL, NULL, NULL, - NULL, 0, NULL, NULL, NULL); - } - case IMAPSearchKindFlagged: - { - return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_FLAGGED, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, 0, - NULL, NULL, NULL, NULL, NULL, - NULL, 0, NULL, NULL, NULL); - } - case IMAPSearchKindUnflagged: - { - return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UNFLAGGED, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, 0, - NULL, NULL, NULL, NULL, NULL, - NULL, 0, NULL, NULL, NULL); - } - case IMAPSearchKindAnswered: - { - return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_ANSWERED, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, 0, - NULL, NULL, NULL, NULL, NULL, - NULL, 0, NULL, NULL, NULL); - } - case IMAPSearchKindUnanswered: - { - return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UNANSWERED, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, 0, - NULL, NULL, NULL, NULL, NULL, - NULL, 0, NULL, NULL, NULL); - } - case IMAPSearchKindDraft: - { - return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_DRAFT, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, 0, - NULL, NULL, NULL, NULL, NULL, - NULL, 0, NULL, NULL, NULL); - } - case IMAPSearchKindUndraft: - { - return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UNDRAFT, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, 0, - NULL, NULL, NULL, NULL, NULL, - NULL, 0, NULL, NULL, NULL); - } - case IMAPSearchKindDeleted: - { - return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_DELETED, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, 0, - NULL, NULL, NULL, NULL, NULL, - NULL, 0, NULL, NULL, NULL); - } - case IMAPSearchKindSpam: - { - return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_KEYWORD, - NULL, NULL, NULL, NULL, NULL, - strdup("Junk"), NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, 0, - NULL, NULL, NULL, NULL, NULL, - NULL, 0, NULL, NULL, NULL); - } - case IMAPSearchKindSizeLarger: - { - return mailimap_search_key_new_larger( (uint32_t) expression->longNumber()); - } - case IMAPSearchKindSizeSmaller: - { - return mailimap_search_key_new_smaller( (uint32_t) expression->longNumber()); - } - case IMAPSearchKindGmailRaw: - { - return mailimap_search_key_new_xgmraw(strdup(expression->value()->UTF8Characters())); - } - case IMAPSearchKindOr: - { - return mailimap_search_key_new_or(searchKeyFromSearchExpression(expression->leftExpression()), searchKeyFromSearchExpression(expression->rightExpression())); - } - case IMAPSearchKindAnd: - { - clist * list; - list = clist_new(); - clist_append(list, searchKeyFromSearchExpression(expression->leftExpression())); - clist_append(list, searchKeyFromSearchExpression(expression->rightExpression())); - return mailimap_search_key_new_multiple(list); - } - case IMAPSearchKindNot: - { - return mailimap_search_key_new_not(searchKeyFromSearchExpression(expression->leftExpression())); - } - - default: - MCAssert(0); - return NULL; - } -} - -IndexSet * IMAPSession::search(String * folder, IMAPSearchExpression * expression, ErrorCode * pError) -{ - struct mailimap_search_key * key; - - key = searchKeyFromSearchExpression(expression); - selectIfNeeded(folder, pError); - if (* pError != ErrorNone) - return NULL; - - clist * result_list = NULL; - - const char * charset = "utf-8"; - if (mYahooServer) { - charset = NULL; - } - - int r; - if (mIsGmail) { - r = mailimap_uid_search_literalplus(mImap, charset, key, &result_list); - } - else { - 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; - } - else if (r == MAILIMAP_ERROR_PARSE) { - * pError = ErrorParse; - return NULL; - } - else if (hasError(r)) { - * pError = ErrorFetch; - return NULL; - } - - IndexSet * result = IndexSet::indexSet(); - for(clistiter * cur = clist_begin(result_list) ; cur != NULL ; cur = clist_next(cur)) { - uint32_t * uid = (uint32_t *) clist_content(cur); - result->addIndex(* uid); - } - mailimap_search_result_free(result_list); - * pError = ErrorNone; - 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", "a_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 - LOCK(); - bool canIdle = mCanIdle; - if (mCanIdle) { - mailstream_setup_idle(mImap->imap_stream); - } - UNLOCK(); - return canIdle; -} - -void IMAPSession::idle(String * folder, uint32_t lastKnownUID, ErrorCode * pError) -{ - int r; - - // connection thread - selectIfNeeded(folder, pError); - if (* pError != ErrorNone) - return; - - if (lastKnownUID != 0) { - Array * msgs; - - msgs = fetchMessagesByUID(folder, IMAPMessagesRequestKindUid, IndexSet::indexSetWithRange(RangeMake(lastKnownUID, UINT64_MAX)), - NULL, pError); - if (* pError != ErrorNone) - return; - if (msgs->count() > 0) { - IMAPMessage * msg; - - msg = (IMAPMessage *) msgs->objectAtIndex(0); - if (msg->uid() > lastKnownUID) { - MCLog("found msg UID %u %u", (unsigned int) msg->uid(), (unsigned int) lastKnownUID); - return; - } - } - } - - r = mailimap_idle(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 = ErrorIdle; - return; - } - - if (!mImap->imap_selection_info->sel_has_exists && !mImap->imap_selection_info->sel_has_recent) { - int r; - r = mailstream_wait_idle(mImap->imap_stream, MAX_IDLE_DELAY); - switch (r) { - case MAILSTREAM_IDLE_ERROR: - case MAILSTREAM_IDLE_CANCELLED: - { - mShouldDisconnect = true; - * pError = ErrorConnection; - MCLog("error or cancelled"); - return; - } - case MAILSTREAM_IDLE_INTERRUPTED: - MCLog("interrupted by user"); - break; - case MAILSTREAM_IDLE_HASDATA: - MCLog("something on the socket"); - break; - case MAILSTREAM_IDLE_TIMEOUT: - MCLog("idle timeout"); - break; - } - } - else { - MCLog("found info before idling"); - } - - r = mailimap_idle_done(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 = ErrorIdle; - return; - } - * pError = ErrorNone; -} - -void IMAPSession::interruptIdle() -{ - // main thread - LOCK(); - if (mCanIdle) { - mailstream_interrupt_idle(mImap->imap_stream); - } - UNLOCK(); -} - -void IMAPSession::unsetupIdle() -{ - // main thread - LOCK(); - if (mCanIdle) { - mailstream_unsetup_idle(mImap->imap_stream); - } - UNLOCK(); -} - -void IMAPSession::disconnect() -{ - unsetup(); -} - -IMAPIdentity * IMAPSession::identity(IMAPIdentity * clientIdentity, ErrorCode * pError) -{ - connectIfNeeded(pError); - if (* pError != ErrorNone) - return NULL; - - struct mailimap_id_params_list * client_identification; - - client_identification = mailimap_id_params_list_new_empty(); - - mc_foreacharray(String, key, clientIdentity->allInfoKeys()) { - char * dup_name; - char * dup_value; - - dup_name = strdup(key->UTF8Characters()); - dup_value = strdup(clientIdentity->infoForKey(key)->UTF8Characters()); - mailimap_id_params_list_add_name_value(client_identification, dup_name, dup_value); - } - - int r; - struct mailimap_id_params_list * server_identification; - 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; - } - else if (r == MAILIMAP_ERROR_PARSE) { - * pError = ErrorParse; - return NULL; - } - else if (hasError(r)) { - * pError = ErrorIdentity; - return NULL; - } - - IMAPIdentity * result = new IMAPIdentity(); - - clistiter * cur; - for(cur = clist_begin(server_identification->idpa_list) ; cur != NULL ; cur = clist_next(cur)) { - struct mailimap_id_param * param; - - param = (struct mailimap_id_param *) clist_content(cur); - - String * responseKey; - String * responseValue; - responseKey = String::stringWithUTF8Characters(param->idpa_name); - responseValue = String::stringWithUTF8Characters(param->idpa_value); - result->setInfoForKey(responseKey, responseValue); - } - - mailimap_id_params_list_free(server_identification); - * pError = ErrorNone; - - result->autorelease(); - return result; -} - -void IMAPSession::bodyProgress(unsigned int current, unsigned int maximum) -{ - if (!mBodyProgressEnabled) - return; - - if (mProgressCallback != NULL) { - mProgressCallback->bodyProgress(this, current, maximum); - } -} - -void IMAPSession::itemsProgress(unsigned int current, unsigned int maximum) -{ - mProgressItemsCount ++; - if (mProgressCallback != NULL) { - mProgressCallback->itemsProgress(this, mProgressItemsCount, maximum); - } -} - -IMAPNamespace * IMAPSession::defaultNamespace() -{ - return mDefaultNamespace; -} - -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; - struct mailimap_namespace_data * namespace_data; - int r; - - loginIfNeeded(pError); - if (* pError != ErrorNone) - return NULL; - - result = HashMap::hashMap(); - r = mailimap_namespace(mImap, &namespace_data); - if (r == MAILIMAP_ERROR_STREAM) { - mShouldDisconnect = true; - * pError = ErrorConnection; - return NULL; - } - else if (r == MAILIMAP_ERROR_PARSE) { - * pError = ErrorParse; - return NULL; - } - else if (hasError(r)) { - * pError = ErrorNamespace; - return NULL; - } - - IMAPNamespace * ns; - - if (namespace_data->ns_personal != NULL) { - ns = new IMAPNamespace(); - ns->importIMAPNamespace(namespace_data->ns_personal); - result->setObjectForKey(IMAPNamespacePersonal, ns); - ns->release(); - } - - if (namespace_data->ns_other != NULL) { - ns = new IMAPNamespace(); - ns->importIMAPNamespace(namespace_data->ns_other); - result->setObjectForKey(IMAPNamespaceOther, ns); - ns->release(); - } - - if (namespace_data->ns_shared != NULL) { - ns = new IMAPNamespace(); - ns->importIMAPNamespace(namespace_data->ns_shared); - result->setObjectForKey(IMAPNamespaceShared, ns); - ns->release(); - } - - mailimap_namespace_data_free(namespace_data); - * pError = ErrorNone; - - return result; -} - -void IMAPSession::storeFlagsByUID(String * folder, IndexSet * uids, IMAPStoreFlagsRequestKind kind, MessageFlag flags, ErrorCode * pError) -{ - this->storeFlagsAndCustomFlagsByUID(folder, uids, kind, flags, NULL, pError); -} - -void IMAPSession::storeFlagsAndCustomFlagsByUID(String * folder, IndexSet * uids, IMAPStoreFlagsRequestKind kind, MessageFlag flags, Array * customFlags, ErrorCode * pError) -{ - storeFlagsAndCustomFlags(folder, true, uids, kind, flags, customFlags, pError); -} - -void IMAPSession::storeFlagsAndCustomFlags(String * folder, bool identifier_is_uid, IndexSet * identifiers, - IMAPStoreFlagsRequestKind kind, MessageFlag flags, Array * customFlags, ErrorCode * pError) -{ - struct mailimap_set * imap_set; - struct mailimap_store_att_flags * store_att_flags; - struct mailimap_flag_list * flag_list; - int r; - clist * setList; - - selectIfNeeded(folder, pError); - if (* pError != ErrorNone) - return; - - imap_set = setFromIndexSet(identifiers); - if (clist_count(imap_set->set_list) == 0) { - mailimap_set_free(imap_set); - return; - } - - setList = splitSet(imap_set, 50); - - flag_list = mailimap_flag_list_new_empty(); - if ((flags & MessageFlagSeen) != 0) { - struct mailimap_flag * f; - - f = mailimap_flag_new_seen(); - mailimap_flag_list_add(flag_list, f); - } - if ((flags & MessageFlagAnswered) != 0) { - struct mailimap_flag * f; - - f = mailimap_flag_new_answered(); - mailimap_flag_list_add(flag_list, f); - } - if ((flags & MessageFlagFlagged) != 0) { - struct mailimap_flag * f; - - f = mailimap_flag_new_flagged(); - mailimap_flag_list_add(flag_list, f); - } - if ((flags & MessageFlagDeleted) != 0) { - struct mailimap_flag * f; - - f = mailimap_flag_new_deleted(); - mailimap_flag_list_add(flag_list, f); - } - if ((flags & MessageFlagDraft) != 0) { - struct mailimap_flag * f; - - f = mailimap_flag_new_draft(); - mailimap_flag_list_add(flag_list, f); - } - if ((flags & MessageFlagMDNSent) != 0) { - struct mailimap_flag * f; - - f = mailimap_flag_new_flag_keyword(strdup("$MDNSent")); - mailimap_flag_list_add(flag_list, f); - } - if ((flags & MessageFlagForwarded) != 0) { - struct mailimap_flag * f; - - f = mailimap_flag_new_flag_keyword(strdup("$Forwarded")); - mailimap_flag_list_add(flag_list, f); - } - if ((flags & MessageFlagSubmitPending) != 0) { - struct mailimap_flag * f; - - f = mailimap_flag_new_flag_keyword(strdup("$SubmitPending")); - mailimap_flag_list_add(flag_list, f); - } - if ((flags & MessageFlagSubmitted) != 0) { - struct mailimap_flag * f; - - f = mailimap_flag_new_flag_keyword(strdup("$Submitted")); - mailimap_flag_list_add(flag_list, f); - } - - if (customFlags != NULL) { - for (unsigned int i = 0 ; i < customFlags->count() ; i ++) { - struct mailimap_flag * f; - String * customFlag = (String *) customFlags->objectAtIndex(i); - - f = mailimap_flag_new_flag_keyword(strdup(customFlag->UTF8Characters())); - mailimap_flag_list_add(flag_list, f); - } - } - - store_att_flags = NULL; - for(clistiter * iter = clist_begin(setList) ; iter != NULL ; iter = clist_next(iter)) { - struct mailimap_set * current_set; - - current_set = (struct mailimap_set *) clist_content(iter); - - switch (kind) { - case IMAPStoreFlagsRequestKindRemove: - store_att_flags = mailimap_store_att_flags_new_remove_flags_silent(flag_list); - break; - case IMAPStoreFlagsRequestKindAdd: - store_att_flags = mailimap_store_att_flags_new_add_flags_silent(flag_list); - break; - case IMAPStoreFlagsRequestKindSet: - store_att_flags = mailimap_store_att_flags_new_set_flags_silent(flag_list); - break; - } - if (identifier_is_uid) { - r = mailimap_uid_store(mImap, current_set, store_att_flags); - } - else { - r = mailimap_store(mImap, current_set, store_att_flags); - } - - if (r == MAILIMAP_ERROR_STREAM) { - mShouldDisconnect = true; - * pError = ErrorConnection; - goto release; - } - else if (r == MAILIMAP_ERROR_PARSE) { - * pError = ErrorParse; - return; - } - else if (hasError(r)) { - * pError = ErrorStore; - return; - } - } - - release: - for(clistiter * iter = clist_begin(setList) ; iter != NULL ; iter = clist_next(iter)) { - struct mailimap_set * current_set; - - current_set = (struct mailimap_set *) clist_content(iter); - mailimap_set_free(current_set); - } - clist_free(setList); - mailimap_store_att_flags_free(store_att_flags); - mailimap_set_free(imap_set); - * pError = ErrorNone; -} - -void IMAPSession::storeFlagsByNumber(String * folder, IndexSet * numbers, IMAPStoreFlagsRequestKind kind, MessageFlag flags, ErrorCode * pError) -{ - this->storeFlagsAndCustomFlagsByNumber(folder, numbers, kind, flags, NULL, pError); -} - -void IMAPSession::storeFlagsAndCustomFlagsByNumber(String * folder, IndexSet * numbers, IMAPStoreFlagsRequestKind kind, MessageFlag flags, Array * customFlags, ErrorCode * pError) -{ - storeFlagsAndCustomFlags(folder, false, numbers, kind, flags, customFlags, pError); -} - -void IMAPSession::storeLabelsByUID(String * folder, IndexSet * uids, IMAPStoreFlagsRequestKind kind, Array * labels, ErrorCode * pError) -{ - storeLabels(folder, true, uids, kind, labels, pError); -} - -void IMAPSession::storeLabelsByNumber(String * folder, IndexSet * numbers, IMAPStoreFlagsRequestKind kind, Array * labels, ErrorCode * pError) -{ - storeLabels(folder, false, numbers, kind, labels, pError); -} - -void IMAPSession::storeLabels(String * folder, bool identifier_is_uid, IndexSet * identifiers, IMAPStoreFlagsRequestKind kind, Array * labels, ErrorCode * pError) -{ - struct mailimap_set * imap_set; - struct mailimap_msg_att_xgmlabels * xgmlabels; - int r; - clist * setList; - - selectIfNeeded(folder, pError); - if (* pError != ErrorNone) - return; - - imap_set = setFromIndexSet(identifiers); - if (clist_count(imap_set->set_list) == 0) { - mailimap_set_free(imap_set); - return; - } - - setList = splitSet(imap_set, 10); - - xgmlabels = mailimap_msg_att_xgmlabels_new_empty(); - for(unsigned int i = 0 ; i < labels->count() ; i ++) { - String * label = (String *) labels->objectAtIndex(i); - mailimap_msg_att_xgmlabels_add(xgmlabels, strdup(label->UTF8Characters())); - } - - for(clistiter * iter = clist_begin(setList) ; iter != NULL ; iter = clist_next(iter)) { - struct mailimap_set * current_set; - int fl_sign; - - current_set = (struct mailimap_set *) clist_content(iter); - - switch (kind) { - case IMAPStoreFlagsRequestKindRemove: - fl_sign = -1; - break; - case IMAPStoreFlagsRequestKindAdd: - fl_sign = 1; - break; - case IMAPStoreFlagsRequestKindSet: - fl_sign = 0; - break; - } - if (identifier_is_uid) { - r = mailimap_uid_store_xgmlabels(mImap, current_set, fl_sign, 1, xgmlabels); - } - else { - r = mailimap_store_xgmlabels(mImap, current_set, fl_sign, 1, xgmlabels); - } - if (r == MAILIMAP_ERROR_STREAM) { - mShouldDisconnect = true; - * pError = ErrorConnection; - goto release; - } - else if (r == MAILIMAP_ERROR_PARSE) { - * pError = ErrorParse; - return; - } - else if (hasError(r)) { - * pError = ErrorStore; - return; - } - } - - release: - for(clistiter * iter = clist_begin(setList) ; iter != NULL ; iter = clist_next(iter)) { - struct mailimap_set * current_set; - - current_set = (struct mailimap_set *) clist_content(iter); - mailimap_set_free(current_set); - } - clist_free(setList); - mailimap_msg_att_xgmlabels_free(xgmlabels); - mailimap_set_free(imap_set); - * pError = ErrorNone; -} - -uint32_t IMAPSession::uidValidity() -{ - return mUIDValidity; -} - -uint32_t IMAPSession::uidNext() -{ - return mUIDNext; -} - -uint64_t IMAPSession::modSequenceValue() -{ - return mModSequenceValue; -} - -unsigned int IMAPSession::lastFolderMessageCount() -{ - return mFolderMsgCount; -} - -uint32_t IMAPSession::firstUnseenUid() -{ - return mFirstUnseenUid; -} - -IMAPSyncResult * IMAPSession::syncMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, - IndexSet * uids, uint64_t modseq, - IMAPProgressCallback * progressCallback, ErrorCode * pError) -{ - return syncMessagesByUIDWithExtraHeaders(folder, requestKind, uids, modseq, progressCallback, NULL, pError); -} - -IMAPSyncResult * IMAPSession::syncMessagesByUIDWithExtraHeaders(String * folder, IMAPMessagesRequestKind requestKind, - IndexSet * uids, uint64_t modseq, - IMAPProgressCallback * progressCallback, Array * extraHeaders, - ErrorCode * pError) -{ - MCAssert(uids->rangesCount() > 0); - struct mailimap_set * imapset = setFromIndexSet(uids); - IMAPSyncResult * result = fetchMessages(folder, requestKind, true, imapset, modseq, NULL, - (uint32_t) uids->allRanges()[0].location, - progressCallback, extraHeaders, pError); - mailimap_set_free(imapset); - return result; - -} - -IndexSet * IMAPSession::capability(ErrorCode * pError) -{ - int r; - struct mailimap_capability_data * cap; - - connectIfNeeded(pError); - if (* pError != ErrorNone) - return NULL; - - r = mailimap_capability(mImap, &cap); - if (r == MAILIMAP_ERROR_STREAM) { - mShouldDisconnect = true; - * pError = ErrorConnection; - return NULL; - } - else if (r == MAILIMAP_ERROR_PARSE) { - * pError = ErrorParse; - return NULL; - } - else if (hasError(r)) { - * pError = ErrorCapability; - return NULL; - } - - mailimap_capability_data_free(cap); - - IndexSet * result = new IndexSet(); - capabilitySetWithSessionState(result); - - * pError = ErrorNone; - result->autorelease(); - return result; -} - -void IMAPSession::capabilitySetWithSessionState(IndexSet * capabilities) -{ - if (mailimap_has_extension(mImap, (char *)"STARTTLS")) { - capabilities->addIndex(IMAPCapabilityStartTLS); - } - if (mailimap_has_authentication(mImap, (char *)"PLAIN")) { - capabilities->addIndex(IMAPCapabilityAuthPlain); - } - if (mailimap_has_authentication(mImap, (char *)"LOGIN")) { - capabilities->addIndex(IMAPCapabilityAuthLogin); - } - if (mailimap_has_idle(mImap)) { - LOCK(); - mCanIdle = true; - UNLOCK(); - } - if (mailimap_has_id(mImap)) { - capabilities->addIndex(IMAPCapabilityId); - } - if (mailimap_has_xlist(mImap)) { - 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. - capabilities->addIndex(IMAPCapabilityGmail); - } - if (mailimap_has_idle(mImap)) { - capabilities->addIndex(IMAPCapabilityIdle); - } - if (mailimap_has_condstore(mImap)) { - 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); - } - if (mailimap_has_extension(mImap, (char *)"CHILDREN")) { - capabilities->addIndex(IMAPCapabilityChildren); - } - - 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; - mIsGmail = true; - } - if (capabilities->containsIndex(IMAPCapabilityIdle)) { - mIdleEnabled = true; - } - if (capabilities->containsIndex(IMAPCapabilityCondstore)) { - mCondstoreEnabled = true; - } - if (capabilities->containsIndex(IMAPCapabilityQResync)) { - mQResyncEnabled = true; - } - if (capabilities->containsIndex(IMAPCapabilityXOAuth2)) { - mXOauth2Enabled = true; - } - if (capabilities->containsIndex(IMAPCapabilityNamespace)) { - mNamespaceEnabled = true; - } - if (capabilities->containsIndex(IMAPCapabilityCompressDeflate)) { - mCompressionEnabled = true; - } -} - -bool IMAPSession::isIdleEnabled() -{ - return mIdleEnabled; -} - -bool IMAPSession::isXListEnabled() -{ - return mXListEnabled; -} - -bool IMAPSession::isCondstoreEnabled() -{ - return mCondstoreEnabled; -} - -bool IMAPSession::isQResyncEnabled() -{ - return mQResyncEnabled; -} - -bool IMAPSession::isIdentityEnabled() -{ - return mIdentityEnabled; -} - -bool IMAPSession::isXOAuthEnabled() -{ - return mXOauth2Enabled; -} - -bool IMAPSession::isNamespaceEnabled() -{ - return mNamespaceEnabled; -} - -bool IMAPSession::isCompressionEnabled() -{ - return mCompressionEnabled; -} - -bool IMAPSession::allowsNewPermanentFlags() { - return mAllowsNewPermanentFlags; -} - -bool IMAPSession::isDisconnected() -{ - return mState == STATE_DISCONNECTED; -} - -void IMAPSession::setConnectionLogger(ConnectionLogger * logger) -{ - mConnectionLogger = logger; -} - -ConnectionLogger * IMAPSession::connectionLogger() -{ - return mConnectionLogger; -} - -String * IMAPSession::htmlRendering(IMAPMessage * message, String * folder, ErrorCode * pError) -{ - HTMLRendererIMAPDataCallback * dataCallback = new HTMLRendererIMAPDataCallback(this, message->uid()); - String * htmlString = HTMLRenderer::htmlForIMAPMessage(folder, - message, - dataCallback, - NULL); - * pError = dataCallback->error(); - - if (* pError != ErrorNone) { - return NULL; - } - - MC_SAFE_RELEASE(dataCallback); - return htmlString; -} - -String * IMAPSession::htmlBodyRendering(IMAPMessage * message, String * folder, ErrorCode * pError) -{ - HTMLRendererIMAPDataCallback * dataCallback = new HTMLRendererIMAPDataCallback(this, message->uid()); - HTMLBodyRendererTemplateCallback * htmlCallback = new HTMLBodyRendererTemplateCallback(); - - String * htmlBodyString = HTMLRenderer::htmlForIMAPMessage(folder, - message, - dataCallback, - htmlCallback); - - * pError = dataCallback->error(); - - if (* pError != ErrorNone) { - return NULL; - } - - MC_SAFE_RELEASE(dataCallback); - MC_SAFE_RELEASE(htmlCallback); - return htmlBodyString; -} - -String * IMAPSession::plainTextRendering(IMAPMessage * message, String * folder, ErrorCode * pError) -{ - String * htmlString = htmlRendering(message, folder, pError); - - if (* pError != ErrorNone) { - return NULL; - } - - String * plainTextString = htmlString->flattenHTML(); - return plainTextString; -} - -String * IMAPSession::plainTextBodyRendering(IMAPMessage * message, String * folder, bool stripWhitespace, ErrorCode * pError) -{ - String * htmlBodyString = htmlBodyRendering(message, folder, pError); - - if (* pError != ErrorNone) { - return NULL; - } - - String * plainTextBodyString = htmlBodyString->flattenHTML(); - if (stripWhitespace) { - return plainTextBodyString->stripWhitespace(); - } - - 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(caps); - 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; -} - -String * IMAPSession::gmailUserDisplayName() -{ - return mGmailUserDisplayName; -} diff --git a/src/core/imap/MCIMAPSession.cpp b/src/core/imap/MCIMAPSession.cpp new file mode 100755 index 00000000..f286cc52 --- /dev/null +++ b/src/core/imap/MCIMAPSession.cpp @@ -0,0 +1,3940 @@ +#include "MCWin32.h" // Should be included first. + +#include "MCIMAPSession.h" + +#include +#include +#include + +#include "MCDefines.h" +#include "MCIMAPSearchExpression.h" +#include "MCIMAPFolder.h" +#include "MCIMAPMessage.h" +#include "MCIMAPPart.h" +#include "MCMessageHeader.h" +#include "MCAbstractPart.h" +#include "MCIMAPProgressCallback.h" +#include "MCIMAPNamespace.h" +#include "MCIMAPSyncResult.h" +#include "MCIMAPFolderStatus.h" +#include "MCConnectionLogger.h" +#include "MCConnectionLoggerUtils.h" +#include "MCHTMLRenderer.h" +#include "MCString.h" +#include "MCUtils.h" +#include "MCHTMLRendererIMAPDataCallback.h" +#include "MCHTMLBodyRendererTemplateCallback.h" +#include "MCCertificateUtils.h" +#include "MCIMAPIdentity.h" +#include "MCLibetpan.h" + +using namespace mailcore; + +enum { + STATE_DISCONNECTED, + STATE_CONNECTED, + STATE_LOGGEDIN, + STATE_SELECTED, +}; + +String * mailcore::IMAPNamespacePersonal = NULL; +String * mailcore::IMAPNamespaceOther = NULL; +String * mailcore::IMAPNamespaceShared = NULL; + +static Array * resultsWithError(int r, clist * list, ErrorCode * pError); + +INITIALIZE(IMAPSEssion) +{ + AutoreleasePool * pool = new AutoreleasePool(); + IMAPNamespacePersonal = (String *) MCSTR("IMAPNamespacePersonal")->retain(); + IMAPNamespaceOther = (String *) MCSTR("IMAPNamespaceOther")->retain(); + IMAPNamespaceShared = (String *) MCSTR("IMAPNamespaceShared")->retain(); + + pool->release(); +} + +#define MAX_IDLE_DELAY (28 * 60) + +#define LOCK() pthread_mutex_lock(&mIdleLock) +#define UNLOCK() pthread_mutex_unlock(&mIdleLock) + +static struct mailimap_flag_list * flags_to_lep(MessageFlag value) +{ + struct mailimap_flag_list * flag_list; + + flag_list = mailimap_flag_list_new_empty(); + + if ((value & MessageFlagSeen) != 0) { + mailimap_flag_list_add(flag_list, mailimap_flag_new_seen()); + } + + if ((value & MessageFlagFlagged) != 0) { + mailimap_flag_list_add(flag_list, mailimap_flag_new_flagged()); + } + + if ((value & MessageFlagDeleted) != 0) { + mailimap_flag_list_add(flag_list, mailimap_flag_new_deleted()); + } + + if ((value & MessageFlagAnswered) != 0) { + mailimap_flag_list_add(flag_list, mailimap_flag_new_answered()); + } + + if ((value & MessageFlagDraft) != 0) { + mailimap_flag_list_add(flag_list, mailimap_flag_new_draft()); + } + + if ((value & MessageFlagForwarded) != 0) { + mailimap_flag_list_add(flag_list, mailimap_flag_new_flag_keyword(strdup("$Forwarded"))); + } + + if ((value & MessageFlagMDNSent) != 0) { + mailimap_flag_list_add(flag_list, mailimap_flag_new_flag_keyword(strdup("$MDNSent"))); + } + + if ((value & MessageFlagSubmitPending) != 0) { + mailimap_flag_list_add(flag_list, mailimap_flag_new_flag_keyword(strdup("$SubmitPending"))); + } + + if ((value & MessageFlagSubmitted) != 0) { + mailimap_flag_list_add(flag_list, mailimap_flag_new_flag_keyword(strdup("$Submitted"))); + } + + return flag_list; +} + +static MessageFlag flag_from_lep(struct mailimap_flag * flag) +{ + switch (flag->fl_type) { + case MAILIMAP_FLAG_ANSWERED: + return MessageFlagAnswered; + case MAILIMAP_FLAG_FLAGGED: + return MessageFlagFlagged; + case MAILIMAP_FLAG_DELETED: + return MessageFlagDeleted; + case MAILIMAP_FLAG_SEEN: + return MessageFlagSeen; + case MAILIMAP_FLAG_DRAFT: + return MessageFlagDraft; + case MAILIMAP_FLAG_KEYWORD: + if (strcasecmp(flag->fl_data.fl_keyword, "$Forwarded") == 0) { + return MessageFlagForwarded; + } + else if (strcasecmp(flag->fl_data.fl_keyword, "$MDNSent") == 0) { + return MessageFlagMDNSent; + } + else if (strcasecmp(flag->fl_data.fl_keyword, "$SubmitPending") == 0) { + return MessageFlagSubmitPending; + } + else if (strcasecmp(flag->fl_data.fl_keyword, "$Submitted") == 0) { + return MessageFlagSubmitted; + } + } + + return MessageFlagNone; +} + +static MessageFlag flags_from_lep_att_dynamic(struct mailimap_msg_att_dynamic * att_dynamic) +{ + if (att_dynamic->att_list == NULL) + return MessageFlagNone; + + MessageFlag flags; + clistiter * iter; + + flags = MessageFlagNone; + for(iter = clist_begin(att_dynamic->att_list) ;iter != NULL ; iter = clist_next(iter)) { + struct mailimap_flag_fetch * flag_fetch; + struct mailimap_flag * flag; + + flag_fetch = (struct mailimap_flag_fetch *) clist_content(iter); + if (flag_fetch->fl_type != MAILIMAP_FLAG_FETCH_OTHER) { + continue; + } + + flag = flag_fetch->fl_flag; + flags = (MessageFlag) (flags | flag_from_lep(flag)); + } + + return flags; +} + +static bool isKnownCustomFlag(const char * keyword) +{ + return !(strcmp(keyword, "$MDNSent") != 0 && strcmp(keyword, "$Forwarded") != 0 && strcmp(keyword, "$SubmitPending") != 0 && strcmp(keyword, "$Submitted") != 0); +} + +static Array * custom_flags_from_lep_att_dynamic(struct mailimap_msg_att_dynamic * att_dynamic) +{ + if (att_dynamic->att_list == NULL) + return NULL; + + clistiter * iter; + bool hasCustomFlags = false; + + for (iter = clist_begin(att_dynamic->att_list); iter != NULL; iter = clist_next(iter)) { + struct mailimap_flag_fetch * flag_fetch; + struct mailimap_flag * flag; + + flag_fetch = (struct mailimap_flag_fetch *) clist_content(iter); + if (flag_fetch->fl_type != MAILIMAP_FLAG_FETCH_OTHER) { + continue; + } + + flag = flag_fetch->fl_flag; + if (flag->fl_type == MAILIMAP_FLAG_KEYWORD) { + if (!isKnownCustomFlag(flag->fl_data.fl_keyword)) { + hasCustomFlags = true; + } + } + } + + if (!hasCustomFlags) + return NULL; + + Array * result = Array::array(); + for (iter = clist_begin(att_dynamic->att_list); iter != NULL; iter = clist_next(iter)) { + struct mailimap_flag_fetch * flag_fetch; + struct mailimap_flag * flag; + + flag_fetch = (struct mailimap_flag_fetch *) clist_content(iter); + if (flag_fetch->fl_type != MAILIMAP_FLAG_FETCH_OTHER) { + continue; + } + + flag = flag_fetch->fl_flag; + if (flag->fl_type == MAILIMAP_FLAG_KEYWORD) { + if (!isKnownCustomFlag(flag->fl_data.fl_keyword)) { + String * customFlag; + customFlag = String::stringWithUTF8Characters(flag->fl_data.fl_keyword); + result->addObject(customFlag); + } + } + } + + return result; +} + +#pragma mark set conversion + +static Array * arrayFromSet(struct mailimap_set * imap_set) +{ + Array * result; + clistiter * iter; + + result = Array::array(); + for(iter = clist_begin(imap_set->set_list) ; iter != NULL ; iter = clist_next(iter)) { + struct mailimap_set_item * item; + unsigned long i; + + item = (struct mailimap_set_item *) clist_content(iter); + for(i = item->set_first ; i <= item->set_last ; i ++) { + Value * nb; + + nb = Value::valueWithUnsignedLongValue(i); + result->addObject(nb); + } + } + + return result; +} + +static clist * splitSet(struct mailimap_set * set, unsigned int splitCount) +{ + struct mailimap_set * current_set; + clist * result; + unsigned int count; + + result = clist_new(); + + current_set = NULL; + count = 0; + for(clistiter * iter = clist_begin(set->set_list) ; iter != NULL ; iter = clist_next(iter)) { + struct mailimap_set_item * item; + + if (current_set == NULL) { + current_set = mailimap_set_new_empty(); + } + + item = (struct mailimap_set_item *) clist_content(iter); + mailimap_set_add_interval(current_set, item->set_first, item->set_last); + count ++; + + if (count >= splitCount) { + clist_append(result, current_set); + current_set = NULL; + count = 0; + } + } + if (current_set != NULL) { + clist_append(result, current_set); + } + + return result; +} + +static struct mailimap_set * setFromIndexSet(IndexSet * indexSet) +{ + struct mailimap_set * imap_set; + + imap_set = mailimap_set_new_empty(); + for(unsigned int i = 0 ; i < indexSet->rangesCount() ; i ++) { + uint64_t left = RangeLeftBound(indexSet->allRanges()[i]); + uint64_t right = RangeRightBound(indexSet->allRanges()[i]); + if (right == UINT64_MAX) { + right = 0; + } + mailimap_set_add_interval(imap_set, (uint32_t) left, (uint32_t) right); + } + + return imap_set; +} + +static IndexSet * indexSetFromSet(struct mailimap_set * imap_set) +{ + IndexSet * indexSet = IndexSet::indexSet(); + for(clistiter * cur = clist_begin(imap_set->set_list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_set_item * item = (struct mailimap_set_item *) clist_content(cur); + if (item->set_last == 0) { + indexSet->addRange(RangeMake(item->set_first, UINT64_MAX)); + } + else { + indexSet->addRange(RangeMake(item->set_first, item->set_last - item->set_first)); + } + } + return indexSet; +} + +void IMAPSession::init() +{ + mHostname = NULL; + mPort = 0; + mUsername = NULL; + mPassword = NULL; + mOAuth2Token = NULL; + mAuthType = AuthTypeSASLNone; + mConnectionType = ConnectionTypeClear; + mCheckCertificateEnabled = true; + mVoIPEnabled = true; + mDelimiter = 0; + + mBodyProgressEnabled = true; + mIdleEnabled = false; + mXListEnabled = false; + mQResyncEnabled = false; + mCondstoreEnabled = false; + mIdentityEnabled = false; + mNamespaceEnabled = false; + mCompressionEnabled = false; + mIsGmail = false; + mAllowsNewPermanentFlags = 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); + mCanIdle = true; + mState = STATE_DISCONNECTED; + mImap = NULL; + mProgressCallback = NULL; + mProgressItemsCount = 0; + mConnectionLogger = NULL; + mAutomaticConfigurationEnabled = true; + mAutomaticConfigurationDone = false; + mShouldDisconnect = false; + mLoginResponse = NULL; + mGmailUserDisplayName = NULL; +} + +IMAPSession::IMAPSession() +{ + init(); +} + +IMAPSession::~IMAPSession() +{ + MC_SAFE_RELEASE(mGmailUserDisplayName); + MC_SAFE_RELEASE(mLoginResponse); + MC_SAFE_RELEASE(mClientIdentity); + MC_SAFE_RELEASE(mServerIdentity); + 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); + pthread_mutex_destroy(&mIdleLock); +} + +void IMAPSession::setHostname(String * hostname) +{ + MC_SAFE_REPLACE_COPY(String, mHostname, hostname); +} + +String * IMAPSession::hostname() +{ + return mHostname; +} + +void IMAPSession::setPort(unsigned int port) +{ + mPort = port; +} + +unsigned int IMAPSession::port() +{ + return mPort; +} + +void IMAPSession::setUsername(String * username) +{ + MC_SAFE_REPLACE_COPY(String, mUsername, username); +} + +String * IMAPSession::username() +{ + return mUsername; +} + +void IMAPSession::setPassword(String * password) +{ + MC_SAFE_REPLACE_COPY(String, mPassword, password); +} + +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; +} + +AuthType IMAPSession::authType() +{ + return mAuthType; +} + +void IMAPSession::setConnectionType(ConnectionType connectionType) +{ + mConnectionType = connectionType; +} + +ConnectionType IMAPSession::connectionType() +{ + return mConnectionType; +} + +void IMAPSession::setTimeout(time_t timeout) +{ + mTimeout = timeout; +} + +time_t IMAPSession::timeout() +{ + return mTimeout; +} + +void IMAPSession::setCheckCertificateEnabled(bool enabled) +{ + mCheckCertificateEnabled = enabled; +} + +bool IMAPSession::isCheckCertificateEnabled() +{ + return mCheckCertificateEnabled; +} + +void IMAPSession::setVoIPEnabled(bool enabled) +{ + mVoIPEnabled = enabled; +} + +bool IMAPSession::isVoIPEnabled() +{ + return mVoIPEnabled; +} + +static bool hasError(int errorCode) +{ + return ((errorCode != MAILIMAP_NO_ERROR) && (errorCode != MAILIMAP_NO_ERROR_AUTHENTICATED) && + (errorCode != MAILIMAP_NO_ERROR_NON_AUTHENTICATED)); +} + +bool IMAPSession::checkCertificate() +{ + if (!isCheckCertificateEnabled()) + return true; + return mailcore::checkCertificate(mImap->imap_stream, hostname()); +} + +void IMAPSession::body_progress(size_t current, size_t maximum, void * context) +{ + IMAPSession * session; + + session = (IMAPSession *) context; + session->bodyProgress((unsigned int) current, (unsigned int) maximum); +} + +void IMAPSession::items_progress(size_t current, size_t maximum, void * context) +{ + IMAPSession * session; + + session = (IMAPSession *) context; + session->itemsProgress((unsigned int) current, (unsigned int) maximum); +} + +static void logger(mailimap * imap, int log_type, const char * buffer, size_t size, void * context) +{ + IMAPSession * session = (IMAPSession *) context; + + if (session->connectionLogger() == NULL) + 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()->log(session, type, data); + } + else { + session->connectionLogger()->log(session, type, NULL); + } +} + +void IMAPSession::setup() +{ + MCAssert(mImap == NULL); + + mImap = mailimap_new(0, NULL); + mailimap_set_timeout(mImap, timeout()); + mailimap_set_progress_callback(mImap, body_progress, IMAPSession::items_progress, this); + mailimap_set_logger(mImap, logger, this); +} + +void IMAPSession::unsetup() +{ + mailimap * imap; + + LOCK(); + imap = mImap; + mImap = NULL; + mCanIdle = false; + UNLOCK(); + + if (imap != NULL) { + if (imap->imap_stream != NULL) { + mailstream_close(imap->imap_stream); + imap->imap_stream = NULL; + } + mailimap_free(imap); + imap = NULL; + } + + mState = STATE_DISCONNECTED; +} + +void IMAPSession::connect(ErrorCode * pError) +{ + int r; + + setup(); + + MCLog("connect %s", MCUTF8DESC(this)); + + MCAssert(mState == STATE_DISCONNECTED); + + switch (mConnectionType) { + case ConnectionTypeStartTLS: + MCLog("STARTTLS connect"); + r = mailimap_socket_connect_voip(mImap, MCUTF8(mHostname), mPort, isVoIPEnabled()); + if (hasError(r)) { + * pError = ErrorConnection; + goto close; + } + + r = mailimap_socket_starttls(mImap); + if (hasError(r)) { + MCLog("no TLS %i", r); + * pError = ErrorTLSNotAvailable; + goto close; + } + break; + + case ConnectionTypeTLS: + r = mailimap_ssl_connect_voip(mImap, MCUTF8(mHostname), mPort, isVoIPEnabled()); + MCLog("ssl connect %s %u %u", MCUTF8(mHostname), mPort, r); + if (hasError(r)) { + MCLog("connect error %i", r); + * pError = ErrorConnection; + goto close; + } + if (!checkCertificate()) { + MCLog("ssl connect certificate ERROR %d", r); + * pError = ErrorCertificate; + goto close; + } + + break; + + default: + MCLog("socket connect %s %u", MCUTF8(mHostname), mPort); + r = mailimap_socket_connect_voip(mImap, MCUTF8(mHostname), mPort, isVoIPEnabled()); + MCLog("socket connect %i", r); + if (hasError(r)) { + MCLog("connect error %i", r); + * pError = ErrorConnection; + goto close; + } + break; + } + + mailstream_low * low; + String * identifierString; + char * identifier; + + low = mailstream_get_low(mImap->imap_stream); + identifierString = String::stringWithUTF8Format("%s@%s:%u", MCUTF8(mUsername), MCUTF8(mHostname), mPort); + identifier = strdup(identifierString->UTF8Characters()); + mailstream_low_set_identifier(low, identifier); + + if (mImap->imap_response != NULL) { + MC_SAFE_REPLACE_RETAIN(String, mWelcomeString, String::stringWithUTF8Characters(mImap->imap_response)); + mYahooServer = (mWelcomeString->locationOfString(MCSTR("yahoo.com")) != -1); + } + + 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"); + return; + +close: + unsetup(); +} + +void IMAPSession::connectIfNeeded(ErrorCode * pError) +{ + if (mShouldDisconnect) { + disconnect(); + mShouldDisconnect = false; + } + + if (mState == STATE_DISCONNECTED) { + connect(pError); + } + else { + * pError = ErrorNone; + } +} + +void IMAPSession::loginIfNeeded(ErrorCode * pError) +{ + connectIfNeeded(pError); + if (* pError != ErrorNone) + return; + + if (mState == STATE_CONNECTED) { + login(pError); + } + else { + * pError = ErrorNone; + } +} + +void IMAPSession::login(ErrorCode * pError) +{ + int r; + + MCLog("login"); + + 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); + utf8password = MCUTF8(mPassword); + if (utf8username == NULL) { + utf8username = ""; + } + if (utf8password == NULL) { + utf8password = ""; + } + + switch (mAuthType) { + case 0: + default: + r = mailimap_login(mImap, utf8username, utf8password); + break; + + case AuthTypeSASLCRAMMD5: + r = mailimap_authenticate(mImap, "CRAM-MD5", + MCUTF8(mHostname), + NULL, + NULL, + utf8username, utf8username, + utf8password, NULL); + break; + + case AuthTypeSASLPlain: + r = mailimap_authenticate(mImap, "PLAIN", + MCUTF8(mHostname), + NULL, + NULL, + utf8username, utf8username, + utf8password, NULL); + break; + + case AuthTypeSASLGSSAPI: + // needs to be tested + r = mailimap_authenticate(mImap, "GSSAPI", + MCUTF8(mHostname), + NULL, + NULL, + utf8username, utf8username, + utf8password, NULL /* realm */); + break; + + case AuthTypeSASLDIGESTMD5: + r = mailimap_authenticate(mImap, "DIGEST-MD5", + MCUTF8(mHostname), + NULL, + NULL, + utf8username, utf8username, + utf8password, NULL); + break; + + case AuthTypeSASLLogin: + r = mailimap_authenticate(mImap, "LOGIN", + MCUTF8(mHostname), + NULL, + NULL, + utf8username, utf8username, + utf8password, NULL); + break; + + case AuthTypeSASLSRP: + r = mailimap_authenticate(mImap, "SRP", + MCUTF8(mHostname), + NULL, + NULL, + utf8username, utf8username, + utf8password, NULL); + break; + + case AuthTypeSASLNTLM: + r = mailimap_authenticate(mImap, "NTLM", + MCUTF8(mHostname), + NULL, + NULL, + utf8username, utf8username, + utf8password, NULL/* realm */); + break; + + case AuthTypeSASLKerberosV4: + r = mailimap_authenticate(mImap, "KERBEROS_V4", + MCUTF8(mHostname), + NULL, + NULL, + utf8username, utf8username, + utf8password, NULL/* realm */); + break; + + case AuthTypeXOAuth2: + case AuthTypeXOAuth2Outlook: + r = mailimap_oauth2_authenticate(mImap, utf8username, MCUTF8(mOAuth2Token)); + break; + } + if (r == MAILIMAP_ERROR_STREAM) { + mShouldDisconnect = true; + * pError = ErrorConnection; + return; + } + else if (r == MAILIMAP_ERROR_PARSE) { + * pError = ErrorParse; + return; + } + else if (hasError(r)) { + String * response; + + response = MCSTR(""); + if (mImap->imap_response != NULL) { + response = String::stringWithUTF8Characters(mImap->imap_response); + } + if (response->locationOfString(MCSTR("not enabled for IMAP use")) != -1) { + * pError = ErrorGmailIMAPNotEnabled; + } + else if (response->locationOfString(MCSTR("bandwidth limits")) != -1) { + * pError = ErrorGmailExceededBandwidthLimit; + } + else if (response->locationOfString(MCSTR("Too many simultaneous connections")) != -1) { + * pError = ErrorGmailTooManySimultaneousConnections; + } + else if (response->locationOfString(MCSTR("Maximum number of connections")) != -1) { + * pError = ErrorGmailTooManySimultaneousConnections; + } + else if (response->locationOfString(MCSTR("Application-specific password required")) != -1) { + * pError = ErrorGmailApplicationSpecificPasswordRequired; + } + else if (response->locationOfString(MCSTR("http://me.com/move")) != -1) { + * pError = ErrorMobileMeMoved; + } + else if (response->locationOfString(MCSTR("OCF12")) != -1) { + * pError = ErrorYahooUnavailable; + } + else { + * pError = ErrorAuthentication; + } + return; + } + + String * loginResponse = MCSTR(""); + if (mIsGmail) { + if (mImap->imap_response != NULL) { + loginResponse = String::stringWithUTF8Characters(mImap->imap_response); + + int location = loginResponse->locationOfString(MCSTR(" authenticated (Success)")); + if (location != -1) { + String * emailAndName = loginResponse->substringToIndex(location); + location = emailAndName->locationOfString(MCSTR(" ")); + MC_SAFE_RELEASE(mGmailUserDisplayName); + mGmailUserDisplayName = emailAndName->substringFromIndex(location + 1); + mGmailUserDisplayName->retain(); + } + } + } + MC_SAFE_REPLACE_COPY(String, mLoginResponse, loginResponse); + + 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()) { + bool hasDefaultNamespace = false; + if (isNamespaceEnabled()) { + HashMap * result = fetchNamespace(pError); + if (* pError != ErrorNone) { + MCLog("fetch namespace failed"); + return; + } + IMAPNamespace * personalNamespace = (IMAPNamespace *) result->objectForKey(IMAPNamespacePersonal); + if (personalNamespace != NULL) { + setDefaultNamespace(personalNamespace); + mDelimiter = defaultNamespace()->mainDelimiter(); + hasDefaultNamespace = true; + } + } + + if (!hasDefaultNamespace) { + 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(MCSTR(""), folder->delimiter()); + setDefaultNamespace(defaultNamespace); + } + + if (isIdentityEnabled()) { + IMAPIdentity * serverIdentity = identity(clientIdentity(), pError); + if (* pError != ErrorNone) { + // Ignore identity errors + MCLog("fetch identity failed"); + } + else { + 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"); +} + +void IMAPSession::selectIfNeeded(String * folder, ErrorCode * pError) +{ + loginIfNeeded(pError); + if (* pError != ErrorNone) + return; + + if (mState == STATE_SELECTED) { + MCAssert(mCurrentFolder != NULL); + if (mCurrentFolder->caseInsensitiveCompare(folder) != 0) { + select(folder, pError); + } + } + else if (mState == STATE_LOGGEDIN) { + select(folder, pError); + } + else { + * pError = ErrorNone; + } +} + +static uint64_t get_mod_sequence_value(mailimap * session) +{ + uint64_t mod_sequence_value; + clistiter * cur; + + mod_sequence_value = 0; + for(cur = clist_begin(session->imap_response_info->rsp_extension_list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_extension_data * ext_data; + struct mailimap_condstore_resptextcode * resptextcode; + + ext_data = (struct mailimap_extension_data *) clist_content(cur); + if (ext_data->ext_extension->ext_id != MAILIMAP_EXTENSION_CONDSTORE) { + continue; + } + if (ext_data->ext_type != MAILIMAP_CONDSTORE_TYPE_RESP_TEXT_CODE) { + continue; + } + + resptextcode = (struct mailimap_condstore_resptextcode *) ext_data->ext_data; + switch (resptextcode->cs_type) { + case MAILIMAP_CONDSTORE_RESPTEXTCODE_HIGHESTMODSEQ: + mod_sequence_value = resptextcode->cs_data.cs_modseq_value; + break; + case MAILIMAP_CONDSTORE_RESPTEXTCODE_NOMODSEQ: + mod_sequence_value = 0; + break; + } + } + + return mod_sequence_value; +} + +void IMAPSession::select(String * folder, ErrorCode * pError) +{ + int r; + + MCLog("select"); + MCAssert(mState == STATE_LOGGEDIN || mState == STATE_SELECTED); + + 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; + } + else if (r == MAILIMAP_ERROR_PARSE) { + * pError = ErrorParse; + return; + } + else if (hasError(r)) { + * pError = ErrorNonExistantFolder; + mState = STATE_LOGGEDIN; + MC_SAFE_RELEASE(mCurrentFolder); + return; + } + + MC_SAFE_REPLACE_COPY(String, mCurrentFolder, folder); + + if (mImap->imap_selection_info != NULL) { + mUIDValidity = mImap->imap_selection_info->sel_uidvalidity; + mUIDNext = mImap->imap_selection_info->sel_uidnext; + if (mImap->imap_selection_info->sel_has_exists) { + mFolderMsgCount = (unsigned int) (mImap->imap_selection_info->sel_exists); + } else { + mFolderMsgCount = -1; + } + + if (mImap->imap_selection_info->sel_first_unseen) { + mFirstUnseenUid = mImap->imap_selection_info->sel_first_unseen; + } else { + mFirstUnseenUid = 0; + } + + if (mImap->imap_selection_info->sel_perm_flags) { + clistiter * cur; + + struct mailimap_flag_perm * perm_flag; + for(cur = clist_end(mImap->imap_selection_info->sel_perm_flags) ; cur != NULL ; + cur = clist_previous(cur)) { + perm_flag = (struct mailimap_flag_perm *)clist_content(cur); + mAllowsNewPermanentFlags = perm_flag->fl_type == MAILIMAP_FLAG_PERM_ALL; + if (mAllowsNewPermanentFlags) { + break; + } + } + } + + mModSequenceValue = get_mod_sequence_value(mImap); + } + + mState = STATE_SELECTED; + * pError = ErrorNone; + MCLog("select ok"); +} + + + + + +IMAPFolderStatus * IMAPSession::folderStatus(String * folder, ErrorCode * pError) +{ + int r; + + MCLog("status"); + MCAssert(mState == STATE_LOGGEDIN || mState == STATE_SELECTED); + + struct mailimap_mailbox_data_status * status; + + struct mailimap_status_att_list * status_att_list; + + status_att_list = mailimap_status_att_list_new_empty(); + mailimap_status_att_list_add(status_att_list, MAILIMAP_STATUS_ATT_UNSEEN); + mailimap_status_att_list_add(status_att_list, MAILIMAP_STATUS_ATT_MESSAGES); + mailimap_status_att_list_add(status_att_list, MAILIMAP_STATUS_ATT_RECENT); + mailimap_status_att_list_add(status_att_list, MAILIMAP_STATUS_ATT_UIDNEXT); + mailimap_status_att_list_add(status_att_list, MAILIMAP_STATUS_ATT_UIDVALIDITY); + if (mCondstoreEnabled) { + mailimap_status_att_list_add(status_att_list, MAILIMAP_STATUS_ATT_HIGHESTMODSEQ); + } + + r = mailimap_status(mImap, MCUTF8(folder), status_att_list, &status); + + IMAPFolderStatus * fs; + fs = new IMAPFolderStatus(); + fs->autorelease(); + + MCLog("status error : %i", r); + if (r == MAILIMAP_ERROR_STREAM) { + mShouldDisconnect = true; + * pError = ErrorConnection; + MCLog("status error : %s %i", MCUTF8DESC(this), * pError); + return fs; + } + else if (r == MAILIMAP_ERROR_PARSE) { + * pError = ErrorParse; + return fs; + } + else if (hasError(r)) { + * pError = ErrorNonExistantFolder; + return fs; + } + + clistiter * cur; + + + if (status != NULL) { + + struct mailimap_status_info * status_info; + for(cur = clist_begin(status->st_info_list) ; cur != NULL ; + cur = clist_next(cur)) { + + status_info = (struct mailimap_status_info *) clist_content(cur); + + switch (status_info->st_att) { + case MAILIMAP_STATUS_ATT_UNSEEN: + fs->setUnseenCount(status_info->st_value); + break; + case MAILIMAP_STATUS_ATT_MESSAGES: + fs->setMessageCount(status_info->st_value); + break; + case MAILIMAP_STATUS_ATT_RECENT: + fs->setRecentCount(status_info->st_value); + break; + case MAILIMAP_STATUS_ATT_UIDNEXT: + fs->setUidNext(status_info->st_value); + break; + case MAILIMAP_STATUS_ATT_UIDVALIDITY: + fs->setUidValidity(status_info->st_value); + break; + case MAILIMAP_STATUS_ATT_EXTENSION: { + struct mailimap_extension_data * ext_data = status_info->st_ext_data; + if (ext_data->ext_extension == &mailimap_extension_condstore) { + struct mailimap_condstore_status_info * status_info = (struct mailimap_condstore_status_info *) ext_data->ext_data; + fs->setHighestModSeqValue(status_info->cs_highestmodseq_value); + } + break; + } + } + } + + + } + + mailimap_status_att_list_free(status_att_list); + + + return fs; +} + +void IMAPSession::noop(ErrorCode * pError) +{ + int r; + + if (mImap == NULL) + return; + + MCLog("connect"); + loginIfNeeded(pError); + if (* pError != ErrorNone) { + return; + } + if (mImap->imap_stream != NULL) { + r = mailimap_noop(mImap); + if (r == MAILIMAP_ERROR_STREAM) { + * pError = ErrorConnection; + } + if (r == MAILIMAP_ERROR_NOOP) { + * pError = ErrorNoop; + } + } +} + +#pragma mark mailbox flags conversion + +static struct { + const char * name; + int flag; +} mb_keyword_flag[] = { + {"Inbox", IMAPFolderFlagInbox}, + {"AllMail", IMAPFolderFlagAllMail}, + {"Sent", IMAPFolderFlagSentMail}, + {"Spam", IMAPFolderFlagSpam}, + {"Starred", IMAPFolderFlagStarred}, + {"Trash", IMAPFolderFlagTrash}, + {"Important", IMAPFolderFlagImportant}, + {"Drafts", IMAPFolderFlagDrafts}, + {"Archive", IMAPFolderFlagArchive}, + {"All", IMAPFolderFlagAll}, + {"Junk", IMAPFolderFlagJunk}, + {"Flagged", IMAPFolderFlagFlagged}, +}; + +static int imap_mailbox_flags_to_flags(struct mailimap_mbx_list_flags * imap_flags) +{ + int flags; + clistiter * cur; + + flags = 0; + if (imap_flags->mbf_type == MAILIMAP_MBX_LIST_FLAGS_SFLAG) { + switch (imap_flags->mbf_sflag) { + case MAILIMAP_MBX_LIST_SFLAG_MARKED: + flags |= IMAPFolderFlagMarked; + break; + case MAILIMAP_MBX_LIST_SFLAG_NOSELECT: + flags |= IMAPFolderFlagNoSelect; + break; + case MAILIMAP_MBX_LIST_SFLAG_UNMARKED: + flags |= IMAPFolderFlagUnmarked; + break; + } + } + + for(cur = clist_begin(imap_flags->mbf_oflags) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_mbx_list_oflag * oflag; + + oflag = (struct mailimap_mbx_list_oflag *) clist_content(cur); + + switch (oflag->of_type) { + case MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS: + flags |= IMAPFolderFlagNoInferiors; + break; + + case MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT: + for(unsigned int i = 0 ; i < sizeof(mb_keyword_flag) / sizeof(mb_keyword_flag[0]) ; i ++) { + if (strcasecmp(mb_keyword_flag[i].name, oflag->of_flag_ext) == 0) { + flags |= mb_keyword_flag[i].flag; + } + } + break; + } + } + + return flags; +} + +static Array * resultsWithError(int r, clist * list, ErrorCode * pError) +{ + clistiter * cur; + Array * result; + + result = Array::array(); + if (r == MAILIMAP_ERROR_STREAM) { + * pError = ErrorConnection; + return NULL; + } + else if (r == MAILIMAP_ERROR_PARSE) { + * pError = ErrorParse; + return NULL; + } + else if (hasError(r)) { + * pError = ErrorNonExistantFolder; + return NULL; + } + + for(cur = clist_begin(list) ; cur != NULL ; cur = cur->next) { + struct mailimap_mailbox_list * mb_list; + IMAPFolderFlag flags; + IMAPFolder * folder; + String * path; + + mb_list = (struct mailimap_mailbox_list *) cur->data; + + flags = IMAPFolderFlagNone; + if (mb_list->mb_flag != NULL) + flags = (IMAPFolderFlag) imap_mailbox_flags_to_flags(mb_list->mb_flag); + + folder = new IMAPFolder(); + path = String::stringWithUTF8Characters(mb_list->mb_name); + if (path->uppercaseString()->isEqual(MCSTR("INBOX"))) { + folder->setPath(MCSTR("INBOX")); + } + else { + folder->setPath(path); + } + folder->setDelimiter(mb_list->mb_delimiter); + folder->setFlags(flags); + + result->addObject(folder); + + folder->release(); + } + + mailimap_list_result_free(list); + + * pError = ErrorNone; + return result; +} + +// Deprecated +char IMAPSession::fetchDelimiterIfNeeded(char defaultDelimiter, ErrorCode * pError) +{ + int r; + clist * imap_folders; + IMAPFolder * folder; + Array * folders; + + if (defaultDelimiter != 0) + return defaultDelimiter; + + r = mailimap_list(mImap, "", "", &imap_folders); + folders = resultsWithError(r, imap_folders, pError); + if (* pError == ErrorConnection) + mShouldDisconnect = true; + if (* pError != ErrorNone) + return 0; + + if (folders->count() > 0) { + folder = (IMAPFolder *) folders->objectAtIndex(0); + } + else { + folder = NULL; + } + if (folder == NULL) + return 0; + + * pError = ErrorNone; + return folder->delimiter(); +} + +Array * /* IMAPFolder */ IMAPSession::fetchSubscribedFolders(ErrorCode * pError) +{ + int r; + clist * imap_folders; + + MCLog("fetch subscribed"); + loginIfNeeded(pError); + if (* pError != ErrorNone) + return NULL; + + if (mDelimiter == 0) { + char delimiter; + + delimiter = fetchDelimiterIfNeeded(mDelimiter, pError); + if (* pError != ErrorNone) + return NULL; + + //setDelimiter(delimiter); + mDelimiter = delimiter; + } + + String * prefix; + prefix = defaultNamespace()->mainPrefix(); + if (prefix == NULL) { + prefix = MCSTR(""); + } + if (prefix->length() > 0) { + 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); + 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; + + loginIfNeeded(pError); + if (* pError != ErrorNone) + return NULL; + + if (mDelimiter == 0) { + char delimiter; + + delimiter = fetchDelimiterIfNeeded(mDelimiter, pError); + if (* pError != ErrorNone) + return NULL; + + //setDelimiter(delimiter); + mDelimiter = delimiter; + } + + String * prefix = NULL; + if (defaultNamespace()) { + prefix = defaultNamespace()->mainPrefix(); + } + if (prefix == NULL) { + prefix = MCSTR(""); + } + if (prefix->length() > 0) { + if (!prefix->hasSuffix(String::stringWithUTF8Format("%c", mDelimiter))) { + prefix = prefix->stringByAppendingUTF8Format("%c", mDelimiter); + } + } + + if (mXListEnabled) { + r = mailimap_xlist(mImap, MCUTF8(prefix), "*", &imap_folders); + } + else { + r = mailimap_list(mImap, MCUTF8(prefix), "*", &imap_folders); + } + Array * result = resultsWithError(r, imap_folders, pError); + if (* pError == ErrorConnection) + mShouldDisconnect = true; + + if (result != NULL) { + bool hasInbox = false; + mc_foreacharray(IMAPFolder, folder, result) { + if (folder->path()->isEqual(MCSTR("INBOX"))) { + hasInbox = true; + } + } + + if (!hasInbox) { + r = mailimap_list(mImap, "", "INBOX", &imap_folders); + Array * inboxResult = resultsWithError(r, imap_folders, pError); + if (* pError == ErrorConnection) + mShouldDisconnect = true; + result->addObjectsFromArray(inboxResult); + } + } + + return result; +} + +void IMAPSession::renameFolder(String * folder, String * otherName, ErrorCode * pError) +{ + int r; + + selectIfNeeded(MCSTR("INBOX"), pError); + if (* pError != ErrorNone) + return; + + r = mailimap_rename(mImap, MCUTF8(folder), MCUTF8(otherName)); + if (r == MAILIMAP_ERROR_STREAM) { + mShouldDisconnect = true; + * pError = ErrorConnection; + return; + } + else if (r == MAILIMAP_ERROR_PARSE) { + * pError = ErrorParse; + return; + } + else if (hasError(r)) { + * pError = ErrorRename; + return; + } + * pError = ErrorNone; +} + +void IMAPSession::deleteFolder(String * folder, ErrorCode * pError) +{ + int r; + + selectIfNeeded(MCSTR("INBOX"), pError); + if (* pError != ErrorNone) + return; + + r = mailimap_delete(mImap, MCUTF8(folder)); + if (r == MAILIMAP_ERROR_STREAM) { + mShouldDisconnect = true; + * pError = ErrorConnection; + return; + } + else if (r == MAILIMAP_ERROR_PARSE) { + * pError = ErrorParse; + return; + } + else if (hasError(r)) { + * pError = ErrorDelete; + return; + } + * pError = ErrorNone; +} + +void IMAPSession::createFolder(String * folder, ErrorCode * pError) +{ + int r; + + selectIfNeeded(MCSTR("INBOX"), pError); + if (* pError != ErrorNone) + return; + + r = mailimap_create(mImap, MCUTF8(folder)); + if (r == MAILIMAP_ERROR_STREAM) { + mShouldDisconnect = true; + * pError = ErrorConnection; + return; + } + else if (r == MAILIMAP_ERROR_PARSE) { + * pError = ErrorParse; + return; + } + else if (hasError(r)) { + * pError = ErrorCreate; + return; + } + + * pError = ErrorNone; + subscribeFolder(folder, pError); +} + +void IMAPSession::subscribeFolder(String * folder, ErrorCode * pError) +{ + int r; + + selectIfNeeded(MCSTR("INBOX"), pError); + if (* pError != ErrorNone) + return; + + r = mailimap_subscribe(mImap, MCUTF8(folder)); + if (r == MAILIMAP_ERROR_STREAM) { + mShouldDisconnect = true; + * pError = ErrorConnection; + return; + } + else if (r == MAILIMAP_ERROR_PARSE) { + * pError = ErrorParse; + return; + } + else if (hasError(r)) { + * pError = ErrorSubscribe; + return; + } + * pError = ErrorNone; +} + +void IMAPSession::unsubscribeFolder(String * folder, ErrorCode * pError) +{ + int r; + + selectIfNeeded(MCSTR("INBOX"), pError); + if (* pError != ErrorNone) + return; + + r = mailimap_unsubscribe(mImap, MCUTF8(folder)); + if (r == MAILIMAP_ERROR_STREAM) { + mShouldDisconnect = true; + * pError = ErrorConnection; + return; + } + else if (r == MAILIMAP_ERROR_PARSE) { + * pError = ErrorParse; + return; + } + else if (hasError(r)) { + * pError = ErrorSubscribe; + return; + } + * pError = ErrorNone; +} + +void IMAPSession::appendMessage(String * folder, Data * messageData, MessageFlag flags, + IMAPProgressCallback * progressCallback, uint32_t * createdUID, ErrorCode * pError) +{ + this->appendMessageWithCustomFlags(folder, messageData, flags, NULL, progressCallback, createdUID, pError); +} + +void IMAPSession::appendMessageWithCustomFlags(String * folder, Data * messageData, MessageFlag flags, Array * customFlags, + IMAPProgressCallback * progressCallback, uint32_t * createdUID, ErrorCode * pError) +{ + this->appendMessageWithCustomFlagsAndDate(folder, messageData, flags, NULL, (time_t) -1, progressCallback, createdUID, pError); +} + +void IMAPSession::appendMessageWithCustomFlagsAndDate(String * folder, Data * messageData, MessageFlag flags, Array * customFlags, time_t date, + IMAPProgressCallback * progressCallback, uint32_t * createdUID, ErrorCode * pError) +{ + int r; + struct mailimap_flag_list * flag_list; + uint32_t uidvalidity; + uint32_t uidresult; + + selectIfNeeded(folder, pError); + if (* pError != ErrorNone) + return; + + mProgressCallback = progressCallback; + bodyProgress(0, messageData->length()); + + flag_list = NULL; + flag_list = flags_to_lep(flags); + if (customFlags != NULL) { + for (unsigned int i = 0 ; i < customFlags->count() ; i ++) { + struct mailimap_flag * f; + String * customFlag = (String *) customFlags->objectAtIndex(i); + + f = mailimap_flag_new_flag_keyword(strdup(customFlag->UTF8Characters())); + mailimap_flag_list_add(flag_list, f); + } + } + struct mailimap_date_time * imap_date = NULL; + if (date != (time_t) -1) { + imap_date = imapDateFromTimestamp(date); + } + r = mailimap_uidplus_append(mImap, MCUTF8(folder), flag_list, imap_date, messageData->bytes(), messageData->length(), + &uidvalidity, &uidresult); + if (imap_date != NULL) { + mailimap_date_time_free(imap_date); + } + mailimap_flag_list_free(flag_list); + + bodyProgress(messageData->length(), messageData->length()); + mProgressCallback = NULL; + + if (r == MAILIMAP_ERROR_STREAM) { + mShouldDisconnect = true; + * pError = ErrorConnection; + return; + } + else if (r == MAILIMAP_ERROR_PARSE) { + * pError = ErrorParse; + return; + } + else if (hasError(r)) { + * pError = ErrorAppend; + return; + } + + * createdUID = uidresult; + * pError = ErrorNone; +} + +void IMAPSession::copyMessages(String * folder, IndexSet * uidSet, String * destFolder, + HashMap ** pUidMapping, ErrorCode * pError) +{ + int r; + struct mailimap_set * set; + struct mailimap_set * src_uid; + struct mailimap_set * dest_uid; + uint32_t uidvalidity; + clist * setList; + IndexSet * uidSetResult; + HashMap * uidMapping = NULL; + + selectIfNeeded(folder, pError); + if (* pError != ErrorNone) + return; + + set = setFromIndexSet(uidSet); + if (clist_count(set->set_list) == 0) { + mailimap_set_free(set); + return; + } + + setList = splitSet(set, 10); + uidSetResult = NULL; + + for(clistiter * iter = clist_begin(setList) ; iter != NULL ; iter = clist_next(iter)) { + struct mailimap_set * current_set; + + current_set = (struct mailimap_set *) clist_content(iter); + + 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; + } + else if (r == MAILIMAP_ERROR_PARSE) { + * pError = ErrorParse; + goto release; + } + else if (hasError(r)) { + * pError = ErrorCopy; + goto release; + } + + if ((src_uid != NULL) && (dest_uid != NULL)) { + if (uidMapping == NULL) { + uidMapping = HashMap::hashMap(); + } + + Array * srcUidsArray = arrayFromSet(src_uid); + Array * destUidsArray = arrayFromSet(dest_uid); + + for(int i = 0 ; i < srcUidsArray->count() && i < destUidsArray->count() ; i ++) { + uidMapping->setObjectForKey(srcUidsArray->objectAtIndex(i), destUidsArray->objectAtIndex(i)); + } + } + + if (src_uid != NULL) { + mailimap_set_free(src_uid); + } + + if (dest_uid != NULL) { + mailimap_set_free(dest_uid); + } + } + if (pUidMapping != NULL) { + * pUidMapping = uidMapping; + } + * pError = ErrorNone; + + release: + + for(clistiter * iter = clist_begin(setList) ; iter != NULL ; iter = clist_next(iter)) { + struct mailimap_set * current_set; + + current_set = (struct mailimap_set *) clist_content(iter); + mailimap_set_free(current_set); + } + clist_free(setList); + mailimap_set_free(set); +} + +void IMAPSession::expunge(String * folder, ErrorCode * pError) +{ + int r; + + selectIfNeeded(folder, pError); + if (* pError != ErrorNone) + return; + + r = mailimap_expunge(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 = ErrorExpunge; + return; + } + * pError = ErrorNone; +} + +static int +fetch_imap(mailimap * imap, bool identifier_is_uid, uint32_t identifier, + struct mailimap_fetch_type * fetch_type, + char ** result, size_t * result_len) +{ + int r; + struct mailimap_msg_att * msg_att; + struct mailimap_msg_att_item * msg_att_item; + clist * fetch_result; + struct mailimap_set * set; + char * text; + size_t text_length; + clistiter * cur; + + set = mailimap_set_new_single(identifier); + if (identifier_is_uid) { + r = mailimap_uid_fetch(imap, set, fetch_type, &fetch_result); + } + else { + r = mailimap_fetch(imap, set, fetch_type, &fetch_result); + } + + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return r; + } + + if (clist_isempty(fetch_result)) { + mailimap_fetch_list_free(fetch_result); + return MAILIMAP_ERROR_FETCH; + } + + msg_att = (struct mailimap_msg_att *) clist_begin(fetch_result)->data; + + text = NULL; + text_length = 0; + + for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; + cur = clist_next(cur)) { + msg_att_item = (struct mailimap_msg_att_item *) clist_content(cur); + + if (msg_att_item->att_type != MAILIMAP_MSG_ATT_ITEM_STATIC) { + continue; + } + + if (msg_att_item->att_data.att_static->att_type != + MAILIMAP_MSG_ATT_BODY_SECTION) { + continue; + } + + text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part; + msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL; + text_length = msg_att_item->att_data.att_static->att_data.att_body_section->sec_length; + } + + mailimap_fetch_list_free(fetch_result); + + if (text == NULL) + return MAILIMAP_ERROR_FETCH; + + * result = text; + * result_len = text_length; + + return MAILIMAP_NO_ERROR; +} + +HashMap * IMAPSession::fetchMessageNumberUIDMapping(String * folder, uint32_t fromUID, uint32_t toUID, + ErrorCode * pError) +{ + struct mailimap_set * imap_set; + struct mailimap_fetch_type * fetch_type; + clist * fetch_result; + HashMap * result; + struct mailimap_fetch_att * fetch_att; + int r; + clistiter * iter; + + selectIfNeeded(folder, pError); + if (* pError != ErrorNone) + return NULL; + + result = HashMap::hashMap(); + + imap_set = mailimap_set_new_interval(fromUID, toUID); + fetch_type = mailimap_fetch_type_new_fetch_att_list_empty(); + fetch_att = mailimap_fetch_att_new_uid(); + mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + + r = mailimap_uid_fetch(mImap, imap_set, fetch_type, &fetch_result); + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(imap_set); + + if (r == MAILIMAP_ERROR_STREAM) { + MCLog("error stream"); + mShouldDisconnect = true; + * pError = ErrorConnection; + return NULL; + } + else if (r == MAILIMAP_ERROR_PARSE) { + MCLog("error parse"); + * pError = ErrorParse; + return NULL; + } + else if (hasError(r)) { + MCLog("error fetch"); + * pError = ErrorFetch; + return NULL; + } + + for(iter = clist_begin(fetch_result) ; iter != NULL ; iter = clist_next(iter)) { + struct mailimap_msg_att * msg_att; + clistiter * item_iter; + uint32_t uid; + + msg_att = (struct mailimap_msg_att *) clist_content(iter); + uid = 0; + for(item_iter = clist_begin(msg_att->att_list) ; item_iter != NULL ; item_iter = clist_next(item_iter)) { + struct mailimap_msg_att_item * att_item; + + att_item = (struct mailimap_msg_att_item *) clist_content(item_iter); + if (att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { + struct mailimap_msg_att_static * att_static; + + att_static = att_item->att_data.att_static; + if (att_static->att_type == MAILIMAP_MSG_ATT_UID) { + uid = att_static->att_data.att_uid; + } + } + } + + if (uid < fromUID) { + uid = 0; + } + + if (uid != 0) { + result->setObjectForKey(Value::valueWithUnsignedLongValue(msg_att->att_number), + Value::valueWithUnsignedLongValue(uid)); + } + } + + mailimap_fetch_list_free(fetch_result); + * pError = ErrorNone; + + return result; +} + +struct msg_att_handler_data { + IMAPSession * self; + bool fetchByUID; + Array * result; + String * folder; + IMAPMessagesRequestKind requestKind; + uint32_t mLastFetchedSequenceNumber; + HashMap * mapping; + bool needsHeader; + bool needsBody; + bool needsFlags; + bool needsGmailLabels; + bool needsGmailMessageID; + bool needsGmailThreadID; + uint32_t startUid; +}; + +static void msg_att_handler(struct mailimap_msg_att * msg_att, void * context) +{ + clistiter * item_iter; + uint32_t uid; + IMAPMessage * msg; + bool hasHeader; + bool hasBody; + bool hasFlags; + bool hasGmailLabels; + bool hasGmailMessageID; + bool hasGmailThreadID; + struct msg_att_handler_data * msg_att_context; + // struct + IMAPSession * self; + bool fetchByUID; + Array * result; + String * folder; + IMAPMessagesRequestKind requestKind; + uint32_t mLastFetchedSequenceNumber; + HashMap * mapping; + bool needsHeader; + bool needsBody; + bool needsFlags; + bool needsGmailLabels; + bool needsGmailMessageID; + bool needsGmailThreadID; + uint32_t startUid; + + msg_att_context = (struct msg_att_handler_data *) context; + self = msg_att_context->self; + fetchByUID = msg_att_context->fetchByUID; + result = msg_att_context->result; + folder = msg_att_context->folder; + requestKind = msg_att_context->requestKind; + mLastFetchedSequenceNumber = msg_att_context->mLastFetchedSequenceNumber; + mapping = msg_att_context->mapping; + needsHeader = msg_att_context->needsHeader; + needsBody = msg_att_context->needsBody; + needsFlags = msg_att_context->needsFlags; + needsGmailLabels = msg_att_context->needsGmailLabels; + needsGmailMessageID = msg_att_context->needsGmailMessageID; + needsGmailThreadID = msg_att_context->needsGmailThreadID; + startUid = msg_att_context->startUid; + + hasHeader = false; + hasBody = false; + hasFlags = false; + hasGmailLabels = false; + hasGmailMessageID = false; + hasGmailThreadID = false; + + msg = new IMAPMessage(); + + uid = 0; + mLastFetchedSequenceNumber = msg_att->att_number; + if (mapping != NULL) { + uid = (uint32_t) ((Value *) mapping->objectForKey(Value::valueWithUnsignedLongValue(msg_att->att_number)))->longLongValue(); + } + msg->setSequenceNumber(msg_att->att_number); + for(item_iter = clist_begin(msg_att->att_list) ; item_iter != NULL ; item_iter = clist_next(item_iter)) { + struct mailimap_msg_att_item * att_item; + + att_item = (struct mailimap_msg_att_item *) clist_content(item_iter); + if (att_item->att_type == MAILIMAP_MSG_ATT_ITEM_DYNAMIC) { + MessageFlag flags; + + flags = flags_from_lep_att_dynamic(att_item->att_data.att_dyn); + msg->setFlags(flags); + msg->setOriginalFlags(flags); + hasFlags = true; + + Array * customFlags; + customFlags = custom_flags_from_lep_att_dynamic(att_item->att_data.att_dyn); + msg->setCustomFlags(customFlags); + } + else if (att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { + struct mailimap_msg_att_static * att_static; + + att_static = att_item->att_data.att_static; + if (att_static->att_type == MAILIMAP_MSG_ATT_UID) { + uid = att_static->att_data.att_uid; + } + else if (att_static->att_type == MAILIMAP_MSG_ATT_ENVELOPE) { + struct mailimap_envelope * env; + + MCLog("parse envelope %lu", (unsigned long) uid); + env = att_static->att_data.att_env; + msg->header()->importIMAPEnvelope(env); + hasHeader = true; + } + else if (att_static->att_type == MAILIMAP_MSG_ATT_BODY_SECTION) { + if ((requestKind & IMAPMessagesRequestKindFullHeaders) != 0 || + (requestKind & IMAPMessagesRequestKindExtraHeaders) != 0) { + char * bytes; + size_t length; + + bytes = att_static->att_data.att_body_section->sec_body_part; + length = att_static->att_data.att_body_section->sec_length; + + msg->header()->importHeadersData(Data::dataWithBytes(bytes, (unsigned int) length)); + hasHeader = true; + } + else { + char * references; + size_t ref_size; + + // references + references = att_static->att_data.att_body_section->sec_body_part; + ref_size = att_static->att_data.att_body_section->sec_length; + + msg->header()->importIMAPReferences(Data::dataWithBytes(references, (unsigned int) ref_size)); + } + } + else if (att_static->att_type == MAILIMAP_MSG_ATT_BODYSTRUCTURE) { + AbstractPart * mainPart; + + // bodystructure + mainPart = IMAPPart::attachmentWithIMAPBody(att_static->att_data.att_body); + msg->setMainPart(mainPart); + hasBody = true; + } + } + else if (att_item->att_type == MAILIMAP_MSG_ATT_ITEM_EXTENSION) { + struct mailimap_extension_data * ext_data; + + ext_data = att_item->att_data.att_extension_data; + if (ext_data->ext_extension == &mailimap_extension_condstore) { + struct mailimap_condstore_fetch_mod_resp * fetch_data; + + fetch_data = (struct mailimap_condstore_fetch_mod_resp *) ext_data->ext_data; + msg->setModSeqValue(fetch_data->cs_modseq_value); + } + else if (ext_data->ext_extension == &mailimap_extension_xgmlabels) { + struct mailimap_msg_att_xgmlabels * cLabels; + Array * labels; + clistiter * cur; + + labels = new Array(); + hasGmailLabels = true; + cLabels = (struct mailimap_msg_att_xgmlabels *) ext_data->ext_data; + for(cur = clist_begin(cLabels->att_labels) ; cur != NULL ; cur = clist_next(cur)) { + char * cLabel; + String * label; + + cLabel = (char *) clist_content(cur); + label = String::stringWithUTF8Characters(cLabel); + labels->addObject(label); + } + if (labels->count() > 0) { + msg->setGmailLabels(labels); + } + labels->release(); + } + else if (ext_data->ext_extension == &mailimap_extension_xgmthrid) { + uint64_t * threadID; + + threadID = (uint64_t *) ext_data->ext_data; + msg->setGmailThreadID(*threadID); + hasGmailThreadID = true; + } + else if (ext_data->ext_extension == &mailimap_extension_xgmmsgid) { + uint64_t * msgID; + + msgID = (uint64_t *) ext_data->ext_data; + msg->setGmailMessageID(*msgID); + hasGmailMessageID = true; + } + } + } + for(item_iter = clist_begin(msg_att->att_list) ; item_iter != NULL ; item_iter = clist_next(item_iter)) { + struct mailimap_msg_att_item * att_item; + + att_item = (struct mailimap_msg_att_item *) clist_content(item_iter); + if (att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { + struct mailimap_msg_att_static * att_static; + + att_static = att_item->att_data.att_static; + if (att_static->att_type == MAILIMAP_MSG_ATT_INTERNALDATE) { + msg->header()->importIMAPInternalDate(att_static->att_data.att_internal_date); + } else if (att_static->att_type == MAILIMAP_MSG_ATT_RFC822_SIZE) { + msg->setSize(att_static->att_data.att_rfc822_size); + } + } + } + + if (fetchByUID) { + if (uid < startUid) { + uid = 0; + } + } + + if (needsBody && !hasBody) { + msg->release(); + return; + } + if (needsHeader && !hasHeader) { + msg->release(); + return; + } + if (needsFlags && !hasFlags) { + msg->release(); + return; + } + if (needsGmailThreadID && !hasGmailThreadID) { + msg->release(); + return; + } + if (needsGmailMessageID && !hasGmailMessageID) { + msg->release(); + return; + } + if (uid != 0) { + msg->setUid(uid); + } + else { + msg->release(); + return; + } + + result->addObject(msg); + msg->release(); + + msg_att_context->mLastFetchedSequenceNumber = mLastFetchedSequenceNumber; +} + +IMAPSyncResult * IMAPSession::fetchMessages(String * folder, IMAPMessagesRequestKind requestKind, bool fetchByUID, + struct mailimap_set * imapset, uint64_t modseq, HashMap * mapping, uint32_t startUid, + IMAPProgressCallback * progressCallback, Array * extraHeaders, ErrorCode * pError) +{ + struct mailimap_fetch_type * fetch_type; + clist * fetch_result; + struct mailimap_qresync_vanished * vanished; + struct mailimap_fetch_att * fetch_att; + int r; + bool needsHeader; + bool needsBody; + bool needsFlags; + bool needsGmailLabels; + bool needsGmailMessageID; + bool needsGmailThreadID; + Array * messages; + IndexSet * vanishedMessages; + + selectIfNeeded(folder, pError); + if (* pError != ErrorNone) + return NULL; + + if (mNeedsMboxMailWorkaround && ((requestKind & IMAPMessagesRequestKindHeaders) != 0)) { + requestKind = (IMAPMessagesRequestKind) (requestKind & ~IMAPMessagesRequestKindHeaders); + requestKind = (IMAPMessagesRequestKind) (requestKind | IMAPMessagesRequestKindFullHeaders); + } + if (extraHeaders != NULL) { + requestKind = (IMAPMessagesRequestKind) (requestKind | IMAPMessagesRequestKindExtraHeaders); + } + + if ((requestKind & IMAPMessagesRequestKindHeaders) != 0) { + mProgressItemsCount = 0; + mProgressCallback = progressCallback; + } + + messages = Array::array(); + + needsHeader = false; + needsBody = false; + needsFlags = false; + needsGmailLabels = false; + needsGmailMessageID = false; + needsGmailThreadID = false; + clist * hdrlist = clist_new(); + + fetch_type = mailimap_fetch_type_new_fetch_att_list_empty(); + fetch_att = mailimap_fetch_att_new_uid(); + mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if ((requestKind & IMAPMessagesRequestKindFlags) != 0) { + MCLog("request flags"); + fetch_att = mailimap_fetch_att_new_flags(); + mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + needsFlags = true; + } + if ((requestKind & IMAPMessagesRequestKindGmailLabels) != 0) { + MCLog("request flags"); + fetch_att = mailimap_fetch_att_new_xgmlabels(); + mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + needsGmailLabels = true; + } + if ((requestKind & IMAPMessagesRequestKindGmailThreadID) != 0) { + fetch_att = mailimap_fetch_att_new_xgmthrid(); + mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + needsGmailThreadID = true; + } + if ((requestKind & IMAPMessagesRequestKindGmailMessageID) != 0) { + fetch_att = mailimap_fetch_att_new_xgmmsgid(); + mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + needsGmailMessageID = true; + } + if ((requestKind & IMAPMessagesRequestKindFullHeaders) != 0) { + char * header; + + MCLog("request envelope"); + + // most important header + header = strdup("Date"); + clist_append(hdrlist, header); + header = strdup("Subject"); + clist_append(hdrlist, header); + header = strdup("From"); + clist_append(hdrlist, header); + header = strdup("Sender"); + clist_append(hdrlist, header); + header = strdup("Reply-To"); + clist_append(hdrlist, header); + header = strdup("To"); + clist_append(hdrlist, header); + header = strdup("Cc"); + clist_append(hdrlist, header); + header = strdup("Message-ID"); + clist_append(hdrlist, header); + header = strdup("References"); + clist_append(hdrlist, header); + header = strdup("In-Reply-To"); + clist_append(hdrlist, header); + } + if ((requestKind & IMAPMessagesRequestKindHeaders) != 0) { + char * header; + + MCLog("request envelope"); + // envelope + fetch_att = mailimap_fetch_att_new_envelope(); + mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + + // references header + header = strdup("References"); + clist_append(hdrlist, header); + if ((requestKind & IMAPMessagesRequestKindHeaderSubject) != 0) { + header = strdup("Subject"); + clist_append(hdrlist, header); + } + } + if ((requestKind & IMAPMessagesRequestKindSize) != 0) { + // message structure + MCLog("request size"); + fetch_att = mailimap_fetch_att_new_rfc822_size(); + mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + } + + if ((requestKind & IMAPMessagesRequestKindStructure) != 0) { + // message structure + MCLog("request bodystructure"); + fetch_att = mailimap_fetch_att_new_bodystructure(); + mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + needsBody = true; + } + if ((requestKind & IMAPMessagesRequestKindInternalDate) != 0) { + // internal date + fetch_att = mailimap_fetch_att_new_internaldate(); + mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + } + if ((requestKind & IMAPMessagesRequestKindExtraHeaders) != 0) { + // custom header request + char * header; + + if (extraHeaders && extraHeaders->count() > 0) { + for (unsigned int i = 0; i < extraHeaders->count(); i++) { + String * headerString = (String *)extraHeaders->objectAtIndex(i); + header = strdup(headerString->UTF8Characters()); + clist_append(hdrlist, header); + } + } + } + + if (clist_begin(hdrlist) != NULL) { + struct mailimap_header_list * imap_hdrlist; + struct mailimap_section * section; + + imap_hdrlist = mailimap_header_list_new(hdrlist); + section = mailimap_section_new_header_fields(imap_hdrlist); + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + needsHeader = true; + } + else { + clist_free(hdrlist); + } + + struct msg_att_handler_data msg_att_data; + + memset(&msg_att_data, 0, sizeof(msg_att_data)); + msg_att_data.self = this; + msg_att_data.fetchByUID = fetchByUID; + msg_att_data.result = messages; + msg_att_data.folder = folder; + msg_att_data.requestKind = requestKind; + msg_att_data.mLastFetchedSequenceNumber = mLastFetchedSequenceNumber; + msg_att_data.mapping = mapping; + msg_att_data.needsHeader = needsHeader; + msg_att_data.needsBody = needsBody; + msg_att_data.needsFlags = needsFlags; + msg_att_data.needsGmailLabels = needsGmailLabels; + msg_att_data.startUid = startUid; + msg_att_data.needsGmailMessageID = needsGmailMessageID; + msg_att_data.needsGmailThreadID = needsGmailThreadID; + mailimap_set_msg_att_handler(mImap, msg_att_handler, &msg_att_data); + + mBodyProgressEnabled = false; + vanished = NULL; + + if (fetchByUID) { + if ((modseq != 0) && (mCondstoreEnabled || mQResyncEnabled)) { + if (mQResyncEnabled) { + r = mailimap_uid_fetch_qresync(mImap, imapset, fetch_type, modseq, + &fetch_result, &vanished); + } + else { /* condstore */ + r = mailimap_uid_fetch_changedsince(mImap, imapset, fetch_type, modseq, + &fetch_result); + } + } + else { + r = mailimap_uid_fetch(mImap, imapset, fetch_type, &fetch_result); + } + } else { + if ((modseq != 0) && (mCondstoreEnabled || mQResyncEnabled)) { + if (mQResyncEnabled) { + r = mailimap_fetch_qresync(mImap, imapset, fetch_type, modseq, + &fetch_result, &vanished); + } + else { /* condstore */ + r = mailimap_fetch_changedsince(mImap, imapset, fetch_type, modseq, + &fetch_result); + } + } + else { + r = mailimap_fetch(mImap, imapset, fetch_type, &fetch_result); + } + } + + vanishedMessages = NULL; + if (vanished != NULL) { + vanishedMessages = indexSetFromSet(vanished->qr_known_uids); + } + + mBodyProgressEnabled = true; + + mProgressCallback = NULL; + + mLastFetchedSequenceNumber = msg_att_data.mLastFetchedSequenceNumber; + + mailimap_fetch_type_free(fetch_type); + + mailimap_set_msg_att_handler(mImap, NULL, NULL); + + if (r == MAILIMAP_ERROR_STREAM) { + MCLog("error stream"); + mShouldDisconnect = true; + * pError = ErrorConnection; + return NULL; + } + else if (r == MAILIMAP_ERROR_PARSE) { + MCLog("error parse"); + * pError = ErrorParse; + return NULL; + } + else if (hasError(r)) { + MCLog("error fetch"); + * pError = ErrorFetch; + return NULL; + } + + IMAPSyncResult * result; + result = new IMAPSyncResult(); + result->setModifiedOrAddedMessages(messages); + result->setVanishedMessages(vanishedMessages); + result->autorelease(); + + if ((requestKind & IMAPMessagesRequestKindHeaders) != 0) { + if (messages->count() == 0) { + unsigned int count; + + count = clist_count(fetch_result); + if (count > 0) { + requestKind = (IMAPMessagesRequestKind) (requestKind & ~IMAPMessagesRequestKindHeaders); + requestKind = (IMAPMessagesRequestKind) (requestKind | IMAPMessagesRequestKindFullHeaders); + + result = fetchMessages(folder, requestKind, fetchByUID, + imapset, modseq, NULL, startUid, progressCallback, extraHeaders, pError); + if (result != NULL) { + if (result->modifiedOrAddedMessages() != NULL) { + if (result->modifiedOrAddedMessages()->count() > 0) { + mNeedsMboxMailWorkaround = true; + } + } + } + } + } + } + + mailimap_fetch_list_free(fetch_result); + * pError = ErrorNone; + + return result; +} + +Array * IMAPSession::fetchMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * uids, IMAPProgressCallback * progressCallback, ErrorCode * pError) +{ + return fetchMessagesByUIDWithExtraHeaders(folder, requestKind, uids, progressCallback, NULL, pError); +} + + +Array * IMAPSession::fetchMessagesByUIDWithExtraHeaders(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * uids, IMAPProgressCallback * progressCallback, + Array * extraHeaders, ErrorCode * pError) +{ + struct mailimap_set * imapset = setFromIndexSet(uids); + IMAPSyncResult * syncResult = fetchMessages(folder, requestKind, true, imapset, 0, NULL, 0, + progressCallback, extraHeaders, pError); + if (syncResult == NULL) { + mailimap_set_free(imapset); + return NULL; + } + Array * result = syncResult->modifiedOrAddedMessages(); + result->retain()->autorelease(); + mailimap_set_free(imapset); + return result; +} + +Array * IMAPSession::fetchMessagesByNumber(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * numbers, IMAPProgressCallback * progressCallback, + ErrorCode * pError) +{ + return fetchMessagesByNumberWithExtraHeaders(folder, requestKind, numbers, progressCallback, NULL, pError); +} + +Array * IMAPSession::fetchMessagesByNumberWithExtraHeaders(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * numbers, IMAPProgressCallback * progressCallback, + Array * extraHeaders, ErrorCode * pError) +{ + struct mailimap_set * imapset = setFromIndexSet(numbers); + IMAPSyncResult * syncResult = fetchMessages(folder, requestKind, false, imapset, 0, NULL, 0, + progressCallback, extraHeaders, pError); + if (syncResult == NULL) { + mailimap_set_free(imapset); + return NULL; + } + Array * result = syncResult->modifiedOrAddedMessages(); + result->retain()->autorelease(); + mailimap_set_free(imapset); + return result; +} + +static int fetch_rfc822(mailimap * session, bool identifier_is_uid, + uint32_t identifier, char ** result, size_t * result_len) +{ + struct mailimap_section * section; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + + section = mailimap_section_new(NULL); + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + int r = fetch_imap(session, identifier_is_uid, identifier, + fetch_type, result, result_len); + mailimap_fetch_type_free(fetch_type); + + return r; + +#if 0 + int r; + clist * fetch_list; + struct mailimap_section * section; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + struct mailimap_set * set; + struct mailimap_msg_att * msg_att; + struct mailimap_msg_att_item * item; + int res; + clistiter * cur; + + section = mailimap_section_new(NULL); + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + + set = mailimap_set_new_single(identifier); + + if (identifier_is_uid) { + r = mailimap_uid_fetch(session, set, fetch_type, &fetch_list); + } + else { + r = mailimap_fetch(session, set, fetch_type, &fetch_list); + } + + mailimap_set_free(set); + mailimap_fetch_type_free(fetch_type); + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + if (clist_isempty(fetch_list)) { + res = MAILIMAP_ERROR_FETCH; + goto free; + } + + msg_att = (struct mailimap_msg_att *) clist_begin(fetch_list)->data; + + for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; cur = clist_next(cur)) { + item = (struct mailimap_msg_att_item *) clist_content(cur); + + if (item->att_type != MAILIMAP_MSG_ATT_ITEM_STATIC) { + continue; + } + if (item->att_data.att_static->att_type != MAILIMAP_MSG_ATT_BODY_SECTION) { + continue; + } + + * result = item->att_data.att_static->att_data.att_body_section->sec_body_part; + item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL; + mailimap_fetch_list_free(fetch_list); + + return MAILIMAP_NO_ERROR; + } + + res = MAILIMAP_ERROR_FETCH; + +free: + mailimap_fetch_list_free(fetch_list); +err: + return res; +#endif +} + +Data * IMAPSession::fetchMessageByUID(String * folder, uint32_t uid, + IMAPProgressCallback * progressCallback, ErrorCode * pError) +{ + return fetchMessage(folder, true, uid, progressCallback, pError); +} + +Data * IMAPSession::fetchMessageByNumber(String * folder, uint32_t number, + IMAPProgressCallback * progressCallback, ErrorCode * pError) +{ + return fetchMessage(folder, false, number, progressCallback, pError); +} + +Data * IMAPSession::fetchMessage(String * folder, bool identifier_is_uid, uint32_t identifier, + IMAPProgressCallback * progressCallback, ErrorCode * pError) +{ + char * rfc822; + size_t rfc822_len; + int r; + Data * data; + + selectIfNeeded(folder, pError); + if (* pError != ErrorNone) + return NULL; + + mProgressItemsCount = 0; + mProgressCallback = progressCallback; + + rfc822 = NULL; + r = fetch_rfc822(mImap, identifier_is_uid, identifier, &rfc822, &rfc822_len); + if (r == MAILIMAP_NO_ERROR) { + size_t len; + + len = 0; + if (rfc822 != NULL) { + len = strlen(rfc822); + } + bodyProgress((unsigned int) len, (unsigned int) len); + } + mProgressCallback = NULL; + + if (r == MAILIMAP_ERROR_STREAM) { + mShouldDisconnect = true; + * pError = ErrorConnection; + return NULL; + } + else if (r == MAILIMAP_ERROR_PARSE) { + * pError = ErrorParse; + return NULL; + } + else if (hasError(r)) { + * pError = ErrorFetch; + return NULL; + } + + if (rfc822 == NULL) { + data = Data::data(); + } + else { + data = Data::dataWithBytes(rfc822, (unsigned int) rfc822_len); + } + + mailimap_nstring_free(rfc822); + * pError = ErrorNone; + + return data; +} + +Data * IMAPSession::fetchMessageAttachment(String * folder, bool identifier_is_uid, + uint32_t identifier, String * partID, + Encoding encoding, IMAPProgressCallback * progressCallback, ErrorCode * pError) +{ + struct mailimap_fetch_type * fetch_type; + struct mailimap_fetch_att * fetch_att; + struct mailimap_section * section; + struct mailimap_section_part * section_part; + clist * sec_list; + Array * partIDArray; + int r; + char * text; + size_t text_length; + Data * data; + + selectIfNeeded(folder, pError); + if (* pError != ErrorNone) + return NULL; + + mProgressItemsCount = 0; + mProgressCallback = progressCallback; + bodyProgress(0, 0); + + partIDArray = partID->componentsSeparatedByString(MCSTR(".")); + sec_list = clist_new(); + for(unsigned int i = 0 ; i < partIDArray->count() ; i ++) { + uint32_t * value; + String * element; + + element = (String *) partIDArray->objectAtIndex(i); + value = (uint32_t *) malloc(sizeof(* value)); + * value = element->intValue(); + clist_append(sec_list, value); + } + section_part = mailimap_section_part_new(sec_list); + section = mailimap_section_new_part(section_part); + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + + r = fetch_imap(mImap, identifier_is_uid, identifier, fetch_type, &text, &text_length); + mailimap_fetch_type_free(fetch_type); + + mProgressCallback = NULL; + + MCLog("had error : %i", r); + if (r == MAILIMAP_ERROR_STREAM) { + mShouldDisconnect = true; + * pError = ErrorConnection; + return NULL; + } + else if (r == MAILIMAP_ERROR_PARSE) { + * pError = ErrorParse; + return NULL; + } + else if (hasError(r)) { + * pError = ErrorFetch; + return NULL; + } + + data = Data::dataWithBytes(text, (unsigned int) text_length); + data = data->decodedDataUsingEncoding(encoding); + + mailimap_nstring_free(text); + * pError = ErrorNone; + + return data; +} + +Data * IMAPSession::fetchMessageAttachmentByUID(String * folder, uint32_t uid, String * partID, + Encoding encoding, IMAPProgressCallback * progressCallback, ErrorCode * pError) +{ + return fetchMessageAttachment(folder, true, uid, partID, encoding, progressCallback, pError); +} + +Data * IMAPSession::fetchMessageAttachmentByNumber(String * folder, uint32_t number, String * partID, + Encoding encoding, IMAPProgressCallback * progressCallback, ErrorCode * pError) +{ + return fetchMessageAttachment(folder, false, number, partID, encoding, progressCallback, pError); +} + +IndexSet * IMAPSession::search(String * folder, IMAPSearchKind kind, String * searchString, ErrorCode * pError) +{ + IMAPSearchExpression * expr; + + expr = NULL; + switch (kind) { + case IMAPSearchKindAll: + { + expr = IMAPSearchExpression::searchAll(); + break; + } + case IMAPSearchKindFrom: + { + expr = IMAPSearchExpression::searchFrom(searchString); + break; + } + case IMAPSearchKindTo: + { + expr = IMAPSearchExpression::searchTo(searchString); + break; + } + case IMAPSearchKindCc: + { + expr = IMAPSearchExpression::searchCc(searchString); + break; + } + case IMAPSearchKindBcc: + { + expr = IMAPSearchExpression::searchBcc(searchString); + break; + } + case IMAPSearchKindRecipient: + { + expr = IMAPSearchExpression::searchRecipient(searchString); + break; + } + case IMAPSearchKindSubject: + { + expr = IMAPSearchExpression::searchSubject(searchString); + break; + } + case IMAPSearchKindContent: + { + expr = IMAPSearchExpression::searchContent(searchString); + break; + } + default: + { + MCAssert(0); + break; + } + } + return search(folder, expr, pError); +} + +static struct mailimap_search_key * searchKeyFromSearchExpression(IMAPSearchExpression * expression) +{ + switch (expression->kind()) { + case IMAPSearchKindAll: + { + return mailimap_search_key_new_all(); + } + case IMAPSearchKindFrom: + { + return mailimap_search_key_new_from(strdup(expression->value()->UTF8Characters())); + } + case IMAPSearchKindTo: + { + return mailimap_search_key_new_to(strdup(expression->value()->UTF8Characters())); + } + case IMAPSearchKindCc: + { + return mailimap_search_key_new_cc(strdup(expression->value()->UTF8Characters())); + } + case IMAPSearchKindBcc: + { + return mailimap_search_key_new_bcc(strdup(expression->value()->UTF8Characters())); + } + case IMAPSearchKindRecipient: + { + struct mailimap_search_key * to_search; + struct mailimap_search_key * cc_search; + struct mailimap_search_key * bcc_search; + struct mailimap_search_key * or_search1; + struct mailimap_search_key * or_search2; + + to_search = mailimap_search_key_new_to(strdup(expression->value()->UTF8Characters())); + cc_search = mailimap_search_key_new_cc(strdup(expression->value()->UTF8Characters())); + bcc_search = mailimap_search_key_new_bcc(strdup(expression->value()->UTF8Characters())); + + or_search1 = mailimap_search_key_new_or(to_search, cc_search); + or_search2 = mailimap_search_key_new_or(or_search1, bcc_search); + + return or_search2; + } + case IMAPSearchKindSubject: + { + return mailimap_search_key_new_subject(strdup(expression->value()->UTF8Characters())); + } + case IMAPSearchKindContent: + { + return mailimap_search_key_new_text(strdup(expression->value()->UTF8Characters())); + } + case IMAPSearchKindBody: + { + return mailimap_search_key_new_body(strdup(expression->value()->UTF8Characters())); + } + case IMAPSearchKindUIDs: + { + return mailimap_search_key_new_uid(setFromIndexSet(expression->uids())); + } + case IMAPSearchKindHeader: + { + return mailimap_search_key_new_header(strdup(expression->header()->UTF8Characters()), strdup(expression->value()->UTF8Characters())); + } + case IMAPSearchKindBeforeDate: + { + time_t date = expression->date(); + struct tm timeinfo; + localtime_r(&date, &timeinfo); + return mailimap_search_key_new_sentbefore(mailimap_date_new(timeinfo.tm_mday, timeinfo.tm_mon+1, timeinfo.tm_year+1900)); + } + case IMAPSearchKindOnDate: + { + time_t date = expression->date(); + struct tm timeinfo; + localtime_r(&date, &timeinfo); + return mailimap_search_key_new_senton(mailimap_date_new(timeinfo.tm_mday, timeinfo.tm_mon+1, timeinfo.tm_year+1900)); + } + case IMAPSearchKindSinceDate: + { + time_t date = expression->date(); + struct tm timeinfo; + localtime_r(&date, &timeinfo); + return mailimap_search_key_new_sentsince(mailimap_date_new(timeinfo.tm_mday, timeinfo.tm_mon+1, timeinfo.tm_year+1900)); + } + case IMAPSearchKindBeforeReceivedDate: + { + time_t date = expression->date(); + struct tm timeinfo; + localtime_r(&date, &timeinfo); + return mailimap_search_key_new_before(mailimap_date_new(timeinfo.tm_mday, timeinfo.tm_mon+1, timeinfo.tm_year+1900)); + } + case IMAPSearchKindOnReceivedDate: + { + time_t date = expression->date(); + struct tm timeinfo; + localtime_r(&date, &timeinfo); + return mailimap_search_key_new_on(mailimap_date_new(timeinfo.tm_mday, timeinfo.tm_mon+1, timeinfo.tm_year+1900)); + } + case IMAPSearchKindSinceReceivedDate: + { + time_t date = expression->date(); + struct tm timeinfo; + localtime_r(&date, &timeinfo); + return mailimap_search_key_new_since(mailimap_date_new(timeinfo.tm_mday, timeinfo.tm_mon+1, timeinfo.tm_year+1900)); + } + case IMAPSearchKindGmailThreadID: + { + return mailimap_search_key_new_xgmthrid(expression->longNumber()); + } + case IMAPSearchKindGmailMessageID: + { + return mailimap_search_key_new_xgmmsgid(expression->longNumber()); + } + case IMAPSearchKindRead: + { + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SEEN, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, 0, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, NULL, NULL); + } + case IMAPSearchKindUnread: + { + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UNSEEN, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, 0, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, NULL, NULL); + } + case IMAPSearchKindFlagged: + { + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_FLAGGED, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, 0, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, NULL, NULL); + } + case IMAPSearchKindUnflagged: + { + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UNFLAGGED, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, 0, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, NULL, NULL); + } + case IMAPSearchKindAnswered: + { + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_ANSWERED, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, 0, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, NULL, NULL); + } + case IMAPSearchKindUnanswered: + { + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UNANSWERED, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, 0, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, NULL, NULL); + } + case IMAPSearchKindDraft: + { + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_DRAFT, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, 0, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, NULL, NULL); + } + case IMAPSearchKindUndraft: + { + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UNDRAFT, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, 0, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, NULL, NULL); + } + case IMAPSearchKindDeleted: + { + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_DELETED, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, 0, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, NULL, NULL); + } + case IMAPSearchKindSpam: + { + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_KEYWORD, + NULL, NULL, NULL, NULL, NULL, + strdup("Junk"), NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, 0, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, NULL, NULL); + } + case IMAPSearchKindSizeLarger: + { + return mailimap_search_key_new_larger( (uint32_t) expression->longNumber()); + } + case IMAPSearchKindSizeSmaller: + { + return mailimap_search_key_new_smaller( (uint32_t) expression->longNumber()); + } + case IMAPSearchKindGmailRaw: + { + return mailimap_search_key_new_xgmraw(strdup(expression->value()->UTF8Characters())); + } + case IMAPSearchKindOr: + { + return mailimap_search_key_new_or(searchKeyFromSearchExpression(expression->leftExpression()), searchKeyFromSearchExpression(expression->rightExpression())); + } + case IMAPSearchKindAnd: + { + clist * list; + list = clist_new(); + clist_append(list, searchKeyFromSearchExpression(expression->leftExpression())); + clist_append(list, searchKeyFromSearchExpression(expression->rightExpression())); + return mailimap_search_key_new_multiple(list); + } + case IMAPSearchKindNot: + { + return mailimap_search_key_new_not(searchKeyFromSearchExpression(expression->leftExpression())); + } + + default: + MCAssert(0); + return NULL; + } +} + +IndexSet * IMAPSession::search(String * folder, IMAPSearchExpression * expression, ErrorCode * pError) +{ + struct mailimap_search_key * key; + + key = searchKeyFromSearchExpression(expression); + selectIfNeeded(folder, pError); + if (* pError != ErrorNone) + return NULL; + + clist * result_list = NULL; + + const char * charset = "utf-8"; + if (mYahooServer) { + charset = NULL; + } + + int r; + if (mIsGmail) { + r = mailimap_uid_search_literalplus(mImap, charset, key, &result_list); + } + else { + 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; + } + else if (r == MAILIMAP_ERROR_PARSE) { + * pError = ErrorParse; + return NULL; + } + else if (hasError(r)) { + * pError = ErrorFetch; + return NULL; + } + + IndexSet * result = IndexSet::indexSet(); + for(clistiter * cur = clist_begin(result_list) ; cur != NULL ; cur = clist_next(cur)) { + uint32_t * uid = (uint32_t *) clist_content(cur); + result->addIndex(* uid); + } + mailimap_search_result_free(result_list); + * pError = ErrorNone; + 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", "a_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 + LOCK(); + bool canIdle = mCanIdle; + if (mCanIdle) { + mailstream_setup_idle(mImap->imap_stream); + } + UNLOCK(); + return canIdle; +} + +void IMAPSession::idle(String * folder, uint32_t lastKnownUID, ErrorCode * pError) +{ + int r; + + // connection thread + selectIfNeeded(folder, pError); + if (* pError != ErrorNone) + return; + + if (lastKnownUID != 0) { + Array * msgs; + + msgs = fetchMessagesByUID(folder, IMAPMessagesRequestKindUid, IndexSet::indexSetWithRange(RangeMake(lastKnownUID, UINT64_MAX)), + NULL, pError); + if (* pError != ErrorNone) + return; + if (msgs->count() > 0) { + IMAPMessage * msg; + + msg = (IMAPMessage *) msgs->objectAtIndex(0); + if (msg->uid() > lastKnownUID) { + MCLog("found msg UID %u %u", (unsigned int) msg->uid(), (unsigned int) lastKnownUID); + return; + } + } + } + + r = mailimap_idle(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 = ErrorIdle; + return; + } + + if (!mImap->imap_selection_info->sel_has_exists && !mImap->imap_selection_info->sel_has_recent) { + int r; + r = mailstream_wait_idle(mImap->imap_stream, MAX_IDLE_DELAY); + switch (r) { + case MAILSTREAM_IDLE_ERROR: + case MAILSTREAM_IDLE_CANCELLED: + { + mShouldDisconnect = true; + * pError = ErrorConnection; + MCLog("error or cancelled"); + return; + } + case MAILSTREAM_IDLE_INTERRUPTED: + MCLog("interrupted by user"); + break; + case MAILSTREAM_IDLE_HASDATA: + MCLog("something on the socket"); + break; + case MAILSTREAM_IDLE_TIMEOUT: + MCLog("idle timeout"); + break; + } + } + else { + MCLog("found info before idling"); + } + + r = mailimap_idle_done(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 = ErrorIdle; + return; + } + * pError = ErrorNone; +} + +void IMAPSession::interruptIdle() +{ + // main thread + LOCK(); + if (mCanIdle) { + mailstream_interrupt_idle(mImap->imap_stream); + } + UNLOCK(); +} + +void IMAPSession::unsetupIdle() +{ + // main thread + LOCK(); + if (mCanIdle) { + mailstream_unsetup_idle(mImap->imap_stream); + } + UNLOCK(); +} + +void IMAPSession::disconnect() +{ + unsetup(); +} + +IMAPIdentity * IMAPSession::identity(IMAPIdentity * clientIdentity, ErrorCode * pError) +{ + connectIfNeeded(pError); + if (* pError != ErrorNone) + return NULL; + + struct mailimap_id_params_list * client_identification; + + client_identification = mailimap_id_params_list_new_empty(); + + mc_foreacharray(String, key, clientIdentity->allInfoKeys()) { + char * dup_name; + char * dup_value; + + dup_name = strdup(key->UTF8Characters()); + dup_value = strdup(clientIdentity->infoForKey(key)->UTF8Characters()); + mailimap_id_params_list_add_name_value(client_identification, dup_name, dup_value); + } + + int r; + struct mailimap_id_params_list * server_identification; + 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; + } + else if (r == MAILIMAP_ERROR_PARSE) { + * pError = ErrorParse; + return NULL; + } + else if (hasError(r)) { + * pError = ErrorIdentity; + return NULL; + } + + IMAPIdentity * result = new IMAPIdentity(); + + clistiter * cur; + for(cur = clist_begin(server_identification->idpa_list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_id_param * param; + + param = (struct mailimap_id_param *) clist_content(cur); + + String * responseKey; + String * responseValue; + responseKey = String::stringWithUTF8Characters(param->idpa_name); + responseValue = String::stringWithUTF8Characters(param->idpa_value); + result->setInfoForKey(responseKey, responseValue); + } + + mailimap_id_params_list_free(server_identification); + * pError = ErrorNone; + + result->autorelease(); + return result; +} + +void IMAPSession::bodyProgress(unsigned int current, unsigned int maximum) +{ + if (!mBodyProgressEnabled) + return; + + if (mProgressCallback != NULL) { + mProgressCallback->bodyProgress(this, current, maximum); + } +} + +void IMAPSession::itemsProgress(unsigned int current, unsigned int maximum) +{ + mProgressItemsCount ++; + if (mProgressCallback != NULL) { + mProgressCallback->itemsProgress(this, mProgressItemsCount, maximum); + } +} + +IMAPNamespace * IMAPSession::defaultNamespace() +{ + return mDefaultNamespace; +} + +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; + struct mailimap_namespace_data * namespace_data; + int r; + + loginIfNeeded(pError); + if (* pError != ErrorNone) + return NULL; + + result = HashMap::hashMap(); + r = mailimap_namespace(mImap, &namespace_data); + if (r == MAILIMAP_ERROR_STREAM) { + mShouldDisconnect = true; + * pError = ErrorConnection; + return NULL; + } + else if (r == MAILIMAP_ERROR_PARSE) { + * pError = ErrorParse; + return NULL; + } + else if (hasError(r)) { + * pError = ErrorNamespace; + return NULL; + } + + IMAPNamespace * ns; + + if (namespace_data->ns_personal != NULL) { + ns = new IMAPNamespace(); + ns->importIMAPNamespace(namespace_data->ns_personal); + result->setObjectForKey(IMAPNamespacePersonal, ns); + ns->release(); + } + + if (namespace_data->ns_other != NULL) { + ns = new IMAPNamespace(); + ns->importIMAPNamespace(namespace_data->ns_other); + result->setObjectForKey(IMAPNamespaceOther, ns); + ns->release(); + } + + if (namespace_data->ns_shared != NULL) { + ns = new IMAPNamespace(); + ns->importIMAPNamespace(namespace_data->ns_shared); + result->setObjectForKey(IMAPNamespaceShared, ns); + ns->release(); + } + + mailimap_namespace_data_free(namespace_data); + * pError = ErrorNone; + + return result; +} + +void IMAPSession::storeFlagsByUID(String * folder, IndexSet * uids, IMAPStoreFlagsRequestKind kind, MessageFlag flags, ErrorCode * pError) +{ + this->storeFlagsAndCustomFlagsByUID(folder, uids, kind, flags, NULL, pError); +} + +void IMAPSession::storeFlagsAndCustomFlagsByUID(String * folder, IndexSet * uids, IMAPStoreFlagsRequestKind kind, MessageFlag flags, Array * customFlags, ErrorCode * pError) +{ + storeFlagsAndCustomFlags(folder, true, uids, kind, flags, customFlags, pError); +} + +void IMAPSession::storeFlagsAndCustomFlags(String * folder, bool identifier_is_uid, IndexSet * identifiers, + IMAPStoreFlagsRequestKind kind, MessageFlag flags, Array * customFlags, ErrorCode * pError) +{ + struct mailimap_set * imap_set; + struct mailimap_store_att_flags * store_att_flags; + struct mailimap_flag_list * flag_list; + int r; + clist * setList; + + selectIfNeeded(folder, pError); + if (* pError != ErrorNone) + return; + + imap_set = setFromIndexSet(identifiers); + if (clist_count(imap_set->set_list) == 0) { + mailimap_set_free(imap_set); + return; + } + + setList = splitSet(imap_set, 50); + + flag_list = mailimap_flag_list_new_empty(); + if ((flags & MessageFlagSeen) != 0) { + struct mailimap_flag * f; + + f = mailimap_flag_new_seen(); + mailimap_flag_list_add(flag_list, f); + } + if ((flags & MessageFlagAnswered) != 0) { + struct mailimap_flag * f; + + f = mailimap_flag_new_answered(); + mailimap_flag_list_add(flag_list, f); + } + if ((flags & MessageFlagFlagged) != 0) { + struct mailimap_flag * f; + + f = mailimap_flag_new_flagged(); + mailimap_flag_list_add(flag_list, f); + } + if ((flags & MessageFlagDeleted) != 0) { + struct mailimap_flag * f; + + f = mailimap_flag_new_deleted(); + mailimap_flag_list_add(flag_list, f); + } + if ((flags & MessageFlagDraft) != 0) { + struct mailimap_flag * f; + + f = mailimap_flag_new_draft(); + mailimap_flag_list_add(flag_list, f); + } + if ((flags & MessageFlagMDNSent) != 0) { + struct mailimap_flag * f; + + f = mailimap_flag_new_flag_keyword(strdup("$MDNSent")); + mailimap_flag_list_add(flag_list, f); + } + if ((flags & MessageFlagForwarded) != 0) { + struct mailimap_flag * f; + + f = mailimap_flag_new_flag_keyword(strdup("$Forwarded")); + mailimap_flag_list_add(flag_list, f); + } + if ((flags & MessageFlagSubmitPending) != 0) { + struct mailimap_flag * f; + + f = mailimap_flag_new_flag_keyword(strdup("$SubmitPending")); + mailimap_flag_list_add(flag_list, f); + } + if ((flags & MessageFlagSubmitted) != 0) { + struct mailimap_flag * f; + + f = mailimap_flag_new_flag_keyword(strdup("$Submitted")); + mailimap_flag_list_add(flag_list, f); + } + + if (customFlags != NULL) { + for (unsigned int i = 0 ; i < customFlags->count() ; i ++) { + struct mailimap_flag * f; + String * customFlag = (String *) customFlags->objectAtIndex(i); + + f = mailimap_flag_new_flag_keyword(strdup(customFlag->UTF8Characters())); + mailimap_flag_list_add(flag_list, f); + } + } + + store_att_flags = NULL; + for(clistiter * iter = clist_begin(setList) ; iter != NULL ; iter = clist_next(iter)) { + struct mailimap_set * current_set; + + current_set = (struct mailimap_set *) clist_content(iter); + + switch (kind) { + case IMAPStoreFlagsRequestKindRemove: + store_att_flags = mailimap_store_att_flags_new_remove_flags_silent(flag_list); + break; + case IMAPStoreFlagsRequestKindAdd: + store_att_flags = mailimap_store_att_flags_new_add_flags_silent(flag_list); + break; + case IMAPStoreFlagsRequestKindSet: + store_att_flags = mailimap_store_att_flags_new_set_flags_silent(flag_list); + break; + } + if (identifier_is_uid) { + r = mailimap_uid_store(mImap, current_set, store_att_flags); + } + else { + r = mailimap_store(mImap, current_set, store_att_flags); + } + + if (r == MAILIMAP_ERROR_STREAM) { + mShouldDisconnect = true; + * pError = ErrorConnection; + goto release; + } + else if (r == MAILIMAP_ERROR_PARSE) { + * pError = ErrorParse; + return; + } + else if (hasError(r)) { + * pError = ErrorStore; + return; + } + } + + release: + for(clistiter * iter = clist_begin(setList) ; iter != NULL ; iter = clist_next(iter)) { + struct mailimap_set * current_set; + + current_set = (struct mailimap_set *) clist_content(iter); + mailimap_set_free(current_set); + } + clist_free(setList); + mailimap_store_att_flags_free(store_att_flags); + mailimap_set_free(imap_set); + * pError = ErrorNone; +} + +void IMAPSession::storeFlagsByNumber(String * folder, IndexSet * numbers, IMAPStoreFlagsRequestKind kind, MessageFlag flags, ErrorCode * pError) +{ + this->storeFlagsAndCustomFlagsByNumber(folder, numbers, kind, flags, NULL, pError); +} + +void IMAPSession::storeFlagsAndCustomFlagsByNumber(String * folder, IndexSet * numbers, IMAPStoreFlagsRequestKind kind, MessageFlag flags, Array * customFlags, ErrorCode * pError) +{ + storeFlagsAndCustomFlags(folder, false, numbers, kind, flags, customFlags, pError); +} + +void IMAPSession::storeLabelsByUID(String * folder, IndexSet * uids, IMAPStoreFlagsRequestKind kind, Array * labels, ErrorCode * pError) +{ + storeLabels(folder, true, uids, kind, labels, pError); +} + +void IMAPSession::storeLabelsByNumber(String * folder, IndexSet * numbers, IMAPStoreFlagsRequestKind kind, Array * labels, ErrorCode * pError) +{ + storeLabels(folder, false, numbers, kind, labels, pError); +} + +void IMAPSession::storeLabels(String * folder, bool identifier_is_uid, IndexSet * identifiers, IMAPStoreFlagsRequestKind kind, Array * labels, ErrorCode * pError) +{ + struct mailimap_set * imap_set; + struct mailimap_msg_att_xgmlabels * xgmlabels; + int r; + clist * setList; + + selectIfNeeded(folder, pError); + if (* pError != ErrorNone) + return; + + imap_set = setFromIndexSet(identifiers); + if (clist_count(imap_set->set_list) == 0) { + mailimap_set_free(imap_set); + return; + } + + setList = splitSet(imap_set, 10); + + xgmlabels = mailimap_msg_att_xgmlabels_new_empty(); + for(unsigned int i = 0 ; i < labels->count() ; i ++) { + String * label = (String *) labels->objectAtIndex(i); + mailimap_msg_att_xgmlabels_add(xgmlabels, strdup(label->UTF8Characters())); + } + + for(clistiter * iter = clist_begin(setList) ; iter != NULL ; iter = clist_next(iter)) { + struct mailimap_set * current_set; + int fl_sign; + + current_set = (struct mailimap_set *) clist_content(iter); + + switch (kind) { + case IMAPStoreFlagsRequestKindRemove: + fl_sign = -1; + break; + case IMAPStoreFlagsRequestKindAdd: + fl_sign = 1; + break; + case IMAPStoreFlagsRequestKindSet: + fl_sign = 0; + break; + } + if (identifier_is_uid) { + r = mailimap_uid_store_xgmlabels(mImap, current_set, fl_sign, 1, xgmlabels); + } + else { + r = mailimap_store_xgmlabels(mImap, current_set, fl_sign, 1, xgmlabels); + } + if (r == MAILIMAP_ERROR_STREAM) { + mShouldDisconnect = true; + * pError = ErrorConnection; + goto release; + } + else if (r == MAILIMAP_ERROR_PARSE) { + * pError = ErrorParse; + return; + } + else if (hasError(r)) { + * pError = ErrorStore; + return; + } + } + + release: + for(clistiter * iter = clist_begin(setList) ; iter != NULL ; iter = clist_next(iter)) { + struct mailimap_set * current_set; + + current_set = (struct mailimap_set *) clist_content(iter); + mailimap_set_free(current_set); + } + clist_free(setList); + mailimap_msg_att_xgmlabels_free(xgmlabels); + mailimap_set_free(imap_set); + * pError = ErrorNone; +} + +uint32_t IMAPSession::uidValidity() +{ + return mUIDValidity; +} + +uint32_t IMAPSession::uidNext() +{ + return mUIDNext; +} + +uint64_t IMAPSession::modSequenceValue() +{ + return mModSequenceValue; +} + +unsigned int IMAPSession::lastFolderMessageCount() +{ + return mFolderMsgCount; +} + +uint32_t IMAPSession::firstUnseenUid() +{ + return mFirstUnseenUid; +} + +IMAPSyncResult * IMAPSession::syncMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * uids, uint64_t modseq, + IMAPProgressCallback * progressCallback, ErrorCode * pError) +{ + return syncMessagesByUIDWithExtraHeaders(folder, requestKind, uids, modseq, progressCallback, NULL, pError); +} + +IMAPSyncResult * IMAPSession::syncMessagesByUIDWithExtraHeaders(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * uids, uint64_t modseq, + IMAPProgressCallback * progressCallback, Array * extraHeaders, + ErrorCode * pError) +{ + MCAssert(uids->rangesCount() > 0); + struct mailimap_set * imapset = setFromIndexSet(uids); + IMAPSyncResult * result = fetchMessages(folder, requestKind, true, imapset, modseq, NULL, + (uint32_t) uids->allRanges()[0].location, + progressCallback, extraHeaders, pError); + mailimap_set_free(imapset); + return result; + +} + +IndexSet * IMAPSession::capability(ErrorCode * pError) +{ + int r; + struct mailimap_capability_data * cap; + + connectIfNeeded(pError); + if (* pError != ErrorNone) + return NULL; + + r = mailimap_capability(mImap, &cap); + if (r == MAILIMAP_ERROR_STREAM) { + mShouldDisconnect = true; + * pError = ErrorConnection; + return NULL; + } + else if (r == MAILIMAP_ERROR_PARSE) { + * pError = ErrorParse; + return NULL; + } + else if (hasError(r)) { + * pError = ErrorCapability; + return NULL; + } + + mailimap_capability_data_free(cap); + + IndexSet * result = new IndexSet(); + capabilitySetWithSessionState(result); + + * pError = ErrorNone; + result->autorelease(); + return result; +} + +void IMAPSession::capabilitySetWithSessionState(IndexSet * capabilities) +{ + if (mailimap_has_extension(mImap, (char *)"STARTTLS")) { + capabilities->addIndex(IMAPCapabilityStartTLS); + } + if (mailimap_has_authentication(mImap, (char *)"PLAIN")) { + capabilities->addIndex(IMAPCapabilityAuthPlain); + } + if (mailimap_has_authentication(mImap, (char *)"LOGIN")) { + capabilities->addIndex(IMAPCapabilityAuthLogin); + } + if (mailimap_has_idle(mImap)) { + LOCK(); + mCanIdle = true; + UNLOCK(); + } + if (mailimap_has_id(mImap)) { + capabilities->addIndex(IMAPCapabilityId); + } + if (mailimap_has_xlist(mImap)) { + 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. + capabilities->addIndex(IMAPCapabilityGmail); + } + if (mailimap_has_idle(mImap)) { + capabilities->addIndex(IMAPCapabilityIdle); + } + if (mailimap_has_condstore(mImap)) { + 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); + } + if (mailimap_has_extension(mImap, (char *)"CHILDREN")) { + capabilities->addIndex(IMAPCapabilityChildren); + } + + 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; + mIsGmail = true; + } + if (capabilities->containsIndex(IMAPCapabilityIdle)) { + mIdleEnabled = true; + } + if (capabilities->containsIndex(IMAPCapabilityCondstore)) { + mCondstoreEnabled = true; + } + if (capabilities->containsIndex(IMAPCapabilityQResync)) { + mQResyncEnabled = true; + } + if (capabilities->containsIndex(IMAPCapabilityXOAuth2)) { + mXOauth2Enabled = true; + } + if (capabilities->containsIndex(IMAPCapabilityNamespace)) { + mNamespaceEnabled = true; + } + if (capabilities->containsIndex(IMAPCapabilityCompressDeflate)) { + mCompressionEnabled = true; + } +} + +bool IMAPSession::isIdleEnabled() +{ + return mIdleEnabled; +} + +bool IMAPSession::isXListEnabled() +{ + return mXListEnabled; +} + +bool IMAPSession::isCondstoreEnabled() +{ + return mCondstoreEnabled; +} + +bool IMAPSession::isQResyncEnabled() +{ + return mQResyncEnabled; +} + +bool IMAPSession::isIdentityEnabled() +{ + return mIdentityEnabled; +} + +bool IMAPSession::isXOAuthEnabled() +{ + return mXOauth2Enabled; +} + +bool IMAPSession::isNamespaceEnabled() +{ + return mNamespaceEnabled; +} + +bool IMAPSession::isCompressionEnabled() +{ + return mCompressionEnabled; +} + +bool IMAPSession::allowsNewPermanentFlags() { + return mAllowsNewPermanentFlags; +} + +bool IMAPSession::isDisconnected() +{ + return mState == STATE_DISCONNECTED; +} + +void IMAPSession::setConnectionLogger(ConnectionLogger * logger) +{ + mConnectionLogger = logger; +} + +ConnectionLogger * IMAPSession::connectionLogger() +{ + return mConnectionLogger; +} + +String * IMAPSession::htmlRendering(IMAPMessage * message, String * folder, ErrorCode * pError) +{ + HTMLRendererIMAPDataCallback * dataCallback = new HTMLRendererIMAPDataCallback(this, message->uid()); + String * htmlString = HTMLRenderer::htmlForIMAPMessage(folder, + message, + dataCallback, + NULL); + * pError = dataCallback->error(); + + if (* pError != ErrorNone) { + return NULL; + } + + MC_SAFE_RELEASE(dataCallback); + return htmlString; +} + +String * IMAPSession::htmlBodyRendering(IMAPMessage * message, String * folder, ErrorCode * pError) +{ + HTMLRendererIMAPDataCallback * dataCallback = new HTMLRendererIMAPDataCallback(this, message->uid()); + HTMLBodyRendererTemplateCallback * htmlCallback = new HTMLBodyRendererTemplateCallback(); + + String * htmlBodyString = HTMLRenderer::htmlForIMAPMessage(folder, + message, + dataCallback, + htmlCallback); + + * pError = dataCallback->error(); + + if (* pError != ErrorNone) { + return NULL; + } + + MC_SAFE_RELEASE(dataCallback); + MC_SAFE_RELEASE(htmlCallback); + return htmlBodyString; +} + +String * IMAPSession::plainTextRendering(IMAPMessage * message, String * folder, ErrorCode * pError) +{ + String * htmlString = htmlRendering(message, folder, pError); + + if (* pError != ErrorNone) { + return NULL; + } + + String * plainTextString = htmlString->flattenHTML(); + return plainTextString; +} + +String * IMAPSession::plainTextBodyRendering(IMAPMessage * message, String * folder, bool stripWhitespace, ErrorCode * pError) +{ + String * htmlBodyString = htmlBodyRendering(message, folder, pError); + + if (* pError != ErrorNone) { + return NULL; + } + + String * plainTextBodyString = htmlBodyString->flattenHTML(); + if (stripWhitespace) { + return plainTextBodyString->stripWhitespace(); + } + + 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(caps); + 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; +} + +String * IMAPSession::gmailUserDisplayName() +{ + return mGmailUserDisplayName; +} diff --git a/src/core/imap/MCIMAPSyncResult.cc b/src/core/imap/MCIMAPSyncResult.cc deleted file mode 100644 index d84f4344..00000000 --- a/src/core/imap/MCIMAPSyncResult.cc +++ /dev/null @@ -1,46 +0,0 @@ -// -// MCIMAPSyncResult.cpp -// mailcore2 -// -// Created by DINH Viêt Hoà on 3/3/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCIMAPSyncResult.h" - -#include "MCUtils.h" - -using namespace mailcore; - -IMAPSyncResult::IMAPSyncResult() -{ - mModifiedOrAddedMessages = NULL; - mVanishedMessages = NULL; -} - -IMAPSyncResult::~IMAPSyncResult() -{ - MC_SAFE_RELEASE(mModifiedOrAddedMessages); - MC_SAFE_RELEASE(mVanishedMessages); -} - -void IMAPSyncResult::setModifiedOrAddedMessages(Array * /* IMAPMessage */ messages) -{ - MC_SAFE_REPLACE_RETAIN(Array, mModifiedOrAddedMessages, messages); -} - -Array * /* IMAPMessage */ IMAPSyncResult::modifiedOrAddedMessages() -{ - return mModifiedOrAddedMessages; -} - -void IMAPSyncResult::setVanishedMessages(IndexSet * messages) -{ - MC_SAFE_REPLACE_RETAIN(IndexSet, mVanishedMessages, messages); -} - -IndexSet * IMAPSyncResult::vanishedMessages() -{ - return mVanishedMessages; -} - diff --git a/src/core/imap/MCIMAPSyncResult.cpp b/src/core/imap/MCIMAPSyncResult.cpp new file mode 100644 index 00000000..d84f4344 --- /dev/null +++ b/src/core/imap/MCIMAPSyncResult.cpp @@ -0,0 +1,46 @@ +// +// MCIMAPSyncResult.cpp +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/3/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCIMAPSyncResult.h" + +#include "MCUtils.h" + +using namespace mailcore; + +IMAPSyncResult::IMAPSyncResult() +{ + mModifiedOrAddedMessages = NULL; + mVanishedMessages = NULL; +} + +IMAPSyncResult::~IMAPSyncResult() +{ + MC_SAFE_RELEASE(mModifiedOrAddedMessages); + MC_SAFE_RELEASE(mVanishedMessages); +} + +void IMAPSyncResult::setModifiedOrAddedMessages(Array * /* IMAPMessage */ messages) +{ + MC_SAFE_REPLACE_RETAIN(Array, mModifiedOrAddedMessages, messages); +} + +Array * /* IMAPMessage */ IMAPSyncResult::modifiedOrAddedMessages() +{ + return mModifiedOrAddedMessages; +} + +void IMAPSyncResult::setVanishedMessages(IndexSet * messages) +{ + MC_SAFE_REPLACE_RETAIN(IndexSet, mVanishedMessages, messages); +} + +IndexSet * IMAPSyncResult::vanishedMessages() +{ + return mVanishedMessages; +} + diff --git a/src/core/nntp/MCNNTPGroupInfo.cc b/src/core/nntp/MCNNTPGroupInfo.cc deleted file mode 100644 index 787967f3..00000000 --- a/src/core/nntp/MCNNTPGroupInfo.cc +++ /dev/null @@ -1,64 +0,0 @@ -// -// MCNNTPGroupInfo.cpp -// mailcore2 -// -// Created by Robert Widmann on 3/6/14. -// Copyright (c) 2014 MailCore. All rights reserved. -// - -#include "MCNNTPGroupInfo.h" - -using namespace mailcore; - -void NNTPGroupInfo::init() -{ - mMessageCount = 0; -} - -NNTPGroupInfo::NNTPGroupInfo() -{ - init(); -} - - -NNTPGroupInfo::NNTPGroupInfo(NNTPGroupInfo * other) -{ - init(); - setMessageCount(other->messageCount()); - setName(other->name()); -} - -NNTPGroupInfo::~NNTPGroupInfo() -{ -} - -String * NNTPGroupInfo::description() -{ - return String::stringWithUTF8Format("<%s:%p> Group name: %s; Message count: %u", - MCUTF8(className()), this, MCUTF8(mName), mMessageCount); -} - -Object * NNTPGroupInfo::copy() -{ - return new NNTPGroupInfo(this); -} - -void NNTPGroupInfo::setName(String * name) -{ - MC_SAFE_REPLACE_COPY(String, mName, name); -} - -String * NNTPGroupInfo::name() -{ - return mName; -} - -void NNTPGroupInfo::setMessageCount(uint32_t messageCount) -{ - mMessageCount = messageCount; -} - -uint32_t NNTPGroupInfo::messageCount() -{ - return mMessageCount; -} \ No newline at end of file diff --git a/src/core/nntp/MCNNTPGroupInfo.cpp b/src/core/nntp/MCNNTPGroupInfo.cpp new file mode 100644 index 00000000..787967f3 --- /dev/null +++ b/src/core/nntp/MCNNTPGroupInfo.cpp @@ -0,0 +1,64 @@ +// +// MCNNTPGroupInfo.cpp +// mailcore2 +// +// Created by Robert Widmann on 3/6/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#include "MCNNTPGroupInfo.h" + +using namespace mailcore; + +void NNTPGroupInfo::init() +{ + mMessageCount = 0; +} + +NNTPGroupInfo::NNTPGroupInfo() +{ + init(); +} + + +NNTPGroupInfo::NNTPGroupInfo(NNTPGroupInfo * other) +{ + init(); + setMessageCount(other->messageCount()); + setName(other->name()); +} + +NNTPGroupInfo::~NNTPGroupInfo() +{ +} + +String * NNTPGroupInfo::description() +{ + return String::stringWithUTF8Format("<%s:%p> Group name: %s; Message count: %u", + MCUTF8(className()), this, MCUTF8(mName), mMessageCount); +} + +Object * NNTPGroupInfo::copy() +{ + return new NNTPGroupInfo(this); +} + +void NNTPGroupInfo::setName(String * name) +{ + MC_SAFE_REPLACE_COPY(String, mName, name); +} + +String * NNTPGroupInfo::name() +{ + return mName; +} + +void NNTPGroupInfo::setMessageCount(uint32_t messageCount) +{ + mMessageCount = messageCount; +} + +uint32_t NNTPGroupInfo::messageCount() +{ + return mMessageCount; +} \ No newline at end of file diff --git a/src/core/nntp/MCNNTPSession.cc b/src/core/nntp/MCNNTPSession.cc deleted file mode 100644 index 4f50f46e..00000000 --- a/src/core/nntp/MCNNTPSession.cc +++ /dev/null @@ -1,893 +0,0 @@ -// -// MCNNTPSession.cpp -// mailcore2 -// -// Created by Robert Widmann on 3/6/14. -// Copyright (c) 2014 MailCore. All rights reserved. -// - -#include "MCWin32.h" // should be included first. - -#include "MCNNTPSession.h" - -#include -#include - -#include "MCNNTPGroupInfo.h" -#include "MCMessageHeader.h" -#include "MCConnectionLoggerUtils.h" -#include "MCCertificateUtils.h" - -#define NNTP_DEFAULT_PORT 119 -#define NNTPS_DEFAULT_PORT 563 - -using namespace mailcore; - -static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item, struct mailimf_fields ** result); - -enum { - STATE_DISCONNECTED, - STATE_CONNECTED, - STATE_LOGGEDIN, - STATE_LISTED, - STATE_SELECTED, -}; - -void NNTPSession::init() -{ - mHostname = NULL; - mPort = NNTP_DEFAULT_PORT; - mUsername = NULL; - mPassword = NULL; - mConnectionType = ConnectionTypeClear; - mCheckCertificateEnabled = true; - mTimeout = 30; - - mNNTP = NULL; - mState = STATE_DISCONNECTED; - mConnectionLogger = NULL; -} - -NNTPSession::NNTPSession() -{ - init(); -} - -NNTPSession::~NNTPSession() -{ - MC_SAFE_RELEASE(mHostname); - MC_SAFE_RELEASE(mUsername); - MC_SAFE_RELEASE(mPassword); -} - -void NNTPSession::setHostname(String * hostname) -{ - MC_SAFE_REPLACE_COPY(String, mHostname, hostname); -} - -String * NNTPSession::hostname() -{ - return mHostname; -} - -void NNTPSession::setPort(unsigned int port) -{ - mPort = port; -} - -unsigned int NNTPSession::port() -{ - return mPort; -} - -void NNTPSession::setUsername(String * username) -{ - MC_SAFE_REPLACE_COPY(String, mUsername, username); -} - -String * NNTPSession::username() -{ - return mUsername; -} - -void NNTPSession::setPassword(String * password) -{ - MC_SAFE_REPLACE_COPY(String, mPassword, password); -} - -String * NNTPSession::password() -{ - return mPassword; -} - -void NNTPSession::setConnectionType(ConnectionType connectionType) -{ - mConnectionType = connectionType; -} - -ConnectionType NNTPSession::connectionType() -{ - return mConnectionType; -} - -void NNTPSession::setTimeout(time_t timeout) -{ - mTimeout = timeout; -} - -time_t NNTPSession::timeout() -{ - return mTimeout; -} - -void NNTPSession::setCheckCertificateEnabled(bool enabled) -{ - mCheckCertificateEnabled = enabled; -} - -bool NNTPSession::isCheckCertificateEnabled() -{ - return mCheckCertificateEnabled; -} - -bool NNTPSession::checkCertificate() -{ - if (!isCheckCertificateEnabled()) - return true; - return mailcore::checkCertificate(mNNTP->nntp_stream, hostname()); -} - -static void logger(newsnntp * nntp, int log_type, const char * buffer, size_t size, void * context) -{ - NNTPSession * session = (NNTPSession *) context; - - if (session->connectionLogger() == NULL) - return; - - ConnectionLogType type = getConnectionType(log_type); - bool isBuffer = isBufferFromLogType(log_type); - - if (isBuffer) { - Data * data = Data::dataWithBytes(buffer, (unsigned int) size); - session->connectionLogger()->log(session, type, data); - } - else { - session->connectionLogger()->log(session, type, NULL); - } -} - - -void NNTPSession::setup() -{ - mNNTP = newsnntp_new(0, NULL); - newsnntp_set_logger(mNNTP, logger, this); -} - -void NNTPSession::unsetup() -{ - if (mNNTP != NULL) { - if (mNNTP->nntp_stream != NULL) { - mailstream_close(mNNTP->nntp_stream); - mNNTP->nntp_stream = NULL; - } - newsnntp_free(mNNTP); - mNNTP = NULL; - } -} - -void NNTPSession::loginIfNeeded(ErrorCode * pError) -{ - connectIfNeeded(pError); - if (* pError != ErrorNone) { - return; - } - - if (mState == STATE_CONNECTED) { - login(pError); - } - else { - * pError = ErrorNone; - } -} - -void NNTPSession::readerIfNeeded(ErrorCode * pError) -{ - connectIfNeeded(pError); - if (* pError != ErrorNone) - return; - - if (mState == STATE_CONNECTED) { - newsnntp_mode_reader(mNNTP); - } - else { - * pError = ErrorNone; - } -} - -void NNTPSession::login(ErrorCode * pError) -{ - int r; - - if (mUsername != NULL) { - r = newsnntp_authinfo_username(mNNTP, mUsername->UTF8Characters()); - if (r == NEWSNNTP_ERROR_STREAM) { - * pError = ErrorConnection; - return; - } - else if (r != NEWSNNTP_NO_ERROR) { - * pError = ErrorAuthentication; - return; - } - } - if (mPassword != NULL) { - r = newsnntp_authinfo_password(mNNTP, mPassword->UTF8Characters()); - if (r == NEWSNNTP_ERROR_STREAM) { - * pError = ErrorConnection; - return; - } - else if (r != NEWSNNTP_NO_ERROR) { - * pError = ErrorAuthentication; - return; - } - } - - mState = STATE_LOGGEDIN; - * pError = ErrorNone; -} - -void NNTPSession::connect(ErrorCode * pError) -{ - int r; - - setup(); - - switch (mConnectionType) { - case ConnectionTypeStartTLS: - MCLog("connect %s %u", MCUTF8(hostname()), (unsigned int) port()); - r = newsnntp_socket_connect(mNNTP, MCUTF8(hostname()), port()); - if (r != NEWSNNTP_NO_ERROR) { - * pError = ErrorConnection; - return; - } - MCLog("done"); - if (!checkCertificate()) { - * pError = ErrorCertificate; - return; - } - break; - - case ConnectionTypeTLS: - MCLog("connect %s %u", MCUTF8(hostname()), (unsigned int) port()); - r = newsnntp_ssl_connect(mNNTP, MCUTF8(hostname()), port()); - if (r != NEWSNNTP_NO_ERROR) { - * pError = ErrorConnection; - return; - } - if (!checkCertificate()) { - * pError = ErrorCertificate; - return; - } - break; - - default: - r = newsnntp_socket_connect(mNNTP, MCUTF8(hostname()), port()); - if (r != NEWSNNTP_NO_ERROR) { - * pError = ErrorConnection; - return; - } - break; - } - - mailstream_low * low; - String * identifierString; - char * identifier; - - low = mailstream_get_low(mNNTP->nntp_stream); - if (mUsername != NULL) { - identifierString = String::stringWithUTF8Format("%s@%s:%u", MCUTF8(mUsername), MCUTF8(mHostname), mPort); - } - else { - identifierString = String::stringWithUTF8Format("%s:%u", MCUTF8(mUsername), mPort); - } - identifier = strdup(identifierString->UTF8Characters()); - mailstream_low_set_identifier(low, identifier); - mState = STATE_CONNECTED; - * pError = ErrorNone; -} - -void NNTPSession::connectIfNeeded(ErrorCode * pError) -{ - if (mState == STATE_DISCONNECTED) { - connect(pError); - } - else { - * pError = ErrorNone; - } -} - -void NNTPSession::disconnect() -{ - if (mNNTP == NULL) - return; - - newsnntp_quit(mNNTP); - mState = STATE_DISCONNECTED; - unsetup(); -} - -void NNTPSession::checkAccount(ErrorCode * pError) -{ - loginIfNeeded(pError); -} - -Array * NNTPSession::listAllNewsgroups(ErrorCode * pError) -{ - int r; - clist * grp_list; - - loginIfNeeded(pError); - if (* pError != ErrorNone) { - return NULL; - } - - r = newsnntp_list(mNNTP, &grp_list); - if (r == NEWSNNTP_ERROR_STREAM) { - * pError = ErrorConnection; - return NULL; - } - else if (r != NEWSNNTP_NO_ERROR) { - * pError = ErrorFetchMessageList; - return NULL; - } - - Array * result = Array::array(); - clistiter * iter; - for(iter = clist_begin(grp_list) ;iter != NULL ; iter = clist_next(iter)) { - struct newsnntp_group_info * grp_info; - String * name; - - grp_info = (struct newsnntp_group_info *) clist_content(iter); - - name = String::stringWithUTF8Characters(grp_info->grp_name); - - NNTPGroupInfo * info = new NNTPGroupInfo(); - info->setName(name); - result->addObject(info); - info->release(); - } - - newsnntp_list_free(grp_list); - * pError = ErrorNone; - mState = STATE_LISTED; - - return result; -} - -Array * NNTPSession::listDefaultNewsgroups(ErrorCode * pError) -{ - int r; - clist * subd_groups; - - MCLog("fetch subscribed"); - loginIfNeeded(pError); - if (* pError != ErrorNone) { - return NULL; - } - - r = newsnntp_list_subscriptions(mNNTP, &subd_groups); - MCLog("fetch subscribed %u", r); - - Array * result = Array::array(); - clistiter * iter; - for(iter = clist_begin(subd_groups) ;iter != NULL ; iter = clist_next(iter)) { - struct newsnntp_group_info * grp_info; - String * name; - - grp_info = (struct newsnntp_group_info *) clist_content(iter); - - name = String::stringWithUTF8Characters(strdup(grp_info->grp_name)); - name->retain(); - - NNTPGroupInfo * info = new NNTPGroupInfo(); - info->setName(name); - result->addObject(info); - info->release(); - } - newsnntp_list_subscriptions_free(subd_groups); - * pError = ErrorNone; - - return result; -} - - -MessageHeader * NNTPSession::fetchHeader(String *groupName, unsigned int index, ErrorCode * pError) -{ - int r; - char * content; - size_t content_len; - - MCLog("fetch header at index %u", index); - - selectGroup(groupName, pError); - if (* pError != ErrorNone) { - return NULL; - } - - r = newsnntp_head(mNNTP, index, &content, &content_len); - if (r != NEWSNNTP_NO_ERROR) { - * pError = ErrorFetchMessageList; - return NULL; - } - - Data * data; - data = new Data(content, (unsigned int) content_len); - MessageHeader * result = new MessageHeader(); - result->importHeadersData(data); - result->autorelease(); - data->release(); - - newsnntp_head_free(content); - * pError = ErrorNone; - - return result; -} - -Data * NNTPSession::fetchArticle(String *groupName, unsigned int index, NNTPProgressCallback * callback, ErrorCode * pError) -{ - int r; - char * content; - size_t content_len; - - MCLog("fetch article at index %u", index); - - selectGroup(groupName, pError); - if (* pError != ErrorNone) { - return NULL; - } - - r = newsnntp_article(mNNTP, index, &content, &content_len); - if (r == NEWSNNTP_ERROR_STREAM) { - * pError = ErrorConnection; - return NULL; - } - else if (r != NEWSNNTP_NO_ERROR) { - * pError = ErrorFetchMessageList; - return NULL; - } - - Data * result; - result = Data::dataWithBytes(content, (unsigned int) content_len); - newsnntp_article_free(content); - * pError = ErrorNone; - - return result; -} - -Data * NNTPSession::fetchArticleByMessageID(String * groupName, String * messageID, ErrorCode * pError) -{ - int r; - char * msgID; - char * content; - size_t content_len; - - MCLog("fetch article at message-id %s", messageID->UTF8Characters()); - - selectGroup(groupName, pError); - if (* pError != ErrorNone) { - return NULL; - } - - msgID = strdup(messageID->UTF8Characters()); - - r = newsnntp_article_by_message_id(mNNTP, msgID, &content, &content_len); - if (r == NEWSNNTP_ERROR_STREAM) { - * pError = ErrorConnection; - return NULL; - } - else if (r != NEWSNNTP_NO_ERROR) { - * pError = ErrorFetchMessageList; - return NULL; - } - - Data * result; - result = Data::dataWithBytes(content, (unsigned int) content_len); - newsnntp_article_free(content); - * pError = ErrorNone; - - return result; -} - -time_t NNTPSession::fetchServerDate(ErrorCode * pError) { - int r; - struct tm time; - time_t result; - - loginIfNeeded(pError); - if (* pError != ErrorNone) { - return NULL; - } - - r = newsnntp_date(mNNTP, &time); - - if (r == NEWSNNTP_ERROR_STREAM) { - * pError = ErrorConnection; - return NULL; - } - else if (r != NEWSNNTP_NO_ERROR) { - * pError = ErrorServerDate; - return NULL; - } - - result = timegm(&time); - * pError = ErrorNone; - - return result; -} - -IndexSet * NNTPSession::fetchAllArticles(String * groupName, ErrorCode * pError) -{ - int r; - clist * msg_list; - - selectGroup(groupName, pError); - if (* pError != ErrorNone) { - return NULL; - } - - r = newsnntp_listgroup(mNNTP, groupName->UTF8Characters(), &msg_list); - if (r == NEWSNNTP_ERROR_STREAM) { - * pError = ErrorConnection; - return NULL; - } - else if (r != NEWSNNTP_NO_ERROR) { - * pError = ErrorFetchMessageList; - return NULL; - } - - IndexSet * result = new IndexSet(); - clistiter * iter; - for(iter = clist_begin(msg_list) ;iter != NULL ; iter = clist_next(iter)) { - uint32_t *msg_info; - - msg_info = (uint32_t *) clist_content(iter); - if (!msg_info) { - continue; - } - - result->addIndex(*msg_info); - } - - newsnntp_listgroup_free(msg_list); - * pError = ErrorNone; - mState = STATE_LISTED; - - return result; -} - -Array * NNTPSession::fetchOverArticlesInRange(Range range, String * groupName, ErrorCode * pError) -{ - int r; - clist * msg_list; - - selectGroup(groupName, pError); - if (* pError != ErrorNone) { - return NULL; - } - r = newsnntp_xover_range(mNNTP, (uint32_t) range.location, (uint32_t) (range.location + range.length), &msg_list); - if (r == NEWSNNTP_ERROR_STREAM) { - * pError = ErrorConnection; - return NULL; - } - else if (r != NEWSNNTP_NO_ERROR) { - * pError = ErrorFetchMessageList; - return NULL; - } - - Array * result = Array::array(); - clistiter * iter; - for(iter = clist_begin(msg_list) ;iter != NULL ; iter = clist_next(iter)) { - struct newsnntp_xover_resp_item * item; - struct mailimf_fields * fields = NULL; - - item = (struct newsnntp_xover_resp_item *) clist_content(iter); - if (!item) { - continue; - } - - r = xover_resp_to_fields(item, &fields); - if (r == MAIL_NO_ERROR) { - MessageHeader * header = new MessageHeader(); - header->importIMFFields(fields); - result->addObject(header); - header->release(); - } - } - - newsnntp_xover_resp_list_free(msg_list); - * pError = ErrorNone; - - return result; -} - -void NNTPSession::selectGroup(String * folder, ErrorCode * pError) -{ - int r; - struct newsnntp_group_info * info; - - loginIfNeeded(pError); - if (* pError != ErrorNone) { - return; - } - - readerIfNeeded(pError); - if (* pError != ErrorNone) { - return; - } - - r = newsnntp_group(mNNTP, folder->UTF8Characters(), &info); - if (r == NEWSNNTP_ERROR_STREAM) { - * pError = ErrorConnection; - MCLog("select error : %s %i", MCUTF8DESC(this), * pError); - return; - } - else if (r == NEWSNNTP_ERROR_NO_SUCH_NEWS_GROUP) { - * pError = ErrorNonExistantFolder; - return; - } - else if (r == MAILIMAP_ERROR_PARSE) { - * pError = ErrorParse; - return; - } - - mState = STATE_SELECTED; - * pError = ErrorNone; - MCLog("select ok"); -} - -void NNTPSession::setConnectionLogger(ConnectionLogger * logger) -{ - mConnectionLogger = logger; -} - -ConnectionLogger * NNTPSession::connectionLogger() -{ - return mConnectionLogger; -} - -// Taken from nntp/nntpdriver.c -static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item, struct mailimf_fields ** result) -{ - size_t cur_token; - clist * list; - struct mailimf_fields * fields; - int r; - - list = clist_new(); - if (list == NULL) { - r = MAIL_ERROR_MEMORY; - goto err; - } - - if (item->ovr_subject != NULL) { - char * subject_str; - struct mailimf_subject * subject; - struct mailimf_field * field; - - subject_str = strdup(item->ovr_subject); - if (subject_str == NULL) { - r = MAIL_ERROR_MEMORY; - goto free_list; - } - - subject = mailimf_subject_new(subject_str); - if (subject == NULL) { - free(subject_str); - r = MAIL_ERROR_MEMORY; - goto free_list; - } - - field = mailimf_field_new(MAILIMF_FIELD_SUBJECT, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, subject, NULL, NULL, NULL); - if (field == NULL) { - mailimf_subject_free(subject); - r = MAIL_ERROR_MEMORY; - goto free_list; - } - - r = clist_append(list, field); - if (r < 0) { - mailimf_field_free(field); - r = MAIL_ERROR_MEMORY; - goto free_list; - } - } - - if (item->ovr_author != NULL) { - struct mailimf_mailbox_list * mb_list; - struct mailimf_from * from; - struct mailimf_field * field; - - cur_token = 0; - r = mailimf_mailbox_list_parse(item->ovr_author, strlen(item->ovr_author), - &cur_token, &mb_list); - switch (r) { - case MAILIMF_NO_ERROR: - from = mailimf_from_new(mb_list); - if (from == NULL) { - mailimf_mailbox_list_free(mb_list); - r = MAIL_ERROR_MEMORY; - goto free_list; - } - - field = mailimf_field_new(MAILIMF_FIELD_FROM, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, from, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL); - if (field == NULL) { - mailimf_from_free(from); - r = MAIL_ERROR_MEMORY; - goto free_list; - } - - r = clist_append(list, field); - if (r < 0) { - mailimf_field_free(field); - r = MAIL_ERROR_MEMORY; - goto free_list; - } - break; - - case MAILIMF_ERROR_PARSE: - break; - - default: - goto free_list; - } - } - - if (item->ovr_date != NULL) { - struct mailimf_date_time * date_time; - struct mailimf_orig_date * orig_date; - struct mailimf_field * field; - - cur_token = 0; - r = mailimf_date_time_parse(item->ovr_date, strlen(item->ovr_date), - &cur_token, &date_time); - switch (r) { - case MAILIMF_NO_ERROR: - orig_date = mailimf_orig_date_new(date_time); - if (orig_date == NULL) { - mailimf_date_time_free(date_time); - r = MAIL_ERROR_MEMORY; - goto free_list; - } - - field = mailimf_field_new(MAILIMF_FIELD_ORIG_DATE, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, orig_date, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL); - if (field == NULL) { - mailimf_orig_date_free(orig_date); - r = MAIL_ERROR_MEMORY; - goto free_list; - } - - r = clist_append(list, field); - if (r < 0) { - mailimf_field_free(field); - r = MAIL_ERROR_MEMORY; - goto free_list; - } - break; - - case MAILIMF_ERROR_PARSE: - break; - - default: - goto free_list; - } - } - - if (item->ovr_message_id != NULL) { - char * msgid_str; - struct mailimf_message_id * msgid; - struct mailimf_field * field; - - cur_token = 0; - r = mailimf_msg_id_parse(item->ovr_message_id, strlen(item->ovr_message_id), - &cur_token, &msgid_str); - - switch (r) { - case MAILIMF_NO_ERROR: - msgid = mailimf_message_id_new(msgid_str); - if (msgid == NULL) { - mailimf_msg_id_free(msgid_str); - r = MAIL_ERROR_MEMORY; - goto free_list; - } - - field = mailimf_field_new(MAILIMF_FIELD_MESSAGE_ID, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, msgid, NULL, - NULL, NULL, NULL, NULL, NULL); - - r = clist_append(list, field); - if (r < 0) { - mailimf_field_free(field); - r = MAIL_ERROR_MEMORY; - goto free_list; - } - break; - - case MAILIMF_ERROR_PARSE: - break; - - default: - goto free_list; - } - } - - if (item->ovr_references != NULL) { - clist * msgid_list; - struct mailimf_references * references; - struct mailimf_field * field; - - cur_token = 0; - - r = mailimf_msg_id_list_parse(item->ovr_references, strlen(item->ovr_references), - &cur_token, &msgid_list); - - switch (r) { - case MAILIMF_NO_ERROR: - references = mailimf_references_new(msgid_list); - if (references == NULL) { - clist_foreach(msgid_list, - (clist_func) mailimf_msg_id_free, NULL); - clist_free(msgid_list); - r = MAIL_ERROR_MEMORY; - goto free_list; - } - - field = mailimf_field_new(MAILIMF_FIELD_REFERENCES, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - references, NULL, NULL, NULL, NULL); - - r = clist_append(list, field); - if (r < 0) { - mailimf_field_free(field); - r = MAIL_ERROR_MEMORY; - goto free_list; - } - - case MAILIMF_ERROR_PARSE: - break; - - default: - goto free_list; - } - } - - fields = mailimf_fields_new(list); - if (fields == NULL) { - r = MAIL_ERROR_MEMORY; - goto free_list; - } - - * result = fields; - - return MAIL_NO_ERROR; - -free_list: - clist_foreach(list, (clist_func) mailimf_field_free, NULL); - clist_free(list); -err: - return r; -} diff --git a/src/core/nntp/MCNNTPSession.cpp b/src/core/nntp/MCNNTPSession.cpp new file mode 100644 index 00000000..4f50f46e --- /dev/null +++ b/src/core/nntp/MCNNTPSession.cpp @@ -0,0 +1,893 @@ +// +// MCNNTPSession.cpp +// mailcore2 +// +// Created by Robert Widmann on 3/6/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#include "MCWin32.h" // should be included first. + +#include "MCNNTPSession.h" + +#include +#include + +#include "MCNNTPGroupInfo.h" +#include "MCMessageHeader.h" +#include "MCConnectionLoggerUtils.h" +#include "MCCertificateUtils.h" + +#define NNTP_DEFAULT_PORT 119 +#define NNTPS_DEFAULT_PORT 563 + +using namespace mailcore; + +static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item, struct mailimf_fields ** result); + +enum { + STATE_DISCONNECTED, + STATE_CONNECTED, + STATE_LOGGEDIN, + STATE_LISTED, + STATE_SELECTED, +}; + +void NNTPSession::init() +{ + mHostname = NULL; + mPort = NNTP_DEFAULT_PORT; + mUsername = NULL; + mPassword = NULL; + mConnectionType = ConnectionTypeClear; + mCheckCertificateEnabled = true; + mTimeout = 30; + + mNNTP = NULL; + mState = STATE_DISCONNECTED; + mConnectionLogger = NULL; +} + +NNTPSession::NNTPSession() +{ + init(); +} + +NNTPSession::~NNTPSession() +{ + MC_SAFE_RELEASE(mHostname); + MC_SAFE_RELEASE(mUsername); + MC_SAFE_RELEASE(mPassword); +} + +void NNTPSession::setHostname(String * hostname) +{ + MC_SAFE_REPLACE_COPY(String, mHostname, hostname); +} + +String * NNTPSession::hostname() +{ + return mHostname; +} + +void NNTPSession::setPort(unsigned int port) +{ + mPort = port; +} + +unsigned int NNTPSession::port() +{ + return mPort; +} + +void NNTPSession::setUsername(String * username) +{ + MC_SAFE_REPLACE_COPY(String, mUsername, username); +} + +String * NNTPSession::username() +{ + return mUsername; +} + +void NNTPSession::setPassword(String * password) +{ + MC_SAFE_REPLACE_COPY(String, mPassword, password); +} + +String * NNTPSession::password() +{ + return mPassword; +} + +void NNTPSession::setConnectionType(ConnectionType connectionType) +{ + mConnectionType = connectionType; +} + +ConnectionType NNTPSession::connectionType() +{ + return mConnectionType; +} + +void NNTPSession::setTimeout(time_t timeout) +{ + mTimeout = timeout; +} + +time_t NNTPSession::timeout() +{ + return mTimeout; +} + +void NNTPSession::setCheckCertificateEnabled(bool enabled) +{ + mCheckCertificateEnabled = enabled; +} + +bool NNTPSession::isCheckCertificateEnabled() +{ + return mCheckCertificateEnabled; +} + +bool NNTPSession::checkCertificate() +{ + if (!isCheckCertificateEnabled()) + return true; + return mailcore::checkCertificate(mNNTP->nntp_stream, hostname()); +} + +static void logger(newsnntp * nntp, int log_type, const char * buffer, size_t size, void * context) +{ + NNTPSession * session = (NNTPSession *) context; + + if (session->connectionLogger() == NULL) + return; + + ConnectionLogType type = getConnectionType(log_type); + bool isBuffer = isBufferFromLogType(log_type); + + if (isBuffer) { + Data * data = Data::dataWithBytes(buffer, (unsigned int) size); + session->connectionLogger()->log(session, type, data); + } + else { + session->connectionLogger()->log(session, type, NULL); + } +} + + +void NNTPSession::setup() +{ + mNNTP = newsnntp_new(0, NULL); + newsnntp_set_logger(mNNTP, logger, this); +} + +void NNTPSession::unsetup() +{ + if (mNNTP != NULL) { + if (mNNTP->nntp_stream != NULL) { + mailstream_close(mNNTP->nntp_stream); + mNNTP->nntp_stream = NULL; + } + newsnntp_free(mNNTP); + mNNTP = NULL; + } +} + +void NNTPSession::loginIfNeeded(ErrorCode * pError) +{ + connectIfNeeded(pError); + if (* pError != ErrorNone) { + return; + } + + if (mState == STATE_CONNECTED) { + login(pError); + } + else { + * pError = ErrorNone; + } +} + +void NNTPSession::readerIfNeeded(ErrorCode * pError) +{ + connectIfNeeded(pError); + if (* pError != ErrorNone) + return; + + if (mState == STATE_CONNECTED) { + newsnntp_mode_reader(mNNTP); + } + else { + * pError = ErrorNone; + } +} + +void NNTPSession::login(ErrorCode * pError) +{ + int r; + + if (mUsername != NULL) { + r = newsnntp_authinfo_username(mNNTP, mUsername->UTF8Characters()); + if (r == NEWSNNTP_ERROR_STREAM) { + * pError = ErrorConnection; + return; + } + else if (r != NEWSNNTP_NO_ERROR) { + * pError = ErrorAuthentication; + return; + } + } + if (mPassword != NULL) { + r = newsnntp_authinfo_password(mNNTP, mPassword->UTF8Characters()); + if (r == NEWSNNTP_ERROR_STREAM) { + * pError = ErrorConnection; + return; + } + else if (r != NEWSNNTP_NO_ERROR) { + * pError = ErrorAuthentication; + return; + } + } + + mState = STATE_LOGGEDIN; + * pError = ErrorNone; +} + +void NNTPSession::connect(ErrorCode * pError) +{ + int r; + + setup(); + + switch (mConnectionType) { + case ConnectionTypeStartTLS: + MCLog("connect %s %u", MCUTF8(hostname()), (unsigned int) port()); + r = newsnntp_socket_connect(mNNTP, MCUTF8(hostname()), port()); + if (r != NEWSNNTP_NO_ERROR) { + * pError = ErrorConnection; + return; + } + MCLog("done"); + if (!checkCertificate()) { + * pError = ErrorCertificate; + return; + } + break; + + case ConnectionTypeTLS: + MCLog("connect %s %u", MCUTF8(hostname()), (unsigned int) port()); + r = newsnntp_ssl_connect(mNNTP, MCUTF8(hostname()), port()); + if (r != NEWSNNTP_NO_ERROR) { + * pError = ErrorConnection; + return; + } + if (!checkCertificate()) { + * pError = ErrorCertificate; + return; + } + break; + + default: + r = newsnntp_socket_connect(mNNTP, MCUTF8(hostname()), port()); + if (r != NEWSNNTP_NO_ERROR) { + * pError = ErrorConnection; + return; + } + break; + } + + mailstream_low * low; + String * identifierString; + char * identifier; + + low = mailstream_get_low(mNNTP->nntp_stream); + if (mUsername != NULL) { + identifierString = String::stringWithUTF8Format("%s@%s:%u", MCUTF8(mUsername), MCUTF8(mHostname), mPort); + } + else { + identifierString = String::stringWithUTF8Format("%s:%u", MCUTF8(mUsername), mPort); + } + identifier = strdup(identifierString->UTF8Characters()); + mailstream_low_set_identifier(low, identifier); + mState = STATE_CONNECTED; + * pError = ErrorNone; +} + +void NNTPSession::connectIfNeeded(ErrorCode * pError) +{ + if (mState == STATE_DISCONNECTED) { + connect(pError); + } + else { + * pError = ErrorNone; + } +} + +void NNTPSession::disconnect() +{ + if (mNNTP == NULL) + return; + + newsnntp_quit(mNNTP); + mState = STATE_DISCONNECTED; + unsetup(); +} + +void NNTPSession::checkAccount(ErrorCode * pError) +{ + loginIfNeeded(pError); +} + +Array * NNTPSession::listAllNewsgroups(ErrorCode * pError) +{ + int r; + clist * grp_list; + + loginIfNeeded(pError); + if (* pError != ErrorNone) { + return NULL; + } + + r = newsnntp_list(mNNTP, &grp_list); + if (r == NEWSNNTP_ERROR_STREAM) { + * pError = ErrorConnection; + return NULL; + } + else if (r != NEWSNNTP_NO_ERROR) { + * pError = ErrorFetchMessageList; + return NULL; + } + + Array * result = Array::array(); + clistiter * iter; + for(iter = clist_begin(grp_list) ;iter != NULL ; iter = clist_next(iter)) { + struct newsnntp_group_info * grp_info; + String * name; + + grp_info = (struct newsnntp_group_info *) clist_content(iter); + + name = String::stringWithUTF8Characters(grp_info->grp_name); + + NNTPGroupInfo * info = new NNTPGroupInfo(); + info->setName(name); + result->addObject(info); + info->release(); + } + + newsnntp_list_free(grp_list); + * pError = ErrorNone; + mState = STATE_LISTED; + + return result; +} + +Array * NNTPSession::listDefaultNewsgroups(ErrorCode * pError) +{ + int r; + clist * subd_groups; + + MCLog("fetch subscribed"); + loginIfNeeded(pError); + if (* pError != ErrorNone) { + return NULL; + } + + r = newsnntp_list_subscriptions(mNNTP, &subd_groups); + MCLog("fetch subscribed %u", r); + + Array * result = Array::array(); + clistiter * iter; + for(iter = clist_begin(subd_groups) ;iter != NULL ; iter = clist_next(iter)) { + struct newsnntp_group_info * grp_info; + String * name; + + grp_info = (struct newsnntp_group_info *) clist_content(iter); + + name = String::stringWithUTF8Characters(strdup(grp_info->grp_name)); + name->retain(); + + NNTPGroupInfo * info = new NNTPGroupInfo(); + info->setName(name); + result->addObject(info); + info->release(); + } + newsnntp_list_subscriptions_free(subd_groups); + * pError = ErrorNone; + + return result; +} + + +MessageHeader * NNTPSession::fetchHeader(String *groupName, unsigned int index, ErrorCode * pError) +{ + int r; + char * content; + size_t content_len; + + MCLog("fetch header at index %u", index); + + selectGroup(groupName, pError); + if (* pError != ErrorNone) { + return NULL; + } + + r = newsnntp_head(mNNTP, index, &content, &content_len); + if (r != NEWSNNTP_NO_ERROR) { + * pError = ErrorFetchMessageList; + return NULL; + } + + Data * data; + data = new Data(content, (unsigned int) content_len); + MessageHeader * result = new MessageHeader(); + result->importHeadersData(data); + result->autorelease(); + data->release(); + + newsnntp_head_free(content); + * pError = ErrorNone; + + return result; +} + +Data * NNTPSession::fetchArticle(String *groupName, unsigned int index, NNTPProgressCallback * callback, ErrorCode * pError) +{ + int r; + char * content; + size_t content_len; + + MCLog("fetch article at index %u", index); + + selectGroup(groupName, pError); + if (* pError != ErrorNone) { + return NULL; + } + + r = newsnntp_article(mNNTP, index, &content, &content_len); + if (r == NEWSNNTP_ERROR_STREAM) { + * pError = ErrorConnection; + return NULL; + } + else if (r != NEWSNNTP_NO_ERROR) { + * pError = ErrorFetchMessageList; + return NULL; + } + + Data * result; + result = Data::dataWithBytes(content, (unsigned int) content_len); + newsnntp_article_free(content); + * pError = ErrorNone; + + return result; +} + +Data * NNTPSession::fetchArticleByMessageID(String * groupName, String * messageID, ErrorCode * pError) +{ + int r; + char * msgID; + char * content; + size_t content_len; + + MCLog("fetch article at message-id %s", messageID->UTF8Characters()); + + selectGroup(groupName, pError); + if (* pError != ErrorNone) { + return NULL; + } + + msgID = strdup(messageID->UTF8Characters()); + + r = newsnntp_article_by_message_id(mNNTP, msgID, &content, &content_len); + if (r == NEWSNNTP_ERROR_STREAM) { + * pError = ErrorConnection; + return NULL; + } + else if (r != NEWSNNTP_NO_ERROR) { + * pError = ErrorFetchMessageList; + return NULL; + } + + Data * result; + result = Data::dataWithBytes(content, (unsigned int) content_len); + newsnntp_article_free(content); + * pError = ErrorNone; + + return result; +} + +time_t NNTPSession::fetchServerDate(ErrorCode * pError) { + int r; + struct tm time; + time_t result; + + loginIfNeeded(pError); + if (* pError != ErrorNone) { + return NULL; + } + + r = newsnntp_date(mNNTP, &time); + + if (r == NEWSNNTP_ERROR_STREAM) { + * pError = ErrorConnection; + return NULL; + } + else if (r != NEWSNNTP_NO_ERROR) { + * pError = ErrorServerDate; + return NULL; + } + + result = timegm(&time); + * pError = ErrorNone; + + return result; +} + +IndexSet * NNTPSession::fetchAllArticles(String * groupName, ErrorCode * pError) +{ + int r; + clist * msg_list; + + selectGroup(groupName, pError); + if (* pError != ErrorNone) { + return NULL; + } + + r = newsnntp_listgroup(mNNTP, groupName->UTF8Characters(), &msg_list); + if (r == NEWSNNTP_ERROR_STREAM) { + * pError = ErrorConnection; + return NULL; + } + else if (r != NEWSNNTP_NO_ERROR) { + * pError = ErrorFetchMessageList; + return NULL; + } + + IndexSet * result = new IndexSet(); + clistiter * iter; + for(iter = clist_begin(msg_list) ;iter != NULL ; iter = clist_next(iter)) { + uint32_t *msg_info; + + msg_info = (uint32_t *) clist_content(iter); + if (!msg_info) { + continue; + } + + result->addIndex(*msg_info); + } + + newsnntp_listgroup_free(msg_list); + * pError = ErrorNone; + mState = STATE_LISTED; + + return result; +} + +Array * NNTPSession::fetchOverArticlesInRange(Range range, String * groupName, ErrorCode * pError) +{ + int r; + clist * msg_list; + + selectGroup(groupName, pError); + if (* pError != ErrorNone) { + return NULL; + } + r = newsnntp_xover_range(mNNTP, (uint32_t) range.location, (uint32_t) (range.location + range.length), &msg_list); + if (r == NEWSNNTP_ERROR_STREAM) { + * pError = ErrorConnection; + return NULL; + } + else if (r != NEWSNNTP_NO_ERROR) { + * pError = ErrorFetchMessageList; + return NULL; + } + + Array * result = Array::array(); + clistiter * iter; + for(iter = clist_begin(msg_list) ;iter != NULL ; iter = clist_next(iter)) { + struct newsnntp_xover_resp_item * item; + struct mailimf_fields * fields = NULL; + + item = (struct newsnntp_xover_resp_item *) clist_content(iter); + if (!item) { + continue; + } + + r = xover_resp_to_fields(item, &fields); + if (r == MAIL_NO_ERROR) { + MessageHeader * header = new MessageHeader(); + header->importIMFFields(fields); + result->addObject(header); + header->release(); + } + } + + newsnntp_xover_resp_list_free(msg_list); + * pError = ErrorNone; + + return result; +} + +void NNTPSession::selectGroup(String * folder, ErrorCode * pError) +{ + int r; + struct newsnntp_group_info * info; + + loginIfNeeded(pError); + if (* pError != ErrorNone) { + return; + } + + readerIfNeeded(pError); + if (* pError != ErrorNone) { + return; + } + + r = newsnntp_group(mNNTP, folder->UTF8Characters(), &info); + if (r == NEWSNNTP_ERROR_STREAM) { + * pError = ErrorConnection; + MCLog("select error : %s %i", MCUTF8DESC(this), * pError); + return; + } + else if (r == NEWSNNTP_ERROR_NO_SUCH_NEWS_GROUP) { + * pError = ErrorNonExistantFolder; + return; + } + else if (r == MAILIMAP_ERROR_PARSE) { + * pError = ErrorParse; + return; + } + + mState = STATE_SELECTED; + * pError = ErrorNone; + MCLog("select ok"); +} + +void NNTPSession::setConnectionLogger(ConnectionLogger * logger) +{ + mConnectionLogger = logger; +} + +ConnectionLogger * NNTPSession::connectionLogger() +{ + return mConnectionLogger; +} + +// Taken from nntp/nntpdriver.c +static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item, struct mailimf_fields ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_fields * fields; + int r; + + list = clist_new(); + if (list == NULL) { + r = MAIL_ERROR_MEMORY; + goto err; + } + + if (item->ovr_subject != NULL) { + char * subject_str; + struct mailimf_subject * subject; + struct mailimf_field * field; + + subject_str = strdup(item->ovr_subject); + if (subject_str == NULL) { + r = MAIL_ERROR_MEMORY; + goto free_list; + } + + subject = mailimf_subject_new(subject_str); + if (subject == NULL) { + free(subject_str); + r = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_SUBJECT, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, subject, NULL, NULL, NULL); + if (field == NULL) { + mailimf_subject_free(subject); + r = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r < 0) { + mailimf_field_free(field); + r = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + if (item->ovr_author != NULL) { + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + struct mailimf_field * field; + + cur_token = 0; + r = mailimf_mailbox_list_parse(item->ovr_author, strlen(item->ovr_author), + &cur_token, &mb_list); + switch (r) { + case MAILIMF_NO_ERROR: + from = mailimf_from_new(mb_list); + if (from == NULL) { + mailimf_mailbox_list_free(mb_list); + r = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, from, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_from_free(from); + r = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r < 0) { + mailimf_field_free(field); + r = MAIL_ERROR_MEMORY; + goto free_list; + } + break; + + case MAILIMF_ERROR_PARSE: + break; + + default: + goto free_list; + } + } + + if (item->ovr_date != NULL) { + struct mailimf_date_time * date_time; + struct mailimf_orig_date * orig_date; + struct mailimf_field * field; + + cur_token = 0; + r = mailimf_date_time_parse(item->ovr_date, strlen(item->ovr_date), + &cur_token, &date_time); + switch (r) { + case MAILIMF_NO_ERROR: + orig_date = mailimf_orig_date_new(date_time); + if (orig_date == NULL) { + mailimf_date_time_free(date_time); + r = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_ORIG_DATE, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, orig_date, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_orig_date_free(orig_date); + r = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r < 0) { + mailimf_field_free(field); + r = MAIL_ERROR_MEMORY; + goto free_list; + } + break; + + case MAILIMF_ERROR_PARSE: + break; + + default: + goto free_list; + } + } + + if (item->ovr_message_id != NULL) { + char * msgid_str; + struct mailimf_message_id * msgid; + struct mailimf_field * field; + + cur_token = 0; + r = mailimf_msg_id_parse(item->ovr_message_id, strlen(item->ovr_message_id), + &cur_token, &msgid_str); + + switch (r) { + case MAILIMF_NO_ERROR: + msgid = mailimf_message_id_new(msgid_str); + if (msgid == NULL) { + mailimf_msg_id_free(msgid_str); + r = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_MESSAGE_ID, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, msgid, NULL, + NULL, NULL, NULL, NULL, NULL); + + r = clist_append(list, field); + if (r < 0) { + mailimf_field_free(field); + r = MAIL_ERROR_MEMORY; + goto free_list; + } + break; + + case MAILIMF_ERROR_PARSE: + break; + + default: + goto free_list; + } + } + + if (item->ovr_references != NULL) { + clist * msgid_list; + struct mailimf_references * references; + struct mailimf_field * field; + + cur_token = 0; + + r = mailimf_msg_id_list_parse(item->ovr_references, strlen(item->ovr_references), + &cur_token, &msgid_list); + + switch (r) { + case MAILIMF_NO_ERROR: + references = mailimf_references_new(msgid_list); + if (references == NULL) { + clist_foreach(msgid_list, + (clist_func) mailimf_msg_id_free, NULL); + clist_free(msgid_list); + r = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_REFERENCES, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + references, NULL, NULL, NULL, NULL); + + r = clist_append(list, field); + if (r < 0) { + mailimf_field_free(field); + r = MAIL_ERROR_MEMORY; + goto free_list; + } + + case MAILIMF_ERROR_PARSE: + break; + + default: + goto free_list; + } + } + + fields = mailimf_fields_new(list); + if (fields == NULL) { + r = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = fields; + + return MAIL_NO_ERROR; + +free_list: + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); +err: + return r; +} diff --git a/src/core/pop/MCPOPMessageInfo.cc b/src/core/pop/MCPOPMessageInfo.cc deleted file mode 100644 index 418d159d..00000000 --- a/src/core/pop/MCPOPMessageInfo.cc +++ /dev/null @@ -1,69 +0,0 @@ -#include "MCPOPMessageInfo.h" - -using namespace mailcore; - -void POPMessageInfo::init() -{ - mIndex = 0; - mSize = 0; - mUid = NULL; -} - -POPMessageInfo::POPMessageInfo() -{ - init(); -} - -POPMessageInfo::POPMessageInfo(POPMessageInfo * other) -{ - init(); - mIndex = other->mIndex; - mSize = other->mSize; - MC_SAFE_REPLACE_COPY(String, mUid, other->mUid); -} - -POPMessageInfo::~POPMessageInfo() -{ - MC_SAFE_RELEASE(mUid); -} - -String * POPMessageInfo::description() -{ - return String::stringWithUTF8Format("<%s:%p %u %s %u>", - MCUTF8(className()), this, mIndex, MCUTF8(mUid), mSize); -} - -Object * POPMessageInfo::copy() -{ - return new POPMessageInfo(this); -} - -void POPMessageInfo::setIndex(unsigned int index) -{ - mIndex = index; -} - -unsigned int POPMessageInfo::index() -{ - return mIndex; -} - -void POPMessageInfo::setSize(unsigned int size) -{ - mSize = size; -} - -unsigned int POPMessageInfo::size() -{ - return mSize; -} - -void POPMessageInfo::setUid(String * uid) -{ - MC_SAFE_REPLACE_COPY(String, mUid, uid); -} - -String * POPMessageInfo::uid() -{ - return mUid; -} diff --git a/src/core/pop/MCPOPMessageInfo.cpp b/src/core/pop/MCPOPMessageInfo.cpp new file mode 100644 index 00000000..418d159d --- /dev/null +++ b/src/core/pop/MCPOPMessageInfo.cpp @@ -0,0 +1,69 @@ +#include "MCPOPMessageInfo.h" + +using namespace mailcore; + +void POPMessageInfo::init() +{ + mIndex = 0; + mSize = 0; + mUid = NULL; +} + +POPMessageInfo::POPMessageInfo() +{ + init(); +} + +POPMessageInfo::POPMessageInfo(POPMessageInfo * other) +{ + init(); + mIndex = other->mIndex; + mSize = other->mSize; + MC_SAFE_REPLACE_COPY(String, mUid, other->mUid); +} + +POPMessageInfo::~POPMessageInfo() +{ + MC_SAFE_RELEASE(mUid); +} + +String * POPMessageInfo::description() +{ + return String::stringWithUTF8Format("<%s:%p %u %s %u>", + MCUTF8(className()), this, mIndex, MCUTF8(mUid), mSize); +} + +Object * POPMessageInfo::copy() +{ + return new POPMessageInfo(this); +} + +void POPMessageInfo::setIndex(unsigned int index) +{ + mIndex = index; +} + +unsigned int POPMessageInfo::index() +{ + return mIndex; +} + +void POPMessageInfo::setSize(unsigned int size) +{ + mSize = size; +} + +unsigned int POPMessageInfo::size() +{ + return mSize; +} + +void POPMessageInfo::setUid(String * uid) +{ + MC_SAFE_REPLACE_COPY(String, mUid, uid); +} + +String * POPMessageInfo::uid() +{ + return mUid; +} diff --git a/src/core/pop/MCPOPSession.cc b/src/core/pop/MCPOPSession.cc deleted file mode 100644 index 8415a081..00000000 --- a/src/core/pop/MCPOPSession.cc +++ /dev/null @@ -1,602 +0,0 @@ -#include "MCWin32.h" // should be included first. - -#include "MCPOPSession.h" - -#include -#include - -#include "MCPOPMessageInfo.h" -#include "MCPOPProgressCallback.h" -#include "MCMessageHeader.h" -#include "MCConnectionLoggerUtils.h" -#include "MCCertificateUtils.h" - -using namespace mailcore; - -enum { - STATE_DISCONNECTED, - STATE_CONNECTED, - STATE_LOGGEDIN, - STATE_LISTED, -}; - -void POPSession::init() -{ - mHostname = NULL; - mPort = 0; - mUsername = NULL; - mPassword = NULL; - mAuthType = AuthTypeSASLNone; - mConnectionType = ConnectionTypeClear; - mCheckCertificateEnabled = true; - mTimeout = 30; - - mPop = NULL; - mCapabilities = POPCapabilityNone; - mProgressCallback = NULL; - mState = STATE_DISCONNECTED; - mConnectionLogger = NULL; -} - -POPSession::POPSession() -{ - init(); -} - -POPSession::~POPSession() -{ - MC_SAFE_RELEASE(mHostname); - MC_SAFE_RELEASE(mUsername); - MC_SAFE_RELEASE(mPassword); -} - -void POPSession::setHostname(String * hostname) -{ - MC_SAFE_REPLACE_COPY(String, mHostname, hostname); -} - -String * POPSession::hostname() -{ - return mHostname; -} - -void POPSession::setPort(unsigned int port) -{ - mPort = port; -} - -unsigned int POPSession::port() -{ - return mPort; -} - -void POPSession::setUsername(String * username) -{ - MC_SAFE_REPLACE_COPY(String, mUsername, username); -} - -String * POPSession::username() -{ - return mUsername; -} - -void POPSession::setPassword(String * password) -{ - MC_SAFE_REPLACE_COPY(String, mPassword, password); -} - -String * POPSession::password() -{ - return mPassword; -} - -void POPSession::setAuthType(AuthType authType) -{ - mAuthType = authType; -} - -AuthType POPSession::authType() -{ - return mAuthType; -} - -void POPSession::setConnectionType(ConnectionType connectionType) -{ - mConnectionType = connectionType; -} - -ConnectionType POPSession::connectionType() -{ - return mConnectionType; -} - -void POPSession::setTimeout(time_t timeout) -{ - mTimeout = timeout; -} - -time_t POPSession::timeout() -{ - return mTimeout; -} - -void POPSession::setCheckCertificateEnabled(bool enabled) -{ - mCheckCertificateEnabled = enabled; -} - -bool POPSession::isCheckCertificateEnabled() -{ - return mCheckCertificateEnabled; -} - -bool POPSession::checkCertificate() -{ - if (!isCheckCertificateEnabled()) - return true; - return mailcore::checkCertificate(mPop->pop3_stream, hostname()); -} - -void POPSession::bodyProgress(unsigned int current, unsigned int maximum) -{ - if (mProgressCallback != NULL) { - mProgressCallback->bodyProgress(this, current, maximum); - } -} - -void POPSession::body_progress(size_t current, size_t maximum, void * context) -{ - POPSession * session; - - session = (POPSession *) context; - session->bodyProgress((unsigned int) current, (unsigned int) maximum); -} - -static void logger(mailpop3 * pop3, int log_type, const char * buffer, size_t size, void * context) -{ - POPSession * session = (POPSession *) context; - - if (session->connectionLogger() == NULL) - return; - - ConnectionLogType type = getConnectionType(log_type); - bool isBuffer = isBufferFromLogType(log_type); - - if (isBuffer) { - Data * data = Data::dataWithBytes(buffer, (unsigned int) size); - session->connectionLogger()->log(session, type, data); - } - else { - session->connectionLogger()->log(session, type, NULL); - } -} - -void POPSession::setup() -{ - mPop = mailpop3_new(0, NULL); - mailpop3_set_progress_callback(mPop, POPSession::body_progress, this); - mailpop3_set_logger(mPop, logger, this); -} - -void POPSession::unsetup() -{ - if (mPop != NULL) { - if (mPop->pop3_stream != NULL) { - mailstream_close(mPop->pop3_stream); - mPop->pop3_stream = NULL; - } - mailpop3_free(mPop); - mPop = NULL; - } -} - -void POPSession::connectIfNeeded(ErrorCode * pError) -{ - if (mState == STATE_DISCONNECTED) { - connect(pError); - } - else { - * pError = ErrorNone; - } -} - -void POPSession::connect(ErrorCode * pError) -{ - int r; - - setup(); - - switch (mConnectionType) { - case ConnectionTypeStartTLS: - MCLog("connect %s %u", MCUTF8(hostname()), (unsigned int) port()); - r = mailpop3_socket_connect(mPop, MCUTF8(hostname()), port()); - if (r != MAILPOP3_NO_ERROR) { - * pError = ErrorConnection; - return; - } - - MCLog("start TLS"); - r = mailpop3_socket_starttls(mPop); - if (r != MAILPOP3_NO_ERROR) { - * pError = ErrorStartTLSNotAvailable; - return; - } - MCLog("done"); - if (!checkCertificate()) { - * pError = ErrorCertificate; - return; - } - break; - - case ConnectionTypeTLS: - MCLog("connect %s %u", MCUTF8(hostname()), (unsigned int) port()); - r = mailpop3_ssl_connect(mPop, MCUTF8(hostname()), port()); - if (r != MAILPOP3_NO_ERROR) { - * pError = ErrorConnection; - return; - } - if (!checkCertificate()) { - * pError = ErrorCertificate; - return; - } - break; - - default: - r = mailpop3_socket_connect(mPop, MCUTF8(hostname()), port()); - if (r != MAILPOP3_NO_ERROR) { - * pError = ErrorConnection; - return; - } - break; - } - - mailstream_low * low; - String * identifierString; - char * identifier; - - low = mailstream_get_low(mPop->pop3_stream); - if (mUsername != NULL) { - identifierString = String::stringWithUTF8Format("%s@%s:%u", MCUTF8(mUsername), MCUTF8(mHostname), mPort); - } - else { - identifierString = String::stringWithUTF8Format("%s:%u", MCUTF8(mUsername), mPort); - } - identifier = strdup(identifierString->UTF8Characters()); - mailstream_low_set_identifier(low, identifier); - mState = STATE_CONNECTED; - * pError = ErrorNone; -} - -void POPSession::disconnect() -{ - if (mPop == NULL) - return; - - mailpop3_quit(mPop); - mState = STATE_DISCONNECTED; - unsetup(); -} - -void POPSession::loginIfNeeded(ErrorCode * pError) -{ - connectIfNeeded(pError); - if (* pError != ErrorNone) - return; - - if (mState == STATE_CONNECTED) { - login(pError); - } - else { - * pError = ErrorNone; - } -} - -void POPSession::login(ErrorCode * pError) -{ - int r; - const char * utf8username; - const char * utf8password; - - utf8username = MCUTF8(username()); - utf8password = MCUTF8(password()); - if (utf8username == NULL) { - utf8username = ""; - } - if (utf8password == NULL) { - utf8password = ""; - } - - switch (authType()) { - case 0: - default: - r = mailpop3_user(mPop, utf8username); - if (r == MAILPOP3_ERROR_STREAM) { - * pError = ErrorConnection; - return; - } - else if (r != MAILPOP3_NO_ERROR) { - * pError = ErrorAuthentication; - return; - } - - r = mailpop3_pass(mPop, utf8password); - break; - - case AuthTypeSASLCRAMMD5: - r = mailpop3_auth(mPop, "CRAM-MD5", - MCUTF8(hostname()), - NULL, - NULL, - utf8username, utf8username, - utf8password, NULL); - break; - - case AuthTypeSASLPlain: - r = mailpop3_auth(mPop, "PLAIN", - MCUTF8(hostname()), - NULL, - NULL, - utf8username, utf8username, - utf8password, NULL); - break; - - case AuthTypeSASLGSSAPI: - // needs to be tested - r = mailpop3_auth(mPop, "GSSAPI", - MCUTF8(hostname()), - NULL, - NULL, - utf8username, utf8username, - utf8password, NULL /* realm */); - break; - - case AuthTypeSASLDIGESTMD5: - r = mailpop3_auth(mPop, "DIGEST-MD5", - MCUTF8(hostname()), - NULL, - NULL, - utf8username, utf8username, - utf8password, NULL); - break; - - case AuthTypeSASLLogin: - r = mailpop3_auth(mPop, "LOGIN", - MCUTF8(hostname()), - NULL, - NULL, - utf8username, utf8username, - utf8password, NULL); - break; - - case AuthTypeSASLSRP: - r = mailpop3_auth(mPop, "SRP", - MCUTF8(hostname()), - NULL, - NULL, - utf8username, utf8username, - utf8password, NULL); - break; - - case AuthTypeSASLNTLM: - r = mailpop3_auth(mPop, "NTLM", - MCUTF8(hostname()), - NULL, - NULL, - utf8username, utf8username, - utf8password, NULL /* realm */); - break; - - case AuthTypeSASLKerberosV4: - r = mailpop3_auth(mPop, "KERBEROS_V4", - MCUTF8(hostname()), - NULL, - NULL, - utf8username, utf8username, - utf8password, NULL /* realm */); - break; - } - if (r == MAILPOP3_ERROR_STREAM) { - * pError = ErrorConnection; - return; - } - else if (r != MAILPOP3_NO_ERROR) { - * pError = ErrorAuthentication; - return; - } - - mState = STATE_LOGGEDIN; - * pError = ErrorNone; -} - -Array * POPSession::fetchMessages(ErrorCode * pError) -{ - int r; - carray * msg_list; - - loginIfNeeded(pError); - if (* pError != ErrorNone) { - return NULL; - } - - r = mailpop3_list(mPop, &msg_list); - if (r == MAILPOP3_ERROR_STREAM) { - * pError = ErrorConnection; - return NULL; - } - else if (r != MAILPOP3_NO_ERROR) { - * pError = ErrorFetchMessageList; - return NULL; - } - - Array * result = Array::array(); - for(unsigned int i = 0 ; i < carray_count(msg_list) ; i ++) { - struct mailpop3_msg_info * msg_info; - String * uid; - - msg_info = (struct mailpop3_msg_info *) carray_get(msg_list, i); - if (msg_info->msg_uidl == NULL) - continue; - - uid = String::stringWithUTF8Characters(msg_info->msg_uidl); - - POPMessageInfo * info = new POPMessageInfo(); - info->setUid(uid); - info->setSize(msg_info->msg_size); - info->setIndex(msg_info->msg_index); - result->addObject(info); - info->release(); - } - - * pError = ErrorNone; - mState = STATE_LISTED; - - return result; -} - -void POPSession::listIfNeeded(ErrorCode * pError) -{ - if (mState == STATE_LISTED) { - * pError = ErrorNone; - return; - } - - fetchMessages(pError); -} - -MessageHeader * POPSession::fetchHeader(unsigned int index, ErrorCode * pError) -{ - int r; - char * content; - size_t content_len; - - listIfNeeded(pError); - if (* pError != ErrorNone) { - return NULL; - } - - r = mailpop3_top(mPop, index, 0, &content, &content_len); - if (r == MAILPOP3_ERROR_STREAM) { - * pError = ErrorConnection; - return NULL; - } - else if (r != MAILPOP3_NO_ERROR) { - * pError = ErrorFetch; - return NULL; - } - - Data * data; - data = new Data(content, (unsigned int) content_len); - MessageHeader * result = new MessageHeader(); - result->importHeadersData(data); - result->autorelease(); - data->release(); - - mailpop3_top_free(content); - * pError = ErrorNone; - - return result; -} - -MessageHeader * POPSession::fetchHeader(POPMessageInfo * msg, ErrorCode * pError) -{ - return fetchHeader(msg->index(), pError); -} - -Data * POPSession::fetchMessage(unsigned int index, POPProgressCallback * callback, ErrorCode * pError) -{ - int r; - char * content; - size_t content_len; - - listIfNeeded(pError); - if (* pError != ErrorNone) { - return NULL; - } - - mProgressCallback = callback; - - r = mailpop3_retr(mPop, index, &content, &content_len); - mProgressCallback = NULL; - if (r == MAILPOP3_ERROR_STREAM) { - * pError = ErrorConnection; - return NULL; - } - else if (r != MAILPOP3_NO_ERROR) { - * pError = ErrorFetch; - return NULL; - } - - Data * result; - result = Data::dataWithBytes(content, (unsigned int) content_len); - mailpop3_retr_free(content); - * pError = ErrorNone; - - return result; -} - -Data * POPSession::fetchMessage(POPMessageInfo * msg, POPProgressCallback * callback, ErrorCode * pError) -{ - return fetchMessage(msg->index(), callback, pError); -} - -void POPSession::deleteMessage(unsigned int index, ErrorCode * pError) -{ - int r; - - listIfNeeded(pError); - if (* pError != ErrorNone) { - return; - } - - r = mailpop3_dele(mPop, index); - if (r == MAILPOP3_ERROR_STREAM) { - * pError = ErrorConnection; - return; - } - else if (r != MAILPOP3_NO_ERROR) { - * pError = ErrorDeleteMessage; - return; - } - - * pError = ErrorNone; -} - -void POPSession::deleteMessage(POPMessageInfo * msg, ErrorCode * pError) -{ - deleteMessage(msg->index(), pError); -} - -void POPSession::checkAccount(ErrorCode * pError) -{ - loginIfNeeded(pError); -} - -void POPSession::noop(ErrorCode * pError) -{ - int r; - - if (mPop == NULL) - return; - - MCLog("connect"); - loginIfNeeded(pError); - if (* pError != ErrorNone) { - return; - } - if (mPop->pop3_stream != NULL) { - r = mailpop3_noop(mPop); - if ((r == MAILPOP3_ERROR_STREAM) || (r == MAILPOP3_ERROR_BAD_STATE)) { - * pError = ErrorConnection; - } - } -} - -void POPSession::setConnectionLogger(ConnectionLogger * logger) -{ - mConnectionLogger = logger; -} - -ConnectionLogger * POPSession::connectionLogger() -{ - return mConnectionLogger; -} diff --git a/src/core/pop/MCPOPSession.cpp b/src/core/pop/MCPOPSession.cpp new file mode 100644 index 00000000..8415a081 --- /dev/null +++ b/src/core/pop/MCPOPSession.cpp @@ -0,0 +1,602 @@ +#include "MCWin32.h" // should be included first. + +#include "MCPOPSession.h" + +#include +#include + +#include "MCPOPMessageInfo.h" +#include "MCPOPProgressCallback.h" +#include "MCMessageHeader.h" +#include "MCConnectionLoggerUtils.h" +#include "MCCertificateUtils.h" + +using namespace mailcore; + +enum { + STATE_DISCONNECTED, + STATE_CONNECTED, + STATE_LOGGEDIN, + STATE_LISTED, +}; + +void POPSession::init() +{ + mHostname = NULL; + mPort = 0; + mUsername = NULL; + mPassword = NULL; + mAuthType = AuthTypeSASLNone; + mConnectionType = ConnectionTypeClear; + mCheckCertificateEnabled = true; + mTimeout = 30; + + mPop = NULL; + mCapabilities = POPCapabilityNone; + mProgressCallback = NULL; + mState = STATE_DISCONNECTED; + mConnectionLogger = NULL; +} + +POPSession::POPSession() +{ + init(); +} + +POPSession::~POPSession() +{ + MC_SAFE_RELEASE(mHostname); + MC_SAFE_RELEASE(mUsername); + MC_SAFE_RELEASE(mPassword); +} + +void POPSession::setHostname(String * hostname) +{ + MC_SAFE_REPLACE_COPY(String, mHostname, hostname); +} + +String * POPSession::hostname() +{ + return mHostname; +} + +void POPSession::setPort(unsigned int port) +{ + mPort = port; +} + +unsigned int POPSession::port() +{ + return mPort; +} + +void POPSession::setUsername(String * username) +{ + MC_SAFE_REPLACE_COPY(String, mUsername, username); +} + +String * POPSession::username() +{ + return mUsername; +} + +void POPSession::setPassword(String * password) +{ + MC_SAFE_REPLACE_COPY(String, mPassword, password); +} + +String * POPSession::password() +{ + return mPassword; +} + +void POPSession::setAuthType(AuthType authType) +{ + mAuthType = authType; +} + +AuthType POPSession::authType() +{ + return mAuthType; +} + +void POPSession::setConnectionType(ConnectionType connectionType) +{ + mConnectionType = connectionType; +} + +ConnectionType POPSession::connectionType() +{ + return mConnectionType; +} + +void POPSession::setTimeout(time_t timeout) +{ + mTimeout = timeout; +} + +time_t POPSession::timeout() +{ + return mTimeout; +} + +void POPSession::setCheckCertificateEnabled(bool enabled) +{ + mCheckCertificateEnabled = enabled; +} + +bool POPSession::isCheckCertificateEnabled() +{ + return mCheckCertificateEnabled; +} + +bool POPSession::checkCertificate() +{ + if (!isCheckCertificateEnabled()) + return true; + return mailcore::checkCertificate(mPop->pop3_stream, hostname()); +} + +void POPSession::bodyProgress(unsigned int current, unsigned int maximum) +{ + if (mProgressCallback != NULL) { + mProgressCallback->bodyProgress(this, current, maximum); + } +} + +void POPSession::body_progress(size_t current, size_t maximum, void * context) +{ + POPSession * session; + + session = (POPSession *) context; + session->bodyProgress((unsigned int) current, (unsigned int) maximum); +} + +static void logger(mailpop3 * pop3, int log_type, const char * buffer, size_t size, void * context) +{ + POPSession * session = (POPSession *) context; + + if (session->connectionLogger() == NULL) + return; + + ConnectionLogType type = getConnectionType(log_type); + bool isBuffer = isBufferFromLogType(log_type); + + if (isBuffer) { + Data * data = Data::dataWithBytes(buffer, (unsigned int) size); + session->connectionLogger()->log(session, type, data); + } + else { + session->connectionLogger()->log(session, type, NULL); + } +} + +void POPSession::setup() +{ + mPop = mailpop3_new(0, NULL); + mailpop3_set_progress_callback(mPop, POPSession::body_progress, this); + mailpop3_set_logger(mPop, logger, this); +} + +void POPSession::unsetup() +{ + if (mPop != NULL) { + if (mPop->pop3_stream != NULL) { + mailstream_close(mPop->pop3_stream); + mPop->pop3_stream = NULL; + } + mailpop3_free(mPop); + mPop = NULL; + } +} + +void POPSession::connectIfNeeded(ErrorCode * pError) +{ + if (mState == STATE_DISCONNECTED) { + connect(pError); + } + else { + * pError = ErrorNone; + } +} + +void POPSession::connect(ErrorCode * pError) +{ + int r; + + setup(); + + switch (mConnectionType) { + case ConnectionTypeStartTLS: + MCLog("connect %s %u", MCUTF8(hostname()), (unsigned int) port()); + r = mailpop3_socket_connect(mPop, MCUTF8(hostname()), port()); + if (r != MAILPOP3_NO_ERROR) { + * pError = ErrorConnection; + return; + } + + MCLog("start TLS"); + r = mailpop3_socket_starttls(mPop); + if (r != MAILPOP3_NO_ERROR) { + * pError = ErrorStartTLSNotAvailable; + return; + } + MCLog("done"); + if (!checkCertificate()) { + * pError = ErrorCertificate; + return; + } + break; + + case ConnectionTypeTLS: + MCLog("connect %s %u", MCUTF8(hostname()), (unsigned int) port()); + r = mailpop3_ssl_connect(mPop, MCUTF8(hostname()), port()); + if (r != MAILPOP3_NO_ERROR) { + * pError = ErrorConnection; + return; + } + if (!checkCertificate()) { + * pError = ErrorCertificate; + return; + } + break; + + default: + r = mailpop3_socket_connect(mPop, MCUTF8(hostname()), port()); + if (r != MAILPOP3_NO_ERROR) { + * pError = ErrorConnection; + return; + } + break; + } + + mailstream_low * low; + String * identifierString; + char * identifier; + + low = mailstream_get_low(mPop->pop3_stream); + if (mUsername != NULL) { + identifierString = String::stringWithUTF8Format("%s@%s:%u", MCUTF8(mUsername), MCUTF8(mHostname), mPort); + } + else { + identifierString = String::stringWithUTF8Format("%s:%u", MCUTF8(mUsername), mPort); + } + identifier = strdup(identifierString->UTF8Characters()); + mailstream_low_set_identifier(low, identifier); + mState = STATE_CONNECTED; + * pError = ErrorNone; +} + +void POPSession::disconnect() +{ + if (mPop == NULL) + return; + + mailpop3_quit(mPop); + mState = STATE_DISCONNECTED; + unsetup(); +} + +void POPSession::loginIfNeeded(ErrorCode * pError) +{ + connectIfNeeded(pError); + if (* pError != ErrorNone) + return; + + if (mState == STATE_CONNECTED) { + login(pError); + } + else { + * pError = ErrorNone; + } +} + +void POPSession::login(ErrorCode * pError) +{ + int r; + const char * utf8username; + const char * utf8password; + + utf8username = MCUTF8(username()); + utf8password = MCUTF8(password()); + if (utf8username == NULL) { + utf8username = ""; + } + if (utf8password == NULL) { + utf8password = ""; + } + + switch (authType()) { + case 0: + default: + r = mailpop3_user(mPop, utf8username); + if (r == MAILPOP3_ERROR_STREAM) { + * pError = ErrorConnection; + return; + } + else if (r != MAILPOP3_NO_ERROR) { + * pError = ErrorAuthentication; + return; + } + + r = mailpop3_pass(mPop, utf8password); + break; + + case AuthTypeSASLCRAMMD5: + r = mailpop3_auth(mPop, "CRAM-MD5", + MCUTF8(hostname()), + NULL, + NULL, + utf8username, utf8username, + utf8password, NULL); + break; + + case AuthTypeSASLPlain: + r = mailpop3_auth(mPop, "PLAIN", + MCUTF8(hostname()), + NULL, + NULL, + utf8username, utf8username, + utf8password, NULL); + break; + + case AuthTypeSASLGSSAPI: + // needs to be tested + r = mailpop3_auth(mPop, "GSSAPI", + MCUTF8(hostname()), + NULL, + NULL, + utf8username, utf8username, + utf8password, NULL /* realm */); + break; + + case AuthTypeSASLDIGESTMD5: + r = mailpop3_auth(mPop, "DIGEST-MD5", + MCUTF8(hostname()), + NULL, + NULL, + utf8username, utf8username, + utf8password, NULL); + break; + + case AuthTypeSASLLogin: + r = mailpop3_auth(mPop, "LOGIN", + MCUTF8(hostname()), + NULL, + NULL, + utf8username, utf8username, + utf8password, NULL); + break; + + case AuthTypeSASLSRP: + r = mailpop3_auth(mPop, "SRP", + MCUTF8(hostname()), + NULL, + NULL, + utf8username, utf8username, + utf8password, NULL); + break; + + case AuthTypeSASLNTLM: + r = mailpop3_auth(mPop, "NTLM", + MCUTF8(hostname()), + NULL, + NULL, + utf8username, utf8username, + utf8password, NULL /* realm */); + break; + + case AuthTypeSASLKerberosV4: + r = mailpop3_auth(mPop, "KERBEROS_V4", + MCUTF8(hostname()), + NULL, + NULL, + utf8username, utf8username, + utf8password, NULL /* realm */); + break; + } + if (r == MAILPOP3_ERROR_STREAM) { + * pError = ErrorConnection; + return; + } + else if (r != MAILPOP3_NO_ERROR) { + * pError = ErrorAuthentication; + return; + } + + mState = STATE_LOGGEDIN; + * pError = ErrorNone; +} + +Array * POPSession::fetchMessages(ErrorCode * pError) +{ + int r; + carray * msg_list; + + loginIfNeeded(pError); + if (* pError != ErrorNone) { + return NULL; + } + + r = mailpop3_list(mPop, &msg_list); + if (r == MAILPOP3_ERROR_STREAM) { + * pError = ErrorConnection; + return NULL; + } + else if (r != MAILPOP3_NO_ERROR) { + * pError = ErrorFetchMessageList; + return NULL; + } + + Array * result = Array::array(); + for(unsigned int i = 0 ; i < carray_count(msg_list) ; i ++) { + struct mailpop3_msg_info * msg_info; + String * uid; + + msg_info = (struct mailpop3_msg_info *) carray_get(msg_list, i); + if (msg_info->msg_uidl == NULL) + continue; + + uid = String::stringWithUTF8Characters(msg_info->msg_uidl); + + POPMessageInfo * info = new POPMessageInfo(); + info->setUid(uid); + info->setSize(msg_info->msg_size); + info->setIndex(msg_info->msg_index); + result->addObject(info); + info->release(); + } + + * pError = ErrorNone; + mState = STATE_LISTED; + + return result; +} + +void POPSession::listIfNeeded(ErrorCode * pError) +{ + if (mState == STATE_LISTED) { + * pError = ErrorNone; + return; + } + + fetchMessages(pError); +} + +MessageHeader * POPSession::fetchHeader(unsigned int index, ErrorCode * pError) +{ + int r; + char * content; + size_t content_len; + + listIfNeeded(pError); + if (* pError != ErrorNone) { + return NULL; + } + + r = mailpop3_top(mPop, index, 0, &content, &content_len); + if (r == MAILPOP3_ERROR_STREAM) { + * pError = ErrorConnection; + return NULL; + } + else if (r != MAILPOP3_NO_ERROR) { + * pError = ErrorFetch; + return NULL; + } + + Data * data; + data = new Data(content, (unsigned int) content_len); + MessageHeader * result = new MessageHeader(); + result->importHeadersData(data); + result->autorelease(); + data->release(); + + mailpop3_top_free(content); + * pError = ErrorNone; + + return result; +} + +MessageHeader * POPSession::fetchHeader(POPMessageInfo * msg, ErrorCode * pError) +{ + return fetchHeader(msg->index(), pError); +} + +Data * POPSession::fetchMessage(unsigned int index, POPProgressCallback * callback, ErrorCode * pError) +{ + int r; + char * content; + size_t content_len; + + listIfNeeded(pError); + if (* pError != ErrorNone) { + return NULL; + } + + mProgressCallback = callback; + + r = mailpop3_retr(mPop, index, &content, &content_len); + mProgressCallback = NULL; + if (r == MAILPOP3_ERROR_STREAM) { + * pError = ErrorConnection; + return NULL; + } + else if (r != MAILPOP3_NO_ERROR) { + * pError = ErrorFetch; + return NULL; + } + + Data * result; + result = Data::dataWithBytes(content, (unsigned int) content_len); + mailpop3_retr_free(content); + * pError = ErrorNone; + + return result; +} + +Data * POPSession::fetchMessage(POPMessageInfo * msg, POPProgressCallback * callback, ErrorCode * pError) +{ + return fetchMessage(msg->index(), callback, pError); +} + +void POPSession::deleteMessage(unsigned int index, ErrorCode * pError) +{ + int r; + + listIfNeeded(pError); + if (* pError != ErrorNone) { + return; + } + + r = mailpop3_dele(mPop, index); + if (r == MAILPOP3_ERROR_STREAM) { + * pError = ErrorConnection; + return; + } + else if (r != MAILPOP3_NO_ERROR) { + * pError = ErrorDeleteMessage; + return; + } + + * pError = ErrorNone; +} + +void POPSession::deleteMessage(POPMessageInfo * msg, ErrorCode * pError) +{ + deleteMessage(msg->index(), pError); +} + +void POPSession::checkAccount(ErrorCode * pError) +{ + loginIfNeeded(pError); +} + +void POPSession::noop(ErrorCode * pError) +{ + int r; + + if (mPop == NULL) + return; + + MCLog("connect"); + loginIfNeeded(pError); + if (* pError != ErrorNone) { + return; + } + if (mPop->pop3_stream != NULL) { + r = mailpop3_noop(mPop); + if ((r == MAILPOP3_ERROR_STREAM) || (r == MAILPOP3_ERROR_BAD_STATE)) { + * pError = ErrorConnection; + } + } +} + +void POPSession::setConnectionLogger(ConnectionLogger * logger) +{ + mConnectionLogger = logger; +} + +ConnectionLogger * POPSession::connectionLogger() +{ + return mConnectionLogger; +} diff --git a/src/core/provider/MCMailProvider.cc b/src/core/provider/MCMailProvider.cc deleted file mode 100644 index 8ebc44db..00000000 --- a/src/core/provider/MCMailProvider.cc +++ /dev/null @@ -1,268 +0,0 @@ -// -// MCMailProvider.cpp -// mailcore2 -// -// Created by Robert Widmann on 4/28/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCMailProvider.h" -#include "MCNetService.h" -#include "MCIterator.h" -#include "MCJSON.h" - -#include - -using namespace mailcore; - -void MailProvider::init() -{ - mIdentifier = NULL; - mImapServices = new Array(); - mSmtpServices = new Array(); - mPopServices = new Array(); - mDomainMatch = new Array(); - mDomainExclude = new Array(); - mMxMatch = new Array(); - mMailboxPaths = NULL; -} - -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(Array, mDomainExclude, other->mDomainExclude); - MC_SAFE_REPLACE_COPY(Array, mMxMatch, other->mMxMatch); - 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(mMxMatch); - MC_SAFE_RELEASE(mDomainMatch); - MC_SAFE_RELEASE(mDomainExclude); - MC_SAFE_RELEASE(mMailboxPaths); - MC_SAFE_RELEASE(mIdentifier); -} - -MailProvider * MailProvider::providerWithInfo(HashMap * info) -{ - MailProvider * provider = new MailProvider(); - provider->fillWithInfo(info); - provider->autorelease(); - return provider; -} - -void MailProvider::fillWithInfo(HashMap * info) -{ - Array * imapInfos; - Array * smtpInfos; - Array * popInfos; - HashMap * serverInfo; - - MC_SAFE_RELEASE(mDomainMatch); - if (info->objectForKey(MCSTR("domain-match")) != NULL) { - mDomainMatch = (Array *) info->objectForKey(MCSTR("domain-match"))->retain(); - } - MC_SAFE_RELEASE(mDomainExclude); - if (info->objectForKey(MCSTR("domain-exclude")) != NULL) { - mDomainExclude = (Array *) info->objectForKey(MCSTR("domain-exclude"))->retain(); - } - MC_SAFE_RELEASE(mMailboxPaths); - if (info->objectForKey(MCSTR("mailboxes")) != NULL) { - mMailboxPaths = (HashMap *) info->objectForKey(MCSTR("mailboxes"))->retain(); - } - MC_SAFE_RELEASE(mMxMatch); - if (info->objectForKey(MCSTR("mx-match")) != NULL) { - mMxMatch = (Array *) info->objectForKey(MCSTR("mx-match"))->retain(); - } - - serverInfo = (HashMap *) info->objectForKey(MCSTR("servers")); - if (serverInfo == NULL) { - MCLog("servers key missing from provider %s", MCUTF8DESC(info)); - } - MCAssert(serverInfo != NULL); - imapInfos = (Array *) serverInfo->objectForKey(MCSTR("imap")); - smtpInfos = (Array *) serverInfo->objectForKey(MCSTR("smtp")); - popInfos = (Array *) serverInfo->objectForKey(MCSTR("pop")); - - mImapServices->removeAllObjects(); - 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); - } - - mPopServices->removeAllObjects(); - 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); -} - -String * MailProvider::identifier() -{ - return mIdentifier; -} - -Array * MailProvider::imapServices() -{ - return mImapServices; -} - -Array * MailProvider::smtpServices() -{ - return mSmtpServices; -} - -Array * MailProvider::popServices() -{ - return mPopServices; -} - -bool MailProvider::matchEmail(String * email) -{ - Array * components; - String * domain; - - components = email->componentsSeparatedByString(MCSTR("@")); - if (components->count() < 2) - return false; - - domain = (String *) components->lastObject(); - - mc_foreacharray(String, exclude, mDomainExclude) { - if (matchDomain(exclude, domain)){ - return false; - } - } - - mc_foreacharray(String, match, mDomainMatch) { - if (matchDomain(match, domain)){ - return true; - } - } - - return false; -} - -bool MailProvider::matchMX(String * hostname) -{ - mc_foreacharray(String, match, mMxMatch) { - if (matchDomain(match, hostname)){ - return true; - } - } - - return false; -} - -bool MailProvider::matchDomain(String * match, String * domain) -{ - const char * cDomain; - regex_t r; - bool matched; - - cDomain = domain->UTF8Characters(); - match = String::stringWithUTF8Format("^%s$", match->UTF8Characters()); - matched = false; - - if (regcomp(&r, match->UTF8Characters(), REG_EXTENDED | REG_ICASE | REG_NOSUB) != 0){ - return matched; - } - - if (regexec(&r, cDomain, 0, NULL, 0) == 0) { - matched = true; - } - - regfree(&r); - - return matched; -} - -String * MailProvider::sentMailFolderPath() -{ - return (String *) mMailboxPaths->objectForKey(MCSTR("sentmail")); -} - -String * MailProvider::starredFolderPath() -{ - return (String *) mMailboxPaths->objectForKey(MCSTR("starred")); -} - -String * MailProvider::allMailFolderPath() -{ - return (String *) mMailboxPaths->objectForKey(MCSTR("allmail")); -} - -String * MailProvider::trashFolderPath() -{ - return (String *) mMailboxPaths->objectForKey(MCSTR("trash")); -} - -String * MailProvider::draftsFolderPath() -{ - return (String *) mMailboxPaths->objectForKey(MCSTR("drafts")); -} - -String * MailProvider::spamFolderPath() -{ - return (String *) mMailboxPaths->objectForKey(MCSTR("spam")); -} - -String * MailProvider::importantFolderPath() -{ - return (String *) mMailboxPaths->objectForKey(MCSTR("important")); -} - -bool MailProvider::isMainFolder(String * folderPath, String * prefix) -{ - mc_foreachhashmapValue(String, path, mMailboxPaths) { - String * fullPath; - - if (prefix != NULL) { - fullPath = prefix->stringByAppendingString((String *) path); - } - else { - fullPath = path; - } - - if (fullPath->isEqual(folderPath)) - return true; - } - - return false; -} - -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.cpp b/src/core/provider/MCMailProvider.cpp new file mode 100644 index 00000000..8ebc44db --- /dev/null +++ b/src/core/provider/MCMailProvider.cpp @@ -0,0 +1,268 @@ +// +// MCMailProvider.cpp +// mailcore2 +// +// Created by Robert Widmann on 4/28/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCMailProvider.h" +#include "MCNetService.h" +#include "MCIterator.h" +#include "MCJSON.h" + +#include + +using namespace mailcore; + +void MailProvider::init() +{ + mIdentifier = NULL; + mImapServices = new Array(); + mSmtpServices = new Array(); + mPopServices = new Array(); + mDomainMatch = new Array(); + mDomainExclude = new Array(); + mMxMatch = new Array(); + mMailboxPaths = NULL; +} + +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(Array, mDomainExclude, other->mDomainExclude); + MC_SAFE_REPLACE_COPY(Array, mMxMatch, other->mMxMatch); + 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(mMxMatch); + MC_SAFE_RELEASE(mDomainMatch); + MC_SAFE_RELEASE(mDomainExclude); + MC_SAFE_RELEASE(mMailboxPaths); + MC_SAFE_RELEASE(mIdentifier); +} + +MailProvider * MailProvider::providerWithInfo(HashMap * info) +{ + MailProvider * provider = new MailProvider(); + provider->fillWithInfo(info); + provider->autorelease(); + return provider; +} + +void MailProvider::fillWithInfo(HashMap * info) +{ + Array * imapInfos; + Array * smtpInfos; + Array * popInfos; + HashMap * serverInfo; + + MC_SAFE_RELEASE(mDomainMatch); + if (info->objectForKey(MCSTR("domain-match")) != NULL) { + mDomainMatch = (Array *) info->objectForKey(MCSTR("domain-match"))->retain(); + } + MC_SAFE_RELEASE(mDomainExclude); + if (info->objectForKey(MCSTR("domain-exclude")) != NULL) { + mDomainExclude = (Array *) info->objectForKey(MCSTR("domain-exclude"))->retain(); + } + MC_SAFE_RELEASE(mMailboxPaths); + if (info->objectForKey(MCSTR("mailboxes")) != NULL) { + mMailboxPaths = (HashMap *) info->objectForKey(MCSTR("mailboxes"))->retain(); + } + MC_SAFE_RELEASE(mMxMatch); + if (info->objectForKey(MCSTR("mx-match")) != NULL) { + mMxMatch = (Array *) info->objectForKey(MCSTR("mx-match"))->retain(); + } + + serverInfo = (HashMap *) info->objectForKey(MCSTR("servers")); + if (serverInfo == NULL) { + MCLog("servers key missing from provider %s", MCUTF8DESC(info)); + } + MCAssert(serverInfo != NULL); + imapInfos = (Array *) serverInfo->objectForKey(MCSTR("imap")); + smtpInfos = (Array *) serverInfo->objectForKey(MCSTR("smtp")); + popInfos = (Array *) serverInfo->objectForKey(MCSTR("pop")); + + mImapServices->removeAllObjects(); + 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); + } + + mPopServices->removeAllObjects(); + 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); +} + +String * MailProvider::identifier() +{ + return mIdentifier; +} + +Array * MailProvider::imapServices() +{ + return mImapServices; +} + +Array * MailProvider::smtpServices() +{ + return mSmtpServices; +} + +Array * MailProvider::popServices() +{ + return mPopServices; +} + +bool MailProvider::matchEmail(String * email) +{ + Array * components; + String * domain; + + components = email->componentsSeparatedByString(MCSTR("@")); + if (components->count() < 2) + return false; + + domain = (String *) components->lastObject(); + + mc_foreacharray(String, exclude, mDomainExclude) { + if (matchDomain(exclude, domain)){ + return false; + } + } + + mc_foreacharray(String, match, mDomainMatch) { + if (matchDomain(match, domain)){ + return true; + } + } + + return false; +} + +bool MailProvider::matchMX(String * hostname) +{ + mc_foreacharray(String, match, mMxMatch) { + if (matchDomain(match, hostname)){ + return true; + } + } + + return false; +} + +bool MailProvider::matchDomain(String * match, String * domain) +{ + const char * cDomain; + regex_t r; + bool matched; + + cDomain = domain->UTF8Characters(); + match = String::stringWithUTF8Format("^%s$", match->UTF8Characters()); + matched = false; + + if (regcomp(&r, match->UTF8Characters(), REG_EXTENDED | REG_ICASE | REG_NOSUB) != 0){ + return matched; + } + + if (regexec(&r, cDomain, 0, NULL, 0) == 0) { + matched = true; + } + + regfree(&r); + + return matched; +} + +String * MailProvider::sentMailFolderPath() +{ + return (String *) mMailboxPaths->objectForKey(MCSTR("sentmail")); +} + +String * MailProvider::starredFolderPath() +{ + return (String *) mMailboxPaths->objectForKey(MCSTR("starred")); +} + +String * MailProvider::allMailFolderPath() +{ + return (String *) mMailboxPaths->objectForKey(MCSTR("allmail")); +} + +String * MailProvider::trashFolderPath() +{ + return (String *) mMailboxPaths->objectForKey(MCSTR("trash")); +} + +String * MailProvider::draftsFolderPath() +{ + return (String *) mMailboxPaths->objectForKey(MCSTR("drafts")); +} + +String * MailProvider::spamFolderPath() +{ + return (String *) mMailboxPaths->objectForKey(MCSTR("spam")); +} + +String * MailProvider::importantFolderPath() +{ + return (String *) mMailboxPaths->objectForKey(MCSTR("important")); +} + +bool MailProvider::isMainFolder(String * folderPath, String * prefix) +{ + mc_foreachhashmapValue(String, path, mMailboxPaths) { + String * fullPath; + + if (prefix != NULL) { + fullPath = prefix->stringByAppendingString((String *) path); + } + else { + fullPath = path; + } + + if (fullPath->isEqual(folderPath)) + return true; + } + + return false; +} + +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/MCMailProvidersManager.cc b/src/core/provider/MCMailProvidersManager.cc deleted file mode 100644 index 0d7938e4..00000000 --- a/src/core/provider/MCMailProvidersManager.cc +++ /dev/null @@ -1,71 +0,0 @@ -// -// MCMailProvidersManager.cpp -// mailcore2 -// -// Created by Robert Widmann on 4/28/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCMailProvidersManager.h" -#include "MCMailProvider.h" -#include "MCJSON.h" - -using namespace mailcore; - -void MailProvidersManager::init() -{ - mProviders = new HashMap(); -} - -MailProvidersManager::MailProvidersManager() { - init(); -} - -MailProvidersManager * MailProvidersManager::sharedManager() -{ - static MailProvidersManager * instance = new MailProvidersManager(); - return instance; -} - - -MailProvider * MailProvidersManager::providerForEmail(String * email) -{ - mc_foreachhashmapValue(MailProvider, provider, mProviders) { - if (provider->matchEmail(email)) - return provider; - } - - return NULL; -} - -MailProvider * MailProvidersManager::providerForMX(String * hostname) -{ - mc_foreachhashmapValue(MailProvider, provider, mProviders) { - if (provider->matchMX(hostname)) - return provider; - } - - return NULL; -} - -MailProvider * MailProvidersManager::providerForIdentifier(String * identifier) -{ - return (MailProvider *) mProviders->objectForKey(identifier); -} - -void MailProvidersManager::registerProviders(HashMap * providers) -{ - mc_foreachhashmapKeyAndValue(String, identifier, HashMap, providerInfo, providers) { - MailProvider * provider = MailProvider::providerWithInfo(providerInfo); - provider->setIdentifier(identifier); - mProviders->setObjectForKey(identifier, provider); - } -} - -void MailProvidersManager::registerProvidersWithFilename(String * filename) -{ - HashMap * providersInfos; - - providersInfos = (HashMap *) JSON::objectFromJSONData(Data::dataWithContentsOfFile(filename)); - registerProviders(providersInfos); -} diff --git a/src/core/provider/MCMailProvidersManager.cpp b/src/core/provider/MCMailProvidersManager.cpp new file mode 100644 index 00000000..0d7938e4 --- /dev/null +++ b/src/core/provider/MCMailProvidersManager.cpp @@ -0,0 +1,71 @@ +// +// MCMailProvidersManager.cpp +// mailcore2 +// +// Created by Robert Widmann on 4/28/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCMailProvidersManager.h" +#include "MCMailProvider.h" +#include "MCJSON.h" + +using namespace mailcore; + +void MailProvidersManager::init() +{ + mProviders = new HashMap(); +} + +MailProvidersManager::MailProvidersManager() { + init(); +} + +MailProvidersManager * MailProvidersManager::sharedManager() +{ + static MailProvidersManager * instance = new MailProvidersManager(); + return instance; +} + + +MailProvider * MailProvidersManager::providerForEmail(String * email) +{ + mc_foreachhashmapValue(MailProvider, provider, mProviders) { + if (provider->matchEmail(email)) + return provider; + } + + return NULL; +} + +MailProvider * MailProvidersManager::providerForMX(String * hostname) +{ + mc_foreachhashmapValue(MailProvider, provider, mProviders) { + if (provider->matchMX(hostname)) + return provider; + } + + return NULL; +} + +MailProvider * MailProvidersManager::providerForIdentifier(String * identifier) +{ + return (MailProvider *) mProviders->objectForKey(identifier); +} + +void MailProvidersManager::registerProviders(HashMap * providers) +{ + mc_foreachhashmapKeyAndValue(String, identifier, HashMap, providerInfo, providers) { + MailProvider * provider = MailProvider::providerWithInfo(providerInfo); + provider->setIdentifier(identifier); + mProviders->setObjectForKey(identifier, provider); + } +} + +void MailProvidersManager::registerProvidersWithFilename(String * filename) +{ + HashMap * providersInfos; + + providersInfos = (HashMap *) JSON::objectFromJSONData(Data::dataWithContentsOfFile(filename)); + registerProviders(providersInfos); +} diff --git a/src/core/provider/MCNetService.cc b/src/core/provider/MCNetService.cc deleted file mode 100644 index 77a21ce2..00000000 --- a/src/core/provider/MCNetService.cc +++ /dev/null @@ -1,146 +0,0 @@ -// -// MCNetService.cpp -// mailcore2 -// -// Created by Robert Widmann on 4/28/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCNetService.h" - -using namespace mailcore; - -void NetService::init() -{ - mHostname = NULL; - mPort = 0; - mConnectionType = ConnectionTypeClear; -} - -NetService::NetService() -{ - 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); -} - -NetService * NetService::serviceWithInfo(HashMap * info) -{ - NetService * service = new NetService(); - service->fillWithInfo(info); - service->autorelease(); - return service; -} - -void NetService::fillWithInfo(HashMap * info) -{ - bool ssl = false; - bool starttls = false; - - setHostname((String *) info->objectForKey(MCSTR("hostname"))); - if (info->objectForKey(MCSTR("port")) != NULL) { - setPort(((Value *) info->objectForKey(MCSTR("port")))->intValue()); - } - if (info->objectForKey(MCSTR("ssl")) != NULL) { - ssl = ((Value *) info->objectForKey(MCSTR("ssl")))->boolValue(); - } - if (info->objectForKey(MCSTR("starttls")) != NULL) { - starttls = ((Value *) info->objectForKey(MCSTR("starttls")))->boolValue(); - } - if (ssl) { - mConnectionType = ConnectionTypeTLS; - } - else if (starttls) { - mConnectionType = ConnectionTypeStartTLS; - } - else { - mConnectionType = ConnectionTypeClear; - } -} - -void NetService::setHostname(String *hostname) -{ - MC_SAFE_REPLACE_COPY(String, mHostname, hostname); -} - -String * NetService::hostname() -{ - return mHostname; -} - -void NetService::setPort(unsigned int port) -{ - mPort = port; -} - -unsigned int NetService::port() -{ - return mPort; -} - -void NetService::setConnectionType(ConnectionType connectionType) -{ - mConnectionType = connectionType; -} - -ConnectionType NetService::connectionType() -{ - return mConnectionType; -} - -String * NetService::normalizedHostnameWithEmail(String * email) -{ - Array *components = email->componentsSeparatedByString(MCSTR("@")); - String *hostname = (String *) mHostname->copy()->autorelease(); - if (components->count() != 0) { - hostname->replaceOccurrencesOfString(MCSTR("{domain}"), (String *) components->lastObject()); - return hostname; - } - return mHostname; -} - -HashMap * NetService::info() -{ - HashMap * result; - - result = new HashMap(); - if (mHostname != NULL) { - result->setObjectForKey(MCSTR("hostname"), mHostname); - } - if (mPort != 0) { - result->setObjectForKey(MCSTR("port"), Value::valueWithIntValue(mPort)); - } - switch (mConnectionType) { - case ConnectionTypeTLS: - result->setObjectForKey(MCSTR("ssl"), Value::valueWithBoolValue(true)); - break; - case ConnectionTypeStartTLS: - result->setObjectForKey(MCSTR("starttls"), Value::valueWithBoolValue(true)); - break; - default: - break; - } - - 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.cpp b/src/core/provider/MCNetService.cpp new file mode 100644 index 00000000..77a21ce2 --- /dev/null +++ b/src/core/provider/MCNetService.cpp @@ -0,0 +1,146 @@ +// +// MCNetService.cpp +// mailcore2 +// +// Created by Robert Widmann on 4/28/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCNetService.h" + +using namespace mailcore; + +void NetService::init() +{ + mHostname = NULL; + mPort = 0; + mConnectionType = ConnectionTypeClear; +} + +NetService::NetService() +{ + 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); +} + +NetService * NetService::serviceWithInfo(HashMap * info) +{ + NetService * service = new NetService(); + service->fillWithInfo(info); + service->autorelease(); + return service; +} + +void NetService::fillWithInfo(HashMap * info) +{ + bool ssl = false; + bool starttls = false; + + setHostname((String *) info->objectForKey(MCSTR("hostname"))); + if (info->objectForKey(MCSTR("port")) != NULL) { + setPort(((Value *) info->objectForKey(MCSTR("port")))->intValue()); + } + if (info->objectForKey(MCSTR("ssl")) != NULL) { + ssl = ((Value *) info->objectForKey(MCSTR("ssl")))->boolValue(); + } + if (info->objectForKey(MCSTR("starttls")) != NULL) { + starttls = ((Value *) info->objectForKey(MCSTR("starttls")))->boolValue(); + } + if (ssl) { + mConnectionType = ConnectionTypeTLS; + } + else if (starttls) { + mConnectionType = ConnectionTypeStartTLS; + } + else { + mConnectionType = ConnectionTypeClear; + } +} + +void NetService::setHostname(String *hostname) +{ + MC_SAFE_REPLACE_COPY(String, mHostname, hostname); +} + +String * NetService::hostname() +{ + return mHostname; +} + +void NetService::setPort(unsigned int port) +{ + mPort = port; +} + +unsigned int NetService::port() +{ + return mPort; +} + +void NetService::setConnectionType(ConnectionType connectionType) +{ + mConnectionType = connectionType; +} + +ConnectionType NetService::connectionType() +{ + return mConnectionType; +} + +String * NetService::normalizedHostnameWithEmail(String * email) +{ + Array *components = email->componentsSeparatedByString(MCSTR("@")); + String *hostname = (String *) mHostname->copy()->autorelease(); + if (components->count() != 0) { + hostname->replaceOccurrencesOfString(MCSTR("{domain}"), (String *) components->lastObject()); + return hostname; + } + return mHostname; +} + +HashMap * NetService::info() +{ + HashMap * result; + + result = new HashMap(); + if (mHostname != NULL) { + result->setObjectForKey(MCSTR("hostname"), mHostname); + } + if (mPort != 0) { + result->setObjectForKey(MCSTR("port"), Value::valueWithIntValue(mPort)); + } + switch (mConnectionType) { + case ConnectionTypeTLS: + result->setObjectForKey(MCSTR("ssl"), Value::valueWithBoolValue(true)); + break; + case ConnectionTypeStartTLS: + result->setObjectForKey(MCSTR("starttls"), Value::valueWithBoolValue(true)); + break; + default: + break; + } + + 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/renderer/MCAddressDisplay.cc b/src/core/renderer/MCAddressDisplay.cc deleted file mode 100644 index d8de47fc..00000000 --- a/src/core/renderer/MCAddressDisplay.cc +++ /dev/null @@ -1,90 +0,0 @@ -// -// MCAddressDisplay.cpp -// testUI -// -// Created by DINH Viêt Hoà on 1/27/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCAddressDisplay.h" - -using namespace mailcore; - -String * AddressDisplay::displayStringForAddress(Address * address) -{ - return address->nonEncodedRFC822String(); -} - -String * AddressDisplay::shortDisplayStringForAddress(Address * address) -{ - if ((address->displayName() != NULL) && (address->displayName()->length() > 0)) { - return address->displayName(); - } - else if (address->mailbox()) { - return address->mailbox(); - } - else { - return MCSTR("invalid"); - } -} - -String * AddressDisplay::veryShortDisplayStringForAddress(Address * address) -{ - if ((address->displayName() != NULL) && (address->displayName()->length() > 0)) { - Array * components; - String * senderName; - - senderName = address->displayName(); - senderName = (String *) senderName->copy()->autorelease(); - - senderName->replaceOccurrencesOfString(MCSTR(","), MCSTR(" ")); - senderName->replaceOccurrencesOfString(MCSTR("'"), MCSTR(" ")); - senderName->replaceOccurrencesOfString(MCSTR("\""), MCSTR(" ")); - components = senderName->componentsSeparatedByString(MCSTR(" ")); - if (components->count() == 0) { - return MCLOCALIZEDSTRING(MCSTR("invalid")); - } - return (String *) components->objectAtIndex(0); - } - else if (address->mailbox()) { - Array * components = address->mailbox()->componentsSeparatedByString(MCSTR("@")); - if (components->count() == 0) { - return MCSTR(""); - } - return (String *) components->objectAtIndex(0); - } - else { - return MCLOCALIZEDSTRING(MCSTR("invalid")); - } -} - -String * AddressDisplay::displayStringForAddresses(Array * addresses) -{ - return Address::nonEncodedRFC822StringForAddresses(addresses); -} - -String * AddressDisplay::shortDisplayStringForAddresses(Array * addresses) -{ - String * result = String::string(); - for(unsigned int i = 0 ; i < addresses->count() ; i ++) { - Address * address = (Address *) addresses->objectAtIndex(i); - if (i != 0) { - result->appendString(MCSTR(", ")); - } - result->appendString(shortDisplayStringForAddress(address)); - } - return result; -} - -String * AddressDisplay::veryShortDisplayStringForAddresses(Array * addresses) -{ - String * result = String::string(); - for(unsigned int i = 0 ; i < addresses->count() ; i ++) { - Address * address = (Address *) addresses->objectAtIndex(i); - if (i != 0) { - result->appendString(MCSTR(", ")); - } - result->appendString(veryShortDisplayStringForAddress(address)); - } - return result; -} diff --git a/src/core/renderer/MCAddressDisplay.cpp b/src/core/renderer/MCAddressDisplay.cpp new file mode 100644 index 00000000..d8de47fc --- /dev/null +++ b/src/core/renderer/MCAddressDisplay.cpp @@ -0,0 +1,90 @@ +// +// MCAddressDisplay.cpp +// testUI +// +// Created by DINH Viêt Hoà on 1/27/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCAddressDisplay.h" + +using namespace mailcore; + +String * AddressDisplay::displayStringForAddress(Address * address) +{ + return address->nonEncodedRFC822String(); +} + +String * AddressDisplay::shortDisplayStringForAddress(Address * address) +{ + if ((address->displayName() != NULL) && (address->displayName()->length() > 0)) { + return address->displayName(); + } + else if (address->mailbox()) { + return address->mailbox(); + } + else { + return MCSTR("invalid"); + } +} + +String * AddressDisplay::veryShortDisplayStringForAddress(Address * address) +{ + if ((address->displayName() != NULL) && (address->displayName()->length() > 0)) { + Array * components; + String * senderName; + + senderName = address->displayName(); + senderName = (String *) senderName->copy()->autorelease(); + + senderName->replaceOccurrencesOfString(MCSTR(","), MCSTR(" ")); + senderName->replaceOccurrencesOfString(MCSTR("'"), MCSTR(" ")); + senderName->replaceOccurrencesOfString(MCSTR("\""), MCSTR(" ")); + components = senderName->componentsSeparatedByString(MCSTR(" ")); + if (components->count() == 0) { + return MCLOCALIZEDSTRING(MCSTR("invalid")); + } + return (String *) components->objectAtIndex(0); + } + else if (address->mailbox()) { + Array * components = address->mailbox()->componentsSeparatedByString(MCSTR("@")); + if (components->count() == 0) { + return MCSTR(""); + } + return (String *) components->objectAtIndex(0); + } + else { + return MCLOCALIZEDSTRING(MCSTR("invalid")); + } +} + +String * AddressDisplay::displayStringForAddresses(Array * addresses) +{ + return Address::nonEncodedRFC822StringForAddresses(addresses); +} + +String * AddressDisplay::shortDisplayStringForAddresses(Array * addresses) +{ + String * result = String::string(); + for(unsigned int i = 0 ; i < addresses->count() ; i ++) { + Address * address = (Address *) addresses->objectAtIndex(i); + if (i != 0) { + result->appendString(MCSTR(", ")); + } + result->appendString(shortDisplayStringForAddress(address)); + } + return result; +} + +String * AddressDisplay::veryShortDisplayStringForAddresses(Array * addresses) +{ + String * result = String::string(); + for(unsigned int i = 0 ; i < addresses->count() ; i ++) { + Address * address = (Address *) addresses->objectAtIndex(i); + if (i != 0) { + result->appendString(MCSTR(", ")); + } + result->appendString(veryShortDisplayStringForAddress(address)); + } + return result; +} diff --git a/src/core/renderer/MCDateFormatter.cc b/src/core/renderer/MCDateFormatter.cc deleted file mode 100644 index 4938d5ec..00000000 --- a/src/core/renderer/MCDateFormatter.cc +++ /dev/null @@ -1,262 +0,0 @@ -// -// MCDateFormatter.cpp -// testUI -// -// Created by DINH Viêt Hoà on 1/28/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCDateFormatter.h" -#include - -#if defined(__APPLE__) -#define USE_COREFOUNDATION 1 -#else -#include -#endif - -#if USE_COREFOUNDATION -#include -#endif - -using namespace mailcore; - -DateFormatter::DateFormatter() -{ - mDateFormatter = NULL; - mDateStyle = DateFormatStyleMedium; - mTimeStyle = DateFormatStyleMedium; - mDateFormat = NULL; - mTimezone = NULL; - mLocale = NULL; - mAppleDateFormatter = NULL; -} - -DateFormatter::~DateFormatter() -{ -#if USE_COREFOUNDATION - if (mAppleDateFormatter != NULL) { - CFRelease(mAppleDateFormatter); - } -#else - if (mDateFormatter != NULL) { - udat_close(mDateFormatter); - } -#endif - MC_SAFE_RELEASE(mDateFormat); - MC_SAFE_RELEASE(mTimezone); - MC_SAFE_RELEASE(mLocale); -} - -DateFormatter * DateFormatter::dateFormatter() -{ - DateFormatter * result = new DateFormatter(); - result->autorelease(); - return result; -} - - -void DateFormatter::setDateStyle(DateFormatStyle style) -{ - mDateStyle = style; -} - -DateFormatStyle DateFormatter::dateStyle() -{ - return mDateStyle; -} - -void DateFormatter::setTimeStyle(DateFormatStyle style) -{ - mTimeStyle = style; -} - -DateFormatStyle DateFormatter::timeStyle() -{ - return mTimeStyle; -} - -void DateFormatter::setLocale(String * locale) -{ - MC_SAFE_REPLACE_COPY(String, mLocale, locale); -} - -String * DateFormatter::locale() -{ - return mLocale; -} - -void DateFormatter::setTimezone(String * timezone) -{ - MC_SAFE_REPLACE_COPY(String, mTimezone, timezone); -} - -String * DateFormatter::timezone() -{ - return mTimezone; -} - -void DateFormatter::setDateFormat(String * dateFormat) -{ - MC_SAFE_REPLACE_COPY(String, mDateFormat, dateFormat); -} - -String * DateFormatter::dateFormat() -{ - return mDateFormat; -} - -String * DateFormatter::stringFromDate(time_t date) -{ - prepare(); -#if USE_COREFOUNDATION - if (mAppleDateFormatter == NULL) - return NULL; - - CFDateRef dateRef = CFDateCreate(NULL, (CFAbsoluteTime) date - kCFAbsoluteTimeIntervalSince1970); - CFStringRef string = CFDateFormatterCreateStringWithDate(NULL, (CFDateFormatterRef) mAppleDateFormatter, dateRef); - CFIndex len = CFStringGetLength(string); - UniChar * buffer = (UniChar *) malloc(sizeof(* buffer) * len); - CFStringGetCharacters(string, CFRangeMake(0, len), buffer); - String * result = String::stringWithCharacters(buffer, (unsigned int) len); - free(buffer); - CFRelease(string); - CFRelease(dateRef); - return result; -#else - if (mDateFormatter == NULL) - return NULL; - - UErrorCode err = U_ZERO_ERROR; - int32_t len = udat_format(mDateFormatter, ((double) date) * 1000., NULL, 0, NULL, &err); - if(err != U_BUFFER_OVERFLOW_ERROR) { - return NULL; - } - - String * result; - - err = U_ZERO_ERROR; - UChar * unichars = (UChar *) malloc((len + 1) * sizeof(unichars)); - udat_format(mDateFormatter, ((double) date) * 1000., unichars, len + 1, NULL, &err); - result = new String(unichars, len); - free(unichars); - - result->autorelease(); - return result; -#endif -} - -time_t DateFormatter::dateFromString(String * dateString) -{ - prepare(); -#if USE_COREFOUNDATION - if (mAppleDateFormatter == NULL) - return (time_t) -1; - - CFAbsoluteTime absoluteTime; - bool r; - time_t result; - CFStringRef dateCFString = CFStringCreateWithCharacters(NULL, (const UniChar *) dateString->unicodeCharacters(), - dateString->length()); - r = CFDateFormatterGetAbsoluteTimeFromString((CFDateFormatterRef) mAppleDateFormatter, dateCFString, - NULL, &absoluteTime); - result = (time_t) -1; - if (r) { - result = (time_t) absoluteTime + kCFAbsoluteTimeIntervalSince1970; - } - CFRelease(dateCFString); - - return result; -#else - if (mDateFormatter == NULL) - return (time_t) -1; - - UErrorCode err = U_ZERO_ERROR; - UDate date = udat_parse(mDateFormatter, dateString->unicodeCharacters(), dateString->length(), - NULL, &err); - if (err != U_ZERO_ERROR) { - return (time_t) -1; - } - - return date / 1000.; -#endif -} - -#if USE_COREFOUNDATION -static CFDateFormatterStyle toAppleStyle(DateFormatStyle style) -{ - switch (style) { - case DateFormatStyleFull: - return kCFDateFormatterFullStyle; - case DateFormatStyleLong: - return kCFDateFormatterLongStyle; - case DateFormatStyleMedium: - return kCFDateFormatterMediumStyle; - case DateFormatStyleShort: - return kCFDateFormatterShortStyle; - case DateFormatStyleNone: - return kCFDateFormatterNoStyle; - } - return kCFDateFormatterMediumStyle; -} -#endif - -void DateFormatter::prepare() -{ -#if USE_COREFOUNDATION - if (mAppleDateFormatter != NULL) - return; - - CFStringRef localeIdentifier = NULL; - CFLocaleRef localeRef = NULL; - if (mLocale != NULL) { - localeIdentifier = CFStringCreateWithCharacters(NULL, (const UniChar *) mLocale->unicodeCharacters(), - mLocale->length()); - localeRef = CFLocaleCreate(NULL, localeIdentifier); - } - if (localeRef == NULL) { - localeRef = CFLocaleCopyCurrent(); - } - mAppleDateFormatter = CFDateFormatterCreate(NULL, localeRef, toAppleStyle(mDateStyle), toAppleStyle(mTimeStyle)); - if (mDateFormat != NULL) { - CFStringRef dateFormatCFString = CFStringCreateWithCharacters(NULL, (const UniChar *) mDateFormat->unicodeCharacters(), - mDateFormat->length()); - CFDateFormatterSetFormat((CFDateFormatterRef) mAppleDateFormatter, dateFormatCFString); - CFRelease(dateFormatCFString); - } - if (localeIdentifier != NULL) { - CFRelease(localeIdentifier); - } - if (localeRef != NULL) { - CFRelease(localeRef); - } -#else - if (mDateFormatter != NULL) - return; - - const UChar * tzID = NULL; - int32_t tzIDLength = -1; - const UChar * pattern = NULL; - int32_t patternLength = -1; - UErrorCode err = U_ZERO_ERROR; - const char * locale = NULL; - - if (mTimezone != NULL) { - tzID = mTimezone->unicodeCharacters(); - tzIDLength = mTimezone->length(); - } - if (mDateFormat != NULL) { - pattern = mDateFormat->unicodeCharacters(); - patternLength = mDateFormat->length(); - } - if (mLocale != NULL) { - locale = mLocale->UTF8Characters(); - } - - mDateFormatter = udat_open((UDateFormatStyle) mTimeStyle, (UDateFormatStyle) mDateStyle, - locale, - tzID, tzIDLength, - pattern, patternLength, - &err); -#endif -} diff --git a/src/core/renderer/MCDateFormatter.cpp b/src/core/renderer/MCDateFormatter.cpp new file mode 100644 index 00000000..4938d5ec --- /dev/null +++ b/src/core/renderer/MCDateFormatter.cpp @@ -0,0 +1,262 @@ +// +// MCDateFormatter.cpp +// testUI +// +// Created by DINH Viêt Hoà on 1/28/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCDateFormatter.h" +#include + +#if defined(__APPLE__) +#define USE_COREFOUNDATION 1 +#else +#include +#endif + +#if USE_COREFOUNDATION +#include +#endif + +using namespace mailcore; + +DateFormatter::DateFormatter() +{ + mDateFormatter = NULL; + mDateStyle = DateFormatStyleMedium; + mTimeStyle = DateFormatStyleMedium; + mDateFormat = NULL; + mTimezone = NULL; + mLocale = NULL; + mAppleDateFormatter = NULL; +} + +DateFormatter::~DateFormatter() +{ +#if USE_COREFOUNDATION + if (mAppleDateFormatter != NULL) { + CFRelease(mAppleDateFormatter); + } +#else + if (mDateFormatter != NULL) { + udat_close(mDateFormatter); + } +#endif + MC_SAFE_RELEASE(mDateFormat); + MC_SAFE_RELEASE(mTimezone); + MC_SAFE_RELEASE(mLocale); +} + +DateFormatter * DateFormatter::dateFormatter() +{ + DateFormatter * result = new DateFormatter(); + result->autorelease(); + return result; +} + + +void DateFormatter::setDateStyle(DateFormatStyle style) +{ + mDateStyle = style; +} + +DateFormatStyle DateFormatter::dateStyle() +{ + return mDateStyle; +} + +void DateFormatter::setTimeStyle(DateFormatStyle style) +{ + mTimeStyle = style; +} + +DateFormatStyle DateFormatter::timeStyle() +{ + return mTimeStyle; +} + +void DateFormatter::setLocale(String * locale) +{ + MC_SAFE_REPLACE_COPY(String, mLocale, locale); +} + +String * DateFormatter::locale() +{ + return mLocale; +} + +void DateFormatter::setTimezone(String * timezone) +{ + MC_SAFE_REPLACE_COPY(String, mTimezone, timezone); +} + +String * DateFormatter::timezone() +{ + return mTimezone; +} + +void DateFormatter::setDateFormat(String * dateFormat) +{ + MC_SAFE_REPLACE_COPY(String, mDateFormat, dateFormat); +} + +String * DateFormatter::dateFormat() +{ + return mDateFormat; +} + +String * DateFormatter::stringFromDate(time_t date) +{ + prepare(); +#if USE_COREFOUNDATION + if (mAppleDateFormatter == NULL) + return NULL; + + CFDateRef dateRef = CFDateCreate(NULL, (CFAbsoluteTime) date - kCFAbsoluteTimeIntervalSince1970); + CFStringRef string = CFDateFormatterCreateStringWithDate(NULL, (CFDateFormatterRef) mAppleDateFormatter, dateRef); + CFIndex len = CFStringGetLength(string); + UniChar * buffer = (UniChar *) malloc(sizeof(* buffer) * len); + CFStringGetCharacters(string, CFRangeMake(0, len), buffer); + String * result = String::stringWithCharacters(buffer, (unsigned int) len); + free(buffer); + CFRelease(string); + CFRelease(dateRef); + return result; +#else + if (mDateFormatter == NULL) + return NULL; + + UErrorCode err = U_ZERO_ERROR; + int32_t len = udat_format(mDateFormatter, ((double) date) * 1000., NULL, 0, NULL, &err); + if(err != U_BUFFER_OVERFLOW_ERROR) { + return NULL; + } + + String * result; + + err = U_ZERO_ERROR; + UChar * unichars = (UChar *) malloc((len + 1) * sizeof(unichars)); + udat_format(mDateFormatter, ((double) date) * 1000., unichars, len + 1, NULL, &err); + result = new String(unichars, len); + free(unichars); + + result->autorelease(); + return result; +#endif +} + +time_t DateFormatter::dateFromString(String * dateString) +{ + prepare(); +#if USE_COREFOUNDATION + if (mAppleDateFormatter == NULL) + return (time_t) -1; + + CFAbsoluteTime absoluteTime; + bool r; + time_t result; + CFStringRef dateCFString = CFStringCreateWithCharacters(NULL, (const UniChar *) dateString->unicodeCharacters(), + dateString->length()); + r = CFDateFormatterGetAbsoluteTimeFromString((CFDateFormatterRef) mAppleDateFormatter, dateCFString, + NULL, &absoluteTime); + result = (time_t) -1; + if (r) { + result = (time_t) absoluteTime + kCFAbsoluteTimeIntervalSince1970; + } + CFRelease(dateCFString); + + return result; +#else + if (mDateFormatter == NULL) + return (time_t) -1; + + UErrorCode err = U_ZERO_ERROR; + UDate date = udat_parse(mDateFormatter, dateString->unicodeCharacters(), dateString->length(), + NULL, &err); + if (err != U_ZERO_ERROR) { + return (time_t) -1; + } + + return date / 1000.; +#endif +} + +#if USE_COREFOUNDATION +static CFDateFormatterStyle toAppleStyle(DateFormatStyle style) +{ + switch (style) { + case DateFormatStyleFull: + return kCFDateFormatterFullStyle; + case DateFormatStyleLong: + return kCFDateFormatterLongStyle; + case DateFormatStyleMedium: + return kCFDateFormatterMediumStyle; + case DateFormatStyleShort: + return kCFDateFormatterShortStyle; + case DateFormatStyleNone: + return kCFDateFormatterNoStyle; + } + return kCFDateFormatterMediumStyle; +} +#endif + +void DateFormatter::prepare() +{ +#if USE_COREFOUNDATION + if (mAppleDateFormatter != NULL) + return; + + CFStringRef localeIdentifier = NULL; + CFLocaleRef localeRef = NULL; + if (mLocale != NULL) { + localeIdentifier = CFStringCreateWithCharacters(NULL, (const UniChar *) mLocale->unicodeCharacters(), + mLocale->length()); + localeRef = CFLocaleCreate(NULL, localeIdentifier); + } + if (localeRef == NULL) { + localeRef = CFLocaleCopyCurrent(); + } + mAppleDateFormatter = CFDateFormatterCreate(NULL, localeRef, toAppleStyle(mDateStyle), toAppleStyle(mTimeStyle)); + if (mDateFormat != NULL) { + CFStringRef dateFormatCFString = CFStringCreateWithCharacters(NULL, (const UniChar *) mDateFormat->unicodeCharacters(), + mDateFormat->length()); + CFDateFormatterSetFormat((CFDateFormatterRef) mAppleDateFormatter, dateFormatCFString); + CFRelease(dateFormatCFString); + } + if (localeIdentifier != NULL) { + CFRelease(localeIdentifier); + } + if (localeRef != NULL) { + CFRelease(localeRef); + } +#else + if (mDateFormatter != NULL) + return; + + const UChar * tzID = NULL; + int32_t tzIDLength = -1; + const UChar * pattern = NULL; + int32_t patternLength = -1; + UErrorCode err = U_ZERO_ERROR; + const char * locale = NULL; + + if (mTimezone != NULL) { + tzID = mTimezone->unicodeCharacters(); + tzIDLength = mTimezone->length(); + } + if (mDateFormat != NULL) { + pattern = mDateFormat->unicodeCharacters(); + patternLength = mDateFormat->length(); + } + if (mLocale != NULL) { + locale = mLocale->UTF8Characters(); + } + + mDateFormatter = udat_open((UDateFormatStyle) mTimeStyle, (UDateFormatStyle) mDateStyle, + locale, + tzID, tzIDLength, + pattern, patternLength, + &err); +#endif +} diff --git a/src/core/renderer/MCHTMLBodyRendererTemplateCallback.cc b/src/core/renderer/MCHTMLBodyRendererTemplateCallback.cc deleted file mode 100644 index 06a1a7a3..00000000 --- a/src/core/renderer/MCHTMLBodyRendererTemplateCallback.cc +++ /dev/null @@ -1,16 +0,0 @@ -// -// MCHTMLBodyRendererTemplateCallback.cc -// mailcore2 -// -// Created by Paul Young on 02/07/2013. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCHTMLBodyRendererTemplateCallback.h" - -using namespace mailcore; - -mailcore::String * HTMLBodyRendererTemplateCallback::templateForMainHeader(MessageHeader * header) -{ - return MCSTR(""); -} diff --git a/src/core/renderer/MCHTMLBodyRendererTemplateCallback.cpp b/src/core/renderer/MCHTMLBodyRendererTemplateCallback.cpp new file mode 100644 index 00000000..06a1a7a3 --- /dev/null +++ b/src/core/renderer/MCHTMLBodyRendererTemplateCallback.cpp @@ -0,0 +1,16 @@ +// +// MCHTMLBodyRendererTemplateCallback.cc +// mailcore2 +// +// Created by Paul Young on 02/07/2013. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCHTMLBodyRendererTemplateCallback.h" + +using namespace mailcore; + +mailcore::String * HTMLBodyRendererTemplateCallback::templateForMainHeader(MessageHeader * header) +{ + return MCSTR(""); +} diff --git a/src/core/renderer/MCHTMLRenderer.cc b/src/core/renderer/MCHTMLRenderer.cc deleted file mode 100644 index 568c939e..00000000 --- a/src/core/renderer/MCHTMLRenderer.cc +++ /dev/null @@ -1,574 +0,0 @@ -// -// MCHTMLRenderer.cpp -// testUI -// -// Created by DINH Viêt Hoà on 1/23/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCHTMLRenderer.h" - -#include -#include "MCAddressDisplay.h" -#include "MCDateFormatter.h" -#include "MCSizeFormatter.h" -#include "MCHTMLRendererCallback.h" - -using namespace mailcore; - -class HTMLRendererIMAPDummyCallback : public HTMLRendererIMAPCallback { -private: - Array *mRequiredParts; - -public: - HTMLRendererIMAPDummyCallback() - { - mRequiredParts = Array::array(); - mRequiredParts->retain(); - } - - virtual ~HTMLRendererIMAPDummyCallback() - { - MC_SAFE_RELEASE(mRequiredParts); - } - - - virtual Data * dataForIMAPPart(String * folder, IMAPPart * part) - { - mRequiredParts->addObject(part); - return Data::data(); - } - - Array * requiredParts() - { - return mRequiredParts; - } - -}; - -enum { - RENDER_STATE_NONE, - RENDER_STATE_HAD_ATTACHMENT, - RENDER_STATE_HAD_ATTACHMENT_THEN_TEXT, -}; - -struct htmlRendererContext { - HTMLRendererIMAPCallback * dataCallback; - HTMLRendererTemplateCallback * htmlCallback; - int firstRendered; - String * folder; - int state; - // pass == 0 -> render only text parts, - // pass == 1 -> render only attachments. - int pass; - bool hasMixedTextAndAttachments; - bool firstAttachment; - bool hasTextPart; - Array * relatedAttachments; - Array * attachments; -}; - -class DefaultTemplateCallback : public Object, public HTMLRendererTemplateCallback { -}; - -static bool partContainsMimeType(AbstractPart * part, String * mimeType); -static bool singlePartContainsMimeType(AbstractPart * part, String * mimeType); -static bool multipartContainsMimeType(AbstractMultipart * part, String * mimeType); -static bool messagePartContainsMimeType(AbstractMessagePart * part, String * mimeType); - -static String * htmlForAbstractPart(AbstractPart * part, htmlRendererContext * context); - -static String * renderTemplate(String * templateContent, HashMap * values); - -static String * htmlForAbstractMessage(String * folder, AbstractMessage * message, - HTMLRendererIMAPCallback * dataCallback, - HTMLRendererTemplateCallback * htmlCallback, - Array * attachments, - Array * relatedAttachments); - -static bool isTextPart(AbstractPart * part, htmlRendererContext * context) -{ - String * mimeType = part->mimeType()->lowercaseString(); - MCAssert(mimeType != NULL); - - if (!part->isInlineAttachment()) { - if ((part->filename() != NULL) && context->firstRendered) { - return false; - } - } - - if (mimeType->isEqual(MCSTR("text/plain"))) { - return true; - } - else if (mimeType->isEqual(MCSTR("text/html"))) { - return true; - } - else { - return false; - } -} - - -static AbstractPart * preferredPartInMultipartAlternative(AbstractMultipart * part) -{ - int htmlPart = -1; - int textPart = -1; - - for(unsigned int i = 0 ; i < part->parts()->count() ; i ++) { - AbstractPart * subpart = (AbstractPart *) part->parts()->objectAtIndex(i); - if (partContainsMimeType(subpart, MCSTR("text/html"))) { - htmlPart = i; - } - else if (partContainsMimeType(subpart, MCSTR("text/plain"))) { - textPart = i; - } - } - if (htmlPart != -1) { - return (AbstractPart *) part->parts()->objectAtIndex(htmlPart); - } - else if (textPart != -1) { - return (AbstractPart *) part->parts()->objectAtIndex(textPart); - } - else if (part->parts()->count() > 0) { - return (AbstractPart *) part->parts()->objectAtIndex(0); - } - else { - return NULL; - } -} - -static bool partContainsMimeType(AbstractPart * part, String * mimeType) -{ - switch (part->partType()) { - case PartTypeSingle: - return singlePartContainsMimeType(part, mimeType); - case PartTypeMessage: - return messagePartContainsMimeType((AbstractMessagePart *) part, mimeType); - case PartTypeMultipartMixed: - case PartTypeMultipartRelated: - case PartTypeMultipartAlternative: - case PartTypeMultipartSigned: - return multipartContainsMimeType((AbstractMultipart *) part, mimeType); - default: - return false; - } -} - -static bool singlePartContainsMimeType(AbstractPart * part, String * mimeType) -{ - return part->mimeType()->lowercaseString()->isEqual(mimeType); -} - -static bool multipartContainsMimeType(AbstractMultipart * part, String * mimeType) -{ - for(unsigned int i = 0 ; i < part->parts()->count() ; i ++) { - AbstractPart * subpart = (AbstractPart *) part->parts()->objectAtIndex(i); - if (partContainsMimeType(subpart, mimeType)) { - return true; - } - } - return false; -} - -static bool messagePartContainsMimeType(AbstractMessagePart * part, String * mimeType) -{ - return partContainsMimeType(part->mainPart(), mimeType); -} - -static String * htmlForAbstractMessage(String * folder, AbstractMessage * message, - HTMLRendererIMAPCallback * dataCallback, - HTMLRendererTemplateCallback * htmlCallback, - Array * attachments, - Array * relatedAttachments) -{ - AbstractPart * mainPart = NULL; - - if (htmlCallback == NULL) { - htmlCallback = new DefaultTemplateCallback(); - ((DefaultTemplateCallback *) htmlCallback)->autorelease(); - } - - if (message->className()->isEqual(MCSTR("mailcore::IMAPMessage"))) { - mainPart = ((IMAPMessage *) message)->mainPart(); - } - else if (message->className()->isEqual(MCSTR("mailcore::MessageParser"))) { - mainPart = ((MessageParser *) message)->mainPart(); - } - MCAssert(mainPart != NULL); - - htmlRendererContext context; - context.dataCallback = dataCallback; - context.htmlCallback = htmlCallback; - context.relatedAttachments = NULL; - context.attachments = NULL; - context.firstRendered = 0; - context.folder = folder; - context.state = RENDER_STATE_NONE; - - context.hasMixedTextAndAttachments = false; - context.pass = 0; - context.firstAttachment = false; - context.hasTextPart = false; - - htmlForAbstractPart(mainPart, &context); - - context.relatedAttachments = relatedAttachments; - context.attachments = attachments; - context.hasMixedTextAndAttachments = (context.state == RENDER_STATE_HAD_ATTACHMENT_THEN_TEXT); - context.pass = 1; - context.firstAttachment = false; - context.hasTextPart = false; - String * content = htmlForAbstractPart(mainPart, &context); - if (content == NULL) - return NULL; - - content = htmlCallback->filterHTMLForMessage(content); - - HashMap * values = htmlCallback->templateValuesForHeader(message->header()); - String * headerString = renderTemplate(htmlCallback->templateForMainHeader(message->header()), values); - - HashMap * msgValues = new HashMap(); - msgValues->setObjectForKey(MCSTR("HEADER"), headerString); - msgValues->setObjectForKey(MCSTR("BODY"), content); - String * result = renderTemplate(htmlCallback->templateForMessage(message), msgValues); - msgValues->release(); - - return result; -} - -static String * htmlForAbstractSinglePart(AbstractPart * part, htmlRendererContext * context); -static String * htmlForAbstractMessagePart(AbstractMessagePart * part, htmlRendererContext * context); -static String * htmlForAbstractMultipartRelated(AbstractMultipart * part, htmlRendererContext * context); -static String * htmlForAbstractMultipartMixed(AbstractMultipart * part, htmlRendererContext * context); -static String * htmlForAbstractMultipartAlternative(AbstractMultipart * part, htmlRendererContext * context); - -static String * htmlForAbstractPart(AbstractPart * part, htmlRendererContext * context) -{ - switch (part->partType()) { - case PartTypeSingle: - return htmlForAbstractSinglePart((AbstractPart *) part, context); - case PartTypeMessage: - return htmlForAbstractMessagePart((AbstractMessagePart *) part, context); - case PartTypeMultipartMixed: - return htmlForAbstractMultipartMixed((AbstractMultipart *) part, context); - case PartTypeMultipartRelated: - return htmlForAbstractMultipartRelated((AbstractMultipart *) part, context); - case PartTypeMultipartAlternative: - return htmlForAbstractMultipartAlternative((AbstractMultipart *) part, context); - case PartTypeMultipartSigned: - return htmlForAbstractMultipartMixed((AbstractMultipart *) part, context); - default: - MCAssert(0); - } - return NULL; -} - -static String * htmlForAbstractSinglePart(AbstractPart * part, htmlRendererContext * context) -{ - String * mimeType = NULL; - if (part->mimeType() != NULL) { - mimeType = part->mimeType()->lowercaseString(); - } - MCAssert(mimeType != NULL); - - if (isTextPart(part, context)) { - if (context->pass == 0) { - if (context->state == RENDER_STATE_HAD_ATTACHMENT) { - context->state = RENDER_STATE_HAD_ATTACHMENT_THEN_TEXT; - } - return NULL; - } - - context->hasTextPart = true; - - if (mimeType->isEqual(MCSTR("text/plain"))) { - String * charset = part->charset(); - Data * data = NULL; - if (part->className()->isEqual(MCSTR("mailcore::IMAPPart"))) { - data = context->dataCallback->dataForIMAPPart(context->folder, (IMAPPart *) part); - } - else if (part->className()->isEqual(MCSTR("mailcore::Attachment"))) { - data = ((Attachment *) part)->data(); - MCAssert(data != NULL); - } - if (data == NULL) - return NULL; - - String * str = data->stringWithDetectedCharset(charset, false); - str = str->htmlMessageContent(); - context->firstRendered = true; - return str; - } - else if (mimeType->isEqual(MCSTR("text/html"))) { - String * charset = part->charset(); - Data * data = NULL; - if (part->className()->isEqual(MCSTR("mailcore::IMAPPart"))) { - data = context->dataCallback->dataForIMAPPart(context->folder, (IMAPPart *) part); - } - else if (part->className()->isEqual(MCSTR("mailcore::Attachment"))) { - data = ((Attachment *) part)->data(); - MCAssert(data != NULL); - } - if (data == NULL) - return NULL; - - String * str = data->stringWithDetectedCharset(charset, true); - str = context->htmlCallback->cleanHTMLForPart(str); - str = context->htmlCallback->filterHTMLForPart(str); - context->firstRendered = true; - return str; - } - else { - MCAssert(0); - return NULL; - } - } - else { - - if (!context->htmlCallback->shouldShowPart(part)) - return MCSTR(""); - - if (context->pass == 0) { - if (context->state == RENDER_STATE_NONE) { - context->state = RENDER_STATE_HAD_ATTACHMENT; - } - return NULL; - } - - if (part->uniqueID() == NULL) { - part->setUniqueID(String::uuidString()); - } - - String * result = String::string(); - String * separatorString; - String * content; - - if (!context->firstAttachment && context->hasTextPart) { - separatorString = context->htmlCallback->templateForAttachmentSeparator(); - } - else { - separatorString = MCSTR(""); - } - - context->firstAttachment = true; - - if (context->htmlCallback->canPreviewPart(part)) { - if (part->className()->isEqual(MCSTR("mailcore::IMAPPart"))) { - context->dataCallback->prefetchImageIMAPPart(context->folder, (IMAPPart *) part); - } - String * url = String::stringWithUTF8Format("x-mailcore-image:%s", - part->uniqueID()->UTF8Characters()); - HashMap * values = context->htmlCallback->templateValuesForPart(part); - values->setObjectForKey(MCSTR("URL"), url); - content = renderTemplate(context->htmlCallback->templateForImage(part), values); - } - else { - if (part->className()->isEqual(MCSTR("mailcore::IMAPPart"))) { - context->dataCallback->prefetchAttachmentIMAPPart(context->folder, (IMAPPart *) part); - } - HashMap * values = context->htmlCallback->templateValuesForPart(part); - content = renderTemplate(context->htmlCallback->templateForAttachment(part), values); - } - - result->appendString(separatorString); - result->appendString(content); - - if (context->attachments != NULL) { - context->attachments->addObject(part); - } - - return result; - } -} - -static String * htmlForAbstractMessagePart(AbstractMessagePart * part, htmlRendererContext * context) -{ - if (context->pass == 0) { - return NULL; - } - String * substring = htmlForAbstractPart(part->mainPart(), context); - if (substring == NULL) - return NULL; - - HashMap * values = context->htmlCallback->templateValuesForHeader(part->header()); - String * headerString = renderTemplate(context->htmlCallback->templateForEmbeddedMessageHeader(part->header()), values); - - HashMap * msgValues = new HashMap(); - msgValues->setObjectForKey(MCSTR("HEADER"), headerString); - msgValues->setObjectForKey(MCSTR("BODY"), substring); - String * result = renderTemplate(context->htmlCallback->templateForEmbeddedMessage(part), msgValues); - msgValues->release(); - - return result; -} - -String * htmlForAbstractMultipartAlternative(AbstractMultipart * part, htmlRendererContext * context) -{ - AbstractPart * preferredAlternative = preferredPartInMultipartAlternative(part); - if (preferredAlternative == NULL) - return MCSTR(""); - - // Exchange sends calendar invitation as alternative part. We need to extract it. - AbstractPart * calendar = NULL; - for(unsigned int i = 0 ; i < part->parts()->count() ; i ++) { - AbstractPart * subpart = (AbstractPart *) part->parts()->objectAtIndex(i); - if (partContainsMimeType(subpart, MCSTR("text/calendar"))) { - calendar = subpart; - } - } - - String * html = htmlForAbstractPart(preferredAlternative, context); - if (html == NULL) { - return NULL; - } - - String * result = String::string(); - result->appendString(html); - if (calendar != NULL) { - result->appendString(htmlForAbstractPart(calendar, context)); - } - return result; -} - -static String * htmlForAbstractMultipartMixed(AbstractMultipart * part, htmlRendererContext * context) -{ - String * result = String::string(); - for(unsigned int i = 0 ; i < part->parts()->count() ; i ++) { - AbstractPart * subpart = (AbstractPart *) part->parts()->objectAtIndex(i); - String * substring = htmlForAbstractPart(subpart, context); - if (context->pass != 0) { - if (substring == NULL) - return NULL; - - result->appendString(substring); - } - } - return result; -} - -static String * htmlForAbstractMultipartRelated(AbstractMultipart * part, htmlRendererContext * context) -{ - if (part->parts()->count() == 0) { - if (context->pass == 0) { - return NULL; - } - else { - return MCSTR(""); - } - } - - // root of the multipart/related. - AbstractPart * subpart = (AbstractPart *) part->parts()->objectAtIndex(0); - if (context->relatedAttachments != NULL) { - for(unsigned int i = 1 ; i < part->parts()->count() ; i ++) { - AbstractPart * otherSubpart = (AbstractPart *) part->parts()->objectAtIndex(i); - if (context->relatedAttachments != NULL) { - context->relatedAttachments->addObject(otherSubpart); - } - } - } - return htmlForAbstractPart(subpart, context); -} - -static void fillTemplateDictionaryFromMCHashMap(ctemplate::TemplateDictionary * dict, HashMap * mcHashMap) -{ - Array * keys = mcHashMap->allKeys(); - - for(unsigned int i = 0 ; i < keys->count() ; i ++) { - String * key = (String *) keys->objectAtIndex(i); - Object * value; - - value = mcHashMap->objectForKey(key); - if (value->className()->isEqual(MCSTR("mailcore::String"))) { - String * str; - - str = (String *) value; - dict->SetValue(key->UTF8Characters(), str->UTF8Characters()); - } - else if (value->className()->isEqual(MCSTR("mailcore::Array"))) { - Array * array; - - array = (Array *) value; - for(unsigned int k = 0 ; k < array->count() ; k ++) { - HashMap * item = (HashMap *) array->objectAtIndex(k); - ctemplate::TemplateDictionary * subDict = dict->AddSectionDictionary(key->UTF8Characters()); - fillTemplateDictionaryFromMCHashMap(subDict, item); - } - } - else if (value->className()->isEqual(MCSTR("mailcore::HashMap"))) { - ctemplate::TemplateDictionary * subDict; - HashMap * item; - - item = (HashMap *) value; - subDict = dict->AddSectionDictionary(key->UTF8Characters()); - fillTemplateDictionaryFromMCHashMap(subDict, item); - } - } -} - -static String * renderTemplate(String * templateContent, HashMap * values) -{ - ctemplate::TemplateDictionary dict("template dict"); - std::string output; - Data * data; - - fillTemplateDictionaryFromMCHashMap(&dict, values); - data = templateContent->dataUsingEncoding("utf-8"); - ctemplate::Template * tpl = ctemplate::Template::StringToTemplate(data->bytes(), data->length(), ctemplate::DO_NOT_STRIP); - if (tpl == NULL) - return NULL; - if (!tpl->Expand(&output, &dict)) - return NULL; - delete tpl; - - return String::stringWithUTF8Characters(output.c_str()); -} - -String * HTMLRenderer::htmlForRFC822Message(MessageParser * message, - HTMLRendererTemplateCallback * htmlCallback) -{ - return htmlForAbstractMessage(NULL, message, NULL, htmlCallback, NULL, NULL); -} - -String * HTMLRenderer::htmlForIMAPMessage(String * folder, - IMAPMessage * message, - HTMLRendererIMAPCallback * dataCallback, - HTMLRendererTemplateCallback * htmlCallback) -{ - return htmlForAbstractMessage(folder, message, dataCallback, htmlCallback, NULL, NULL); -} - -Array * HTMLRenderer::attachmentsForMessage(AbstractMessage * message) -{ - Array * attachments = Array::array(); - HTMLRendererIMAPCallback * dataCallback = new HTMLRendererIMAPDummyCallback(); - String * ignoredResult = htmlForAbstractMessage(NULL, message, dataCallback, NULL, attachments, NULL); - delete dataCallback; - dataCallback = NULL; - (void) ignoredResult; // remove unused variable warning. - return attachments; -} - -Array * HTMLRenderer::htmlInlineAttachmentsForMessage(AbstractMessage * message) -{ - Array * htmlInlineAttachments = Array::array(); - HTMLRendererIMAPCallback * dataCallback = new HTMLRendererIMAPDummyCallback(); - String * ignoredResult = htmlForAbstractMessage(NULL, message, dataCallback, NULL, NULL, htmlInlineAttachments); - delete dataCallback; - dataCallback = NULL; - (void) ignoredResult; // remove unused variable warning. - return htmlInlineAttachments; -} - -Array * HTMLRenderer::requiredPartsForRendering(AbstractMessage * message) -{ - HTMLRendererIMAPDummyCallback * dataCallback = new HTMLRendererIMAPDummyCallback(); - String * ignoredResult = htmlForAbstractMessage(NULL, message, dataCallback, NULL, NULL, NULL); - - Array *requiredParts = dataCallback->requiredParts(); - - delete dataCallback; - dataCallback = NULL; - (void) ignoredResult; // remove unused variable warning. - return requiredParts; -} diff --git a/src/core/renderer/MCHTMLRenderer.cpp b/src/core/renderer/MCHTMLRenderer.cpp new file mode 100644 index 00000000..568c939e --- /dev/null +++ b/src/core/renderer/MCHTMLRenderer.cpp @@ -0,0 +1,574 @@ +// +// MCHTMLRenderer.cpp +// testUI +// +// Created by DINH Viêt Hoà on 1/23/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCHTMLRenderer.h" + +#include +#include "MCAddressDisplay.h" +#include "MCDateFormatter.h" +#include "MCSizeFormatter.h" +#include "MCHTMLRendererCallback.h" + +using namespace mailcore; + +class HTMLRendererIMAPDummyCallback : public HTMLRendererIMAPCallback { +private: + Array *mRequiredParts; + +public: + HTMLRendererIMAPDummyCallback() + { + mRequiredParts = Array::array(); + mRequiredParts->retain(); + } + + virtual ~HTMLRendererIMAPDummyCallback() + { + MC_SAFE_RELEASE(mRequiredParts); + } + + + virtual Data * dataForIMAPPart(String * folder, IMAPPart * part) + { + mRequiredParts->addObject(part); + return Data::data(); + } + + Array * requiredParts() + { + return mRequiredParts; + } + +}; + +enum { + RENDER_STATE_NONE, + RENDER_STATE_HAD_ATTACHMENT, + RENDER_STATE_HAD_ATTACHMENT_THEN_TEXT, +}; + +struct htmlRendererContext { + HTMLRendererIMAPCallback * dataCallback; + HTMLRendererTemplateCallback * htmlCallback; + int firstRendered; + String * folder; + int state; + // pass == 0 -> render only text parts, + // pass == 1 -> render only attachments. + int pass; + bool hasMixedTextAndAttachments; + bool firstAttachment; + bool hasTextPart; + Array * relatedAttachments; + Array * attachments; +}; + +class DefaultTemplateCallback : public Object, public HTMLRendererTemplateCallback { +}; + +static bool partContainsMimeType(AbstractPart * part, String * mimeType); +static bool singlePartContainsMimeType(AbstractPart * part, String * mimeType); +static bool multipartContainsMimeType(AbstractMultipart * part, String * mimeType); +static bool messagePartContainsMimeType(AbstractMessagePart * part, String * mimeType); + +static String * htmlForAbstractPart(AbstractPart * part, htmlRendererContext * context); + +static String * renderTemplate(String * templateContent, HashMap * values); + +static String * htmlForAbstractMessage(String * folder, AbstractMessage * message, + HTMLRendererIMAPCallback * dataCallback, + HTMLRendererTemplateCallback * htmlCallback, + Array * attachments, + Array * relatedAttachments); + +static bool isTextPart(AbstractPart * part, htmlRendererContext * context) +{ + String * mimeType = part->mimeType()->lowercaseString(); + MCAssert(mimeType != NULL); + + if (!part->isInlineAttachment()) { + if ((part->filename() != NULL) && context->firstRendered) { + return false; + } + } + + if (mimeType->isEqual(MCSTR("text/plain"))) { + return true; + } + else if (mimeType->isEqual(MCSTR("text/html"))) { + return true; + } + else { + return false; + } +} + + +static AbstractPart * preferredPartInMultipartAlternative(AbstractMultipart * part) +{ + int htmlPart = -1; + int textPart = -1; + + for(unsigned int i = 0 ; i < part->parts()->count() ; i ++) { + AbstractPart * subpart = (AbstractPart *) part->parts()->objectAtIndex(i); + if (partContainsMimeType(subpart, MCSTR("text/html"))) { + htmlPart = i; + } + else if (partContainsMimeType(subpart, MCSTR("text/plain"))) { + textPart = i; + } + } + if (htmlPart != -1) { + return (AbstractPart *) part->parts()->objectAtIndex(htmlPart); + } + else if (textPart != -1) { + return (AbstractPart *) part->parts()->objectAtIndex(textPart); + } + else if (part->parts()->count() > 0) { + return (AbstractPart *) part->parts()->objectAtIndex(0); + } + else { + return NULL; + } +} + +static bool partContainsMimeType(AbstractPart * part, String * mimeType) +{ + switch (part->partType()) { + case PartTypeSingle: + return singlePartContainsMimeType(part, mimeType); + case PartTypeMessage: + return messagePartContainsMimeType((AbstractMessagePart *) part, mimeType); + case PartTypeMultipartMixed: + case PartTypeMultipartRelated: + case PartTypeMultipartAlternative: + case PartTypeMultipartSigned: + return multipartContainsMimeType((AbstractMultipart *) part, mimeType); + default: + return false; + } +} + +static bool singlePartContainsMimeType(AbstractPart * part, String * mimeType) +{ + return part->mimeType()->lowercaseString()->isEqual(mimeType); +} + +static bool multipartContainsMimeType(AbstractMultipart * part, String * mimeType) +{ + for(unsigned int i = 0 ; i < part->parts()->count() ; i ++) { + AbstractPart * subpart = (AbstractPart *) part->parts()->objectAtIndex(i); + if (partContainsMimeType(subpart, mimeType)) { + return true; + } + } + return false; +} + +static bool messagePartContainsMimeType(AbstractMessagePart * part, String * mimeType) +{ + return partContainsMimeType(part->mainPart(), mimeType); +} + +static String * htmlForAbstractMessage(String * folder, AbstractMessage * message, + HTMLRendererIMAPCallback * dataCallback, + HTMLRendererTemplateCallback * htmlCallback, + Array * attachments, + Array * relatedAttachments) +{ + AbstractPart * mainPart = NULL; + + if (htmlCallback == NULL) { + htmlCallback = new DefaultTemplateCallback(); + ((DefaultTemplateCallback *) htmlCallback)->autorelease(); + } + + if (message->className()->isEqual(MCSTR("mailcore::IMAPMessage"))) { + mainPart = ((IMAPMessage *) message)->mainPart(); + } + else if (message->className()->isEqual(MCSTR("mailcore::MessageParser"))) { + mainPart = ((MessageParser *) message)->mainPart(); + } + MCAssert(mainPart != NULL); + + htmlRendererContext context; + context.dataCallback = dataCallback; + context.htmlCallback = htmlCallback; + context.relatedAttachments = NULL; + context.attachments = NULL; + context.firstRendered = 0; + context.folder = folder; + context.state = RENDER_STATE_NONE; + + context.hasMixedTextAndAttachments = false; + context.pass = 0; + context.firstAttachment = false; + context.hasTextPart = false; + + htmlForAbstractPart(mainPart, &context); + + context.relatedAttachments = relatedAttachments; + context.attachments = attachments; + context.hasMixedTextAndAttachments = (context.state == RENDER_STATE_HAD_ATTACHMENT_THEN_TEXT); + context.pass = 1; + context.firstAttachment = false; + context.hasTextPart = false; + String * content = htmlForAbstractPart(mainPart, &context); + if (content == NULL) + return NULL; + + content = htmlCallback->filterHTMLForMessage(content); + + HashMap * values = htmlCallback->templateValuesForHeader(message->header()); + String * headerString = renderTemplate(htmlCallback->templateForMainHeader(message->header()), values); + + HashMap * msgValues = new HashMap(); + msgValues->setObjectForKey(MCSTR("HEADER"), headerString); + msgValues->setObjectForKey(MCSTR("BODY"), content); + String * result = renderTemplate(htmlCallback->templateForMessage(message), msgValues); + msgValues->release(); + + return result; +} + +static String * htmlForAbstractSinglePart(AbstractPart * part, htmlRendererContext * context); +static String * htmlForAbstractMessagePart(AbstractMessagePart * part, htmlRendererContext * context); +static String * htmlForAbstractMultipartRelated(AbstractMultipart * part, htmlRendererContext * context); +static String * htmlForAbstractMultipartMixed(AbstractMultipart * part, htmlRendererContext * context); +static String * htmlForAbstractMultipartAlternative(AbstractMultipart * part, htmlRendererContext * context); + +static String * htmlForAbstractPart(AbstractPart * part, htmlRendererContext * context) +{ + switch (part->partType()) { + case PartTypeSingle: + return htmlForAbstractSinglePart((AbstractPart *) part, context); + case PartTypeMessage: + return htmlForAbstractMessagePart((AbstractMessagePart *) part, context); + case PartTypeMultipartMixed: + return htmlForAbstractMultipartMixed((AbstractMultipart *) part, context); + case PartTypeMultipartRelated: + return htmlForAbstractMultipartRelated((AbstractMultipart *) part, context); + case PartTypeMultipartAlternative: + return htmlForAbstractMultipartAlternative((AbstractMultipart *) part, context); + case PartTypeMultipartSigned: + return htmlForAbstractMultipartMixed((AbstractMultipart *) part, context); + default: + MCAssert(0); + } + return NULL; +} + +static String * htmlForAbstractSinglePart(AbstractPart * part, htmlRendererContext * context) +{ + String * mimeType = NULL; + if (part->mimeType() != NULL) { + mimeType = part->mimeType()->lowercaseString(); + } + MCAssert(mimeType != NULL); + + if (isTextPart(part, context)) { + if (context->pass == 0) { + if (context->state == RENDER_STATE_HAD_ATTACHMENT) { + context->state = RENDER_STATE_HAD_ATTACHMENT_THEN_TEXT; + } + return NULL; + } + + context->hasTextPart = true; + + if (mimeType->isEqual(MCSTR("text/plain"))) { + String * charset = part->charset(); + Data * data = NULL; + if (part->className()->isEqual(MCSTR("mailcore::IMAPPart"))) { + data = context->dataCallback->dataForIMAPPart(context->folder, (IMAPPart *) part); + } + else if (part->className()->isEqual(MCSTR("mailcore::Attachment"))) { + data = ((Attachment *) part)->data(); + MCAssert(data != NULL); + } + if (data == NULL) + return NULL; + + String * str = data->stringWithDetectedCharset(charset, false); + str = str->htmlMessageContent(); + context->firstRendered = true; + return str; + } + else if (mimeType->isEqual(MCSTR("text/html"))) { + String * charset = part->charset(); + Data * data = NULL; + if (part->className()->isEqual(MCSTR("mailcore::IMAPPart"))) { + data = context->dataCallback->dataForIMAPPart(context->folder, (IMAPPart *) part); + } + else if (part->className()->isEqual(MCSTR("mailcore::Attachment"))) { + data = ((Attachment *) part)->data(); + MCAssert(data != NULL); + } + if (data == NULL) + return NULL; + + String * str = data->stringWithDetectedCharset(charset, true); + str = context->htmlCallback->cleanHTMLForPart(str); + str = context->htmlCallback->filterHTMLForPart(str); + context->firstRendered = true; + return str; + } + else { + MCAssert(0); + return NULL; + } + } + else { + + if (!context->htmlCallback->shouldShowPart(part)) + return MCSTR(""); + + if (context->pass == 0) { + if (context->state == RENDER_STATE_NONE) { + context->state = RENDER_STATE_HAD_ATTACHMENT; + } + return NULL; + } + + if (part->uniqueID() == NULL) { + part->setUniqueID(String::uuidString()); + } + + String * result = String::string(); + String * separatorString; + String * content; + + if (!context->firstAttachment && context->hasTextPart) { + separatorString = context->htmlCallback->templateForAttachmentSeparator(); + } + else { + separatorString = MCSTR(""); + } + + context->firstAttachment = true; + + if (context->htmlCallback->canPreviewPart(part)) { + if (part->className()->isEqual(MCSTR("mailcore::IMAPPart"))) { + context->dataCallback->prefetchImageIMAPPart(context->folder, (IMAPPart *) part); + } + String * url = String::stringWithUTF8Format("x-mailcore-image:%s", + part->uniqueID()->UTF8Characters()); + HashMap * values = context->htmlCallback->templateValuesForPart(part); + values->setObjectForKey(MCSTR("URL"), url); + content = renderTemplate(context->htmlCallback->templateForImage(part), values); + } + else { + if (part->className()->isEqual(MCSTR("mailcore::IMAPPart"))) { + context->dataCallback->prefetchAttachmentIMAPPart(context->folder, (IMAPPart *) part); + } + HashMap * values = context->htmlCallback->templateValuesForPart(part); + content = renderTemplate(context->htmlCallback->templateForAttachment(part), values); + } + + result->appendString(separatorString); + result->appendString(content); + + if (context->attachments != NULL) { + context->attachments->addObject(part); + } + + return result; + } +} + +static String * htmlForAbstractMessagePart(AbstractMessagePart * part, htmlRendererContext * context) +{ + if (context->pass == 0) { + return NULL; + } + String * substring = htmlForAbstractPart(part->mainPart(), context); + if (substring == NULL) + return NULL; + + HashMap * values = context->htmlCallback->templateValuesForHeader(part->header()); + String * headerString = renderTemplate(context->htmlCallback->templateForEmbeddedMessageHeader(part->header()), values); + + HashMap * msgValues = new HashMap(); + msgValues->setObjectForKey(MCSTR("HEADER"), headerString); + msgValues->setObjectForKey(MCSTR("BODY"), substring); + String * result = renderTemplate(context->htmlCallback->templateForEmbeddedMessage(part), msgValues); + msgValues->release(); + + return result; +} + +String * htmlForAbstractMultipartAlternative(AbstractMultipart * part, htmlRendererContext * context) +{ + AbstractPart * preferredAlternative = preferredPartInMultipartAlternative(part); + if (preferredAlternative == NULL) + return MCSTR(""); + + // Exchange sends calendar invitation as alternative part. We need to extract it. + AbstractPart * calendar = NULL; + for(unsigned int i = 0 ; i < part->parts()->count() ; i ++) { + AbstractPart * subpart = (AbstractPart *) part->parts()->objectAtIndex(i); + if (partContainsMimeType(subpart, MCSTR("text/calendar"))) { + calendar = subpart; + } + } + + String * html = htmlForAbstractPart(preferredAlternative, context); + if (html == NULL) { + return NULL; + } + + String * result = String::string(); + result->appendString(html); + if (calendar != NULL) { + result->appendString(htmlForAbstractPart(calendar, context)); + } + return result; +} + +static String * htmlForAbstractMultipartMixed(AbstractMultipart * part, htmlRendererContext * context) +{ + String * result = String::string(); + for(unsigned int i = 0 ; i < part->parts()->count() ; i ++) { + AbstractPart * subpart = (AbstractPart *) part->parts()->objectAtIndex(i); + String * substring = htmlForAbstractPart(subpart, context); + if (context->pass != 0) { + if (substring == NULL) + return NULL; + + result->appendString(substring); + } + } + return result; +} + +static String * htmlForAbstractMultipartRelated(AbstractMultipart * part, htmlRendererContext * context) +{ + if (part->parts()->count() == 0) { + if (context->pass == 0) { + return NULL; + } + else { + return MCSTR(""); + } + } + + // root of the multipart/related. + AbstractPart * subpart = (AbstractPart *) part->parts()->objectAtIndex(0); + if (context->relatedAttachments != NULL) { + for(unsigned int i = 1 ; i < part->parts()->count() ; i ++) { + AbstractPart * otherSubpart = (AbstractPart *) part->parts()->objectAtIndex(i); + if (context->relatedAttachments != NULL) { + context->relatedAttachments->addObject(otherSubpart); + } + } + } + return htmlForAbstractPart(subpart, context); +} + +static void fillTemplateDictionaryFromMCHashMap(ctemplate::TemplateDictionary * dict, HashMap * mcHashMap) +{ + Array * keys = mcHashMap->allKeys(); + + for(unsigned int i = 0 ; i < keys->count() ; i ++) { + String * key = (String *) keys->objectAtIndex(i); + Object * value; + + value = mcHashMap->objectForKey(key); + if (value->className()->isEqual(MCSTR("mailcore::String"))) { + String * str; + + str = (String *) value; + dict->SetValue(key->UTF8Characters(), str->UTF8Characters()); + } + else if (value->className()->isEqual(MCSTR("mailcore::Array"))) { + Array * array; + + array = (Array *) value; + for(unsigned int k = 0 ; k < array->count() ; k ++) { + HashMap * item = (HashMap *) array->objectAtIndex(k); + ctemplate::TemplateDictionary * subDict = dict->AddSectionDictionary(key->UTF8Characters()); + fillTemplateDictionaryFromMCHashMap(subDict, item); + } + } + else if (value->className()->isEqual(MCSTR("mailcore::HashMap"))) { + ctemplate::TemplateDictionary * subDict; + HashMap * item; + + item = (HashMap *) value; + subDict = dict->AddSectionDictionary(key->UTF8Characters()); + fillTemplateDictionaryFromMCHashMap(subDict, item); + } + } +} + +static String * renderTemplate(String * templateContent, HashMap * values) +{ + ctemplate::TemplateDictionary dict("template dict"); + std::string output; + Data * data; + + fillTemplateDictionaryFromMCHashMap(&dict, values); + data = templateContent->dataUsingEncoding("utf-8"); + ctemplate::Template * tpl = ctemplate::Template::StringToTemplate(data->bytes(), data->length(), ctemplate::DO_NOT_STRIP); + if (tpl == NULL) + return NULL; + if (!tpl->Expand(&output, &dict)) + return NULL; + delete tpl; + + return String::stringWithUTF8Characters(output.c_str()); +} + +String * HTMLRenderer::htmlForRFC822Message(MessageParser * message, + HTMLRendererTemplateCallback * htmlCallback) +{ + return htmlForAbstractMessage(NULL, message, NULL, htmlCallback, NULL, NULL); +} + +String * HTMLRenderer::htmlForIMAPMessage(String * folder, + IMAPMessage * message, + HTMLRendererIMAPCallback * dataCallback, + HTMLRendererTemplateCallback * htmlCallback) +{ + return htmlForAbstractMessage(folder, message, dataCallback, htmlCallback, NULL, NULL); +} + +Array * HTMLRenderer::attachmentsForMessage(AbstractMessage * message) +{ + Array * attachments = Array::array(); + HTMLRendererIMAPCallback * dataCallback = new HTMLRendererIMAPDummyCallback(); + String * ignoredResult = htmlForAbstractMessage(NULL, message, dataCallback, NULL, attachments, NULL); + delete dataCallback; + dataCallback = NULL; + (void) ignoredResult; // remove unused variable warning. + return attachments; +} + +Array * HTMLRenderer::htmlInlineAttachmentsForMessage(AbstractMessage * message) +{ + Array * htmlInlineAttachments = Array::array(); + HTMLRendererIMAPCallback * dataCallback = new HTMLRendererIMAPDummyCallback(); + String * ignoredResult = htmlForAbstractMessage(NULL, message, dataCallback, NULL, NULL, htmlInlineAttachments); + delete dataCallback; + dataCallback = NULL; + (void) ignoredResult; // remove unused variable warning. + return htmlInlineAttachments; +} + +Array * HTMLRenderer::requiredPartsForRendering(AbstractMessage * message) +{ + HTMLRendererIMAPDummyCallback * dataCallback = new HTMLRendererIMAPDummyCallback(); + String * ignoredResult = htmlForAbstractMessage(NULL, message, dataCallback, NULL, NULL, NULL); + + Array *requiredParts = dataCallback->requiredParts(); + + delete dataCallback; + dataCallback = NULL; + (void) ignoredResult; // remove unused variable warning. + return requiredParts; +} diff --git a/src/core/renderer/MCHTMLRendererCallback.cc b/src/core/renderer/MCHTMLRendererCallback.cc deleted file mode 100644 index edaf7e92..00000000 --- a/src/core/renderer/MCHTMLRendererCallback.cc +++ /dev/null @@ -1,283 +0,0 @@ -// -// MCHTMLRendererCallback.cpp -// mailcore2 -// -// Created by DINH Viêt Hoà on 2/2/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCHTMLRendererCallback.h" - -#include "MCAddressDisplay.h" -#include "MCDateFormatter.h" -#include "MCSizeFormatter.h" -#include "MCAttachment.h" - -using namespace mailcore; - -mailcore::HashMap * HTMLRendererTemplateCallback::templateValuesForHeader(mailcore::MessageHeader * header) -{ - mailcore::HashMap * result = mailcore::HashMap::hashMap(); - - if (header->from() != NULL) { - result->setObjectForKey(MCSTR("HASFROM"), mailcore::HashMap::hashMap()); - result->setObjectForKey(MCSTR("FROM"), mailcore::AddressDisplay::displayStringForAddress(header->from())->htmlEncodedString()); - result->setObjectForKey(MCSTR("SHORTFROM"), mailcore::AddressDisplay::shortDisplayStringForAddress(header->from())->htmlEncodedString()); - result->setObjectForKey(MCSTR("VERYSHORTFROM"), mailcore::AddressDisplay::veryShortDisplayStringForAddress(header->from())->htmlEncodedString()); - } - else { - result->setObjectForKey(MCSTR("NOFROM"), mailcore::HashMap::hashMap()); - } - - if ((header->to() != NULL) && (header->to()->count() > 0)) { - result->setObjectForKey(MCSTR("HASTO"), mailcore::HashMap::hashMap()); - result->setObjectForKey(MCSTR("TO"), mailcore::AddressDisplay::displayStringForAddresses(header->to())->htmlEncodedString()); - result->setObjectForKey(MCSTR("SHORTTO"), mailcore::AddressDisplay::shortDisplayStringForAddresses(header->to())->htmlEncodedString()); - result->setObjectForKey(MCSTR("VERYSHORTTO"), mailcore::AddressDisplay::veryShortDisplayStringForAddresses(header->to())->htmlEncodedString()); - } - else { - result->setObjectForKey(MCSTR("NOTO"), mailcore::HashMap::hashMap()); - } - - if ((header->cc() != NULL) && (header->cc()->count() > 0)) { - result->setObjectForKey(MCSTR("HASCC"), mailcore::HashMap::hashMap()); - result->setObjectForKey(MCSTR("CC"), mailcore::AddressDisplay::displayStringForAddresses(header->cc())->htmlEncodedString()); - result->setObjectForKey(MCSTR("SHORTCC"), mailcore::AddressDisplay::shortDisplayStringForAddresses(header->cc())->htmlEncodedString()); - result->setObjectForKey(MCSTR("VERYSHORTCC"), mailcore::AddressDisplay::veryShortDisplayStringForAddresses(header->cc())->htmlEncodedString()); - } - else { - result->setObjectForKey(MCSTR("NOCC"), mailcore::HashMap::hashMap()); - } - - if ((header->bcc() != NULL) && (header->bcc()->count() > 0)) { - result->setObjectForKey(MCSTR("HASBCC"), mailcore::HashMap::hashMap()); - result->setObjectForKey(MCSTR("BCC"), mailcore::AddressDisplay::displayStringForAddresses(header->bcc())->htmlEncodedString()); - result->setObjectForKey(MCSTR("SHORTBCC"), mailcore::AddressDisplay::shortDisplayStringForAddresses(header->bcc())->htmlEncodedString()); - result->setObjectForKey(MCSTR("VERYSHORTBCC"), mailcore::AddressDisplay::veryShortDisplayStringForAddresses(header->bcc())->htmlEncodedString()); - } - else { - result->setObjectForKey(MCSTR("NOBCC"), mailcore::HashMap::hashMap()); - } - - mailcore::Array * recipient = new mailcore::Array(); - recipient->addObjectsFromArray(header->to()); - recipient->addObjectsFromArray(header->cc()); - recipient->addObjectsFromArray(header->bcc()); - - if (recipient->count() > 0) { - result->setObjectForKey(MCSTR("HASRECIPIENT"), mailcore::HashMap::hashMap()); - result->setObjectForKey(MCSTR("RECIPIENT"), mailcore::AddressDisplay::displayStringForAddresses(recipient)->htmlEncodedString()); - result->setObjectForKey(MCSTR("SHORTRECIPIENT"), mailcore::AddressDisplay::shortDisplayStringForAddresses(recipient)->htmlEncodedString()); - result->setObjectForKey(MCSTR("VERYSHORTRECIPIENT"), mailcore::AddressDisplay::veryShortDisplayStringForAddresses(recipient)->htmlEncodedString()); - } - else { - result->setObjectForKey(MCSTR("NORECIPIENT"), mailcore::HashMap::hashMap()); - } - recipient->release(); - - if ((header->replyTo() != NULL) && (header->replyTo()->count() > 0)) { - result->setObjectForKey(MCSTR("HASREPLYTO"), mailcore::HashMap::hashMap()); - result->setObjectForKey(MCSTR("REPLYTO"), mailcore::AddressDisplay::displayStringForAddresses(header->replyTo())->htmlEncodedString()); - result->setObjectForKey(MCSTR("SHORTREPLYTO"), mailcore::AddressDisplay::shortDisplayStringForAddresses(header->replyTo())->htmlEncodedString()); - result->setObjectForKey(MCSTR("VERYSHORTREPLYTO"), mailcore::AddressDisplay::veryShortDisplayStringForAddresses(header->replyTo())->htmlEncodedString()); - } - else { - result->setObjectForKey(MCSTR("NOREPLYTO"), mailcore::HashMap::hashMap()); - } - - if ((header->subject() != NULL) && (header->subject()->length() > 0)) { - result->setObjectForKey(MCSTR("EXTRACTEDSUBJECT"), header->partialExtractedSubject()->htmlEncodedString()); - result->setObjectForKey(MCSTR("SUBJECT"), header->subject()->htmlEncodedString()); - result->setObjectForKey(MCSTR("HASSUBJECT"), mailcore::HashMap::hashMap()); - } - else { - result->setObjectForKey(MCSTR("NOSUBJECT"), mailcore::HashMap::hashMap()); - } - - mailcore::String * dateString; - static mailcore::DateFormatter * fullFormatter = NULL; - if (fullFormatter == NULL) { - fullFormatter = new mailcore::DateFormatter(); - fullFormatter->setDateStyle(mailcore::DateFormatStyleFull); - fullFormatter->setTimeStyle(mailcore::DateFormatStyleFull); - } - dateString = fullFormatter->stringFromDate(header->date()); - if (dateString != NULL) { - result->setObjectForKey(MCSTR("FULLDATE"), dateString->htmlEncodedString()); - } - static mailcore::DateFormatter * longFormatter = NULL; - if (longFormatter == NULL) { - longFormatter = new mailcore::DateFormatter(); - longFormatter->setDateStyle(mailcore::DateFormatStyleLong); - longFormatter->setTimeStyle(mailcore::DateFormatStyleLong); - } - dateString = longFormatter->stringFromDate(header->date()); - if (dateString != NULL) { - result->setObjectForKey(MCSTR("LONGDATE"), dateString->htmlEncodedString()); - } - static mailcore::DateFormatter * mediumFormatter = NULL; - if (mediumFormatter == NULL) { - mediumFormatter = new mailcore::DateFormatter(); - mediumFormatter->setDateStyle(mailcore::DateFormatStyleMedium); - mediumFormatter->setTimeStyle(mailcore::DateFormatStyleMedium); - } - dateString = mediumFormatter->stringFromDate(header->date()); - if (dateString != NULL) { - result->setObjectForKey(MCSTR("MEDIUMDATE"), dateString->htmlEncodedString()); - } - static mailcore::DateFormatter * shortFormatter = NULL; - if (shortFormatter == NULL) { - shortFormatter = new mailcore::DateFormatter(); - shortFormatter->setDateStyle(mailcore::DateFormatStyleShort); - shortFormatter->setTimeStyle(mailcore::DateFormatStyleShort); - } - dateString = shortFormatter->stringFromDate(header->date()); - if (dateString != NULL) { - result->setObjectForKey(MCSTR("SHORTDATE"), dateString->htmlEncodedString()); - } - - return result; -} - -mailcore::HashMap * HTMLRendererTemplateCallback::templateValuesForPart(mailcore::AbstractPart * part) -{ - mailcore::HashMap * result = mailcore::HashMap::hashMap(); - mailcore::String * filename = NULL; - - if (part->filename() != NULL) { - filename = part->filename()->lastPathComponent(); - } - - if (filename != NULL) { - result->setObjectForKey(MCSTR("FILENAME"), filename->htmlEncodedString()); - result->setObjectForKey(MCSTR("HASFILENAME"), mailcore::HashMap::hashMap()); - } - else { - result->setObjectForKey(MCSTR("NOFILENAME"), mailcore::HashMap::hashMap()); - } - - if (part->className()->isEqual(MCSTR("mailcore::IMAPPart"))) { - mailcore::IMAPPart * imapPart = (mailcore::IMAPPart *) part; - mailcore::String * value = mailcore::SizeFormatter::stringWithSize(imapPart->decodedSize()); - result->setObjectForKey(MCSTR("SIZE"), value); - result->setObjectForKey(MCSTR("HASSIZE"), mailcore::HashMap::hashMap()); - } - else if (part->className()->isEqual(MCSTR("mailcore::Attachment"))) { - mailcore::Attachment * attachment = (mailcore::Attachment *) part; - mailcore::String * value = mailcore::SizeFormatter::stringWithSize(attachment->data()->length()); - result->setObjectForKey(MCSTR("SIZE"), value); - result->setObjectForKey(MCSTR("HASSIZE"), mailcore::HashMap::hashMap()); - } - else { - result->setObjectForKey(MCSTR("NOSIZE"), mailcore::HashMap::hashMap()); - } - - if (part->contentID() != NULL) { - result->setObjectForKey(MCSTR("CONTENTID"), part->contentID()); - } - if (part->uniqueID() != NULL) { - result->setObjectForKey(MCSTR("UNIQUEID"), part->uniqueID()); - } - - return result; -} - -mailcore::String * HTMLRendererTemplateCallback::templateForMainHeader(MessageHeader * header) -{ - return MCSTR("
\ - {{#HASFROM}}\ -
From: {{FROM}}
\ - {{/HASFROM}}\ - {{#HASTO}}\ -
To: {{TO}}
\ - {{/HASTO}}\ - {{#HASCC}}\ -
Cc: {{CC}}
\ - {{/HASCC}}\ - {{#HASBCC}}\ -
Bcc: {{BCC}}
\ - {{/HASBCC}}\ - {{#NORECIPIENT}}\ -
To: Undisclosed recipient
\ - {{/NORECIPIENT}}\ - {{#HASSUBJECT}}\ -
Subject: {{EXTRACTEDSUBJECT}}
\ - {{/HASSUBJECT}}\ - {{#NOSUBJECT}}\ -
Subject: No Subject
\ - {{/NOSUBJECT}}\ -
Date: {{LONGDATE}}
\ -
"); -} - -mailcore::String * HTMLRendererTemplateCallback::templateForEmbeddedMessageHeader(MessageHeader * header) -{ - return templateForMainHeader(header); -} - -mailcore::String * HTMLRendererTemplateCallback::templateForImage(AbstractPart * part) -{ - return MCSTR(""); -} - -mailcore::String * HTMLRendererTemplateCallback::templateForAttachment(AbstractPart * part) -{ - return MCSTR("{{#HASSIZE}}\ - {{#HASFILENAME}}\ -
- {{FILENAME}}, {{SIZE}}
\ - {{/HASFILENAME}}\ - {{#NOFILENAME}}\ -
- Untitled, {{SIZE}}
\ - {{/NOFILENAME}}\ - {{/HASSIZE}}\ - {{#NOSIZE}}\ - {{#HASFILENAME}}\ -
- {{FILENAME}}
\ - {{/HASFILENAME}}\ - {{#NOFILENAME}}\ -
- Untitled
\ - {{/NOFILENAME}}\ - {{/NOSIZE}}\ - "); -} - -mailcore::String * HTMLRendererTemplateCallback::templateForMessage(AbstractMessage * message) -{ - return MCSTR("
{{HEADER}}
{{BODY}}
"); -} - - -mailcore::String * HTMLRendererTemplateCallback::templateForEmbeddedMessage(AbstractMessagePart * part) -{ - return MCSTR("
{{HEADER}}
{{BODY}}
"); -} - -mailcore::String * HTMLRendererTemplateCallback::templateForAttachmentSeparator() -{ - return MCSTR("
"); -} - -mailcore::String * HTMLRendererTemplateCallback::filterHTMLForMessage(mailcore::String * html) -{ - return html; -} - -mailcore::String * HTMLRendererTemplateCallback::cleanHTMLForPart(mailcore::String * html) -{ - return html->cleanedHTMLString(); -} - -mailcore::String * HTMLRendererTemplateCallback::filterHTMLForPart(mailcore::String * html) -{ - return html; -} - -bool HTMLRendererTemplateCallback::canPreviewPart(AbstractPart * part) -{ - return false; -} - -bool HTMLRendererTemplateCallback::shouldShowPart(AbstractPart * part) -{ - return true; -} diff --git a/src/core/renderer/MCHTMLRendererCallback.cpp b/src/core/renderer/MCHTMLRendererCallback.cpp new file mode 100644 index 00000000..edaf7e92 --- /dev/null +++ b/src/core/renderer/MCHTMLRendererCallback.cpp @@ -0,0 +1,283 @@ +// +// MCHTMLRendererCallback.cpp +// mailcore2 +// +// Created by DINH Viêt Hoà on 2/2/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCHTMLRendererCallback.h" + +#include "MCAddressDisplay.h" +#include "MCDateFormatter.h" +#include "MCSizeFormatter.h" +#include "MCAttachment.h" + +using namespace mailcore; + +mailcore::HashMap * HTMLRendererTemplateCallback::templateValuesForHeader(mailcore::MessageHeader * header) +{ + mailcore::HashMap * result = mailcore::HashMap::hashMap(); + + if (header->from() != NULL) { + result->setObjectForKey(MCSTR("HASFROM"), mailcore::HashMap::hashMap()); + result->setObjectForKey(MCSTR("FROM"), mailcore::AddressDisplay::displayStringForAddress(header->from())->htmlEncodedString()); + result->setObjectForKey(MCSTR("SHORTFROM"), mailcore::AddressDisplay::shortDisplayStringForAddress(header->from())->htmlEncodedString()); + result->setObjectForKey(MCSTR("VERYSHORTFROM"), mailcore::AddressDisplay::veryShortDisplayStringForAddress(header->from())->htmlEncodedString()); + } + else { + result->setObjectForKey(MCSTR("NOFROM"), mailcore::HashMap::hashMap()); + } + + if ((header->to() != NULL) && (header->to()->count() > 0)) { + result->setObjectForKey(MCSTR("HASTO"), mailcore::HashMap::hashMap()); + result->setObjectForKey(MCSTR("TO"), mailcore::AddressDisplay::displayStringForAddresses(header->to())->htmlEncodedString()); + result->setObjectForKey(MCSTR("SHORTTO"), mailcore::AddressDisplay::shortDisplayStringForAddresses(header->to())->htmlEncodedString()); + result->setObjectForKey(MCSTR("VERYSHORTTO"), mailcore::AddressDisplay::veryShortDisplayStringForAddresses(header->to())->htmlEncodedString()); + } + else { + result->setObjectForKey(MCSTR("NOTO"), mailcore::HashMap::hashMap()); + } + + if ((header->cc() != NULL) && (header->cc()->count() > 0)) { + result->setObjectForKey(MCSTR("HASCC"), mailcore::HashMap::hashMap()); + result->setObjectForKey(MCSTR("CC"), mailcore::AddressDisplay::displayStringForAddresses(header->cc())->htmlEncodedString()); + result->setObjectForKey(MCSTR("SHORTCC"), mailcore::AddressDisplay::shortDisplayStringForAddresses(header->cc())->htmlEncodedString()); + result->setObjectForKey(MCSTR("VERYSHORTCC"), mailcore::AddressDisplay::veryShortDisplayStringForAddresses(header->cc())->htmlEncodedString()); + } + else { + result->setObjectForKey(MCSTR("NOCC"), mailcore::HashMap::hashMap()); + } + + if ((header->bcc() != NULL) && (header->bcc()->count() > 0)) { + result->setObjectForKey(MCSTR("HASBCC"), mailcore::HashMap::hashMap()); + result->setObjectForKey(MCSTR("BCC"), mailcore::AddressDisplay::displayStringForAddresses(header->bcc())->htmlEncodedString()); + result->setObjectForKey(MCSTR("SHORTBCC"), mailcore::AddressDisplay::shortDisplayStringForAddresses(header->bcc())->htmlEncodedString()); + result->setObjectForKey(MCSTR("VERYSHORTBCC"), mailcore::AddressDisplay::veryShortDisplayStringForAddresses(header->bcc())->htmlEncodedString()); + } + else { + result->setObjectForKey(MCSTR("NOBCC"), mailcore::HashMap::hashMap()); + } + + mailcore::Array * recipient = new mailcore::Array(); + recipient->addObjectsFromArray(header->to()); + recipient->addObjectsFromArray(header->cc()); + recipient->addObjectsFromArray(header->bcc()); + + if (recipient->count() > 0) { + result->setObjectForKey(MCSTR("HASRECIPIENT"), mailcore::HashMap::hashMap()); + result->setObjectForKey(MCSTR("RECIPIENT"), mailcore::AddressDisplay::displayStringForAddresses(recipient)->htmlEncodedString()); + result->setObjectForKey(MCSTR("SHORTRECIPIENT"), mailcore::AddressDisplay::shortDisplayStringForAddresses(recipient)->htmlEncodedString()); + result->setObjectForKey(MCSTR("VERYSHORTRECIPIENT"), mailcore::AddressDisplay::veryShortDisplayStringForAddresses(recipient)->htmlEncodedString()); + } + else { + result->setObjectForKey(MCSTR("NORECIPIENT"), mailcore::HashMap::hashMap()); + } + recipient->release(); + + if ((header->replyTo() != NULL) && (header->replyTo()->count() > 0)) { + result->setObjectForKey(MCSTR("HASREPLYTO"), mailcore::HashMap::hashMap()); + result->setObjectForKey(MCSTR("REPLYTO"), mailcore::AddressDisplay::displayStringForAddresses(header->replyTo())->htmlEncodedString()); + result->setObjectForKey(MCSTR("SHORTREPLYTO"), mailcore::AddressDisplay::shortDisplayStringForAddresses(header->replyTo())->htmlEncodedString()); + result->setObjectForKey(MCSTR("VERYSHORTREPLYTO"), mailcore::AddressDisplay::veryShortDisplayStringForAddresses(header->replyTo())->htmlEncodedString()); + } + else { + result->setObjectForKey(MCSTR("NOREPLYTO"), mailcore::HashMap::hashMap()); + } + + if ((header->subject() != NULL) && (header->subject()->length() > 0)) { + result->setObjectForKey(MCSTR("EXTRACTEDSUBJECT"), header->partialExtractedSubject()->htmlEncodedString()); + result->setObjectForKey(MCSTR("SUBJECT"), header->subject()->htmlEncodedString()); + result->setObjectForKey(MCSTR("HASSUBJECT"), mailcore::HashMap::hashMap()); + } + else { + result->setObjectForKey(MCSTR("NOSUBJECT"), mailcore::HashMap::hashMap()); + } + + mailcore::String * dateString; + static mailcore::DateFormatter * fullFormatter = NULL; + if (fullFormatter == NULL) { + fullFormatter = new mailcore::DateFormatter(); + fullFormatter->setDateStyle(mailcore::DateFormatStyleFull); + fullFormatter->setTimeStyle(mailcore::DateFormatStyleFull); + } + dateString = fullFormatter->stringFromDate(header->date()); + if (dateString != NULL) { + result->setObjectForKey(MCSTR("FULLDATE"), dateString->htmlEncodedString()); + } + static mailcore::DateFormatter * longFormatter = NULL; + if (longFormatter == NULL) { + longFormatter = new mailcore::DateFormatter(); + longFormatter->setDateStyle(mailcore::DateFormatStyleLong); + longFormatter->setTimeStyle(mailcore::DateFormatStyleLong); + } + dateString = longFormatter->stringFromDate(header->date()); + if (dateString != NULL) { + result->setObjectForKey(MCSTR("LONGDATE"), dateString->htmlEncodedString()); + } + static mailcore::DateFormatter * mediumFormatter = NULL; + if (mediumFormatter == NULL) { + mediumFormatter = new mailcore::DateFormatter(); + mediumFormatter->setDateStyle(mailcore::DateFormatStyleMedium); + mediumFormatter->setTimeStyle(mailcore::DateFormatStyleMedium); + } + dateString = mediumFormatter->stringFromDate(header->date()); + if (dateString != NULL) { + result->setObjectForKey(MCSTR("MEDIUMDATE"), dateString->htmlEncodedString()); + } + static mailcore::DateFormatter * shortFormatter = NULL; + if (shortFormatter == NULL) { + shortFormatter = new mailcore::DateFormatter(); + shortFormatter->setDateStyle(mailcore::DateFormatStyleShort); + shortFormatter->setTimeStyle(mailcore::DateFormatStyleShort); + } + dateString = shortFormatter->stringFromDate(header->date()); + if (dateString != NULL) { + result->setObjectForKey(MCSTR("SHORTDATE"), dateString->htmlEncodedString()); + } + + return result; +} + +mailcore::HashMap * HTMLRendererTemplateCallback::templateValuesForPart(mailcore::AbstractPart * part) +{ + mailcore::HashMap * result = mailcore::HashMap::hashMap(); + mailcore::String * filename = NULL; + + if (part->filename() != NULL) { + filename = part->filename()->lastPathComponent(); + } + + if (filename != NULL) { + result->setObjectForKey(MCSTR("FILENAME"), filename->htmlEncodedString()); + result->setObjectForKey(MCSTR("HASFILENAME"), mailcore::HashMap::hashMap()); + } + else { + result->setObjectForKey(MCSTR("NOFILENAME"), mailcore::HashMap::hashMap()); + } + + if (part->className()->isEqual(MCSTR("mailcore::IMAPPart"))) { + mailcore::IMAPPart * imapPart = (mailcore::IMAPPart *) part; + mailcore::String * value = mailcore::SizeFormatter::stringWithSize(imapPart->decodedSize()); + result->setObjectForKey(MCSTR("SIZE"), value); + result->setObjectForKey(MCSTR("HASSIZE"), mailcore::HashMap::hashMap()); + } + else if (part->className()->isEqual(MCSTR("mailcore::Attachment"))) { + mailcore::Attachment * attachment = (mailcore::Attachment *) part; + mailcore::String * value = mailcore::SizeFormatter::stringWithSize(attachment->data()->length()); + result->setObjectForKey(MCSTR("SIZE"), value); + result->setObjectForKey(MCSTR("HASSIZE"), mailcore::HashMap::hashMap()); + } + else { + result->setObjectForKey(MCSTR("NOSIZE"), mailcore::HashMap::hashMap()); + } + + if (part->contentID() != NULL) { + result->setObjectForKey(MCSTR("CONTENTID"), part->contentID()); + } + if (part->uniqueID() != NULL) { + result->setObjectForKey(MCSTR("UNIQUEID"), part->uniqueID()); + } + + return result; +} + +mailcore::String * HTMLRendererTemplateCallback::templateForMainHeader(MessageHeader * header) +{ + return MCSTR("
\ + {{#HASFROM}}\ +
From: {{FROM}}
\ + {{/HASFROM}}\ + {{#HASTO}}\ +
To: {{TO}}
\ + {{/HASTO}}\ + {{#HASCC}}\ +
Cc: {{CC}}
\ + {{/HASCC}}\ + {{#HASBCC}}\ +
Bcc: {{BCC}}
\ + {{/HASBCC}}\ + {{#NORECIPIENT}}\ +
To: Undisclosed recipient
\ + {{/NORECIPIENT}}\ + {{#HASSUBJECT}}\ +
Subject: {{EXTRACTEDSUBJECT}}
\ + {{/HASSUBJECT}}\ + {{#NOSUBJECT}}\ +
Subject: No Subject
\ + {{/NOSUBJECT}}\ +
Date: {{LONGDATE}}
\ +
"); +} + +mailcore::String * HTMLRendererTemplateCallback::templateForEmbeddedMessageHeader(MessageHeader * header) +{ + return templateForMainHeader(header); +} + +mailcore::String * HTMLRendererTemplateCallback::templateForImage(AbstractPart * part) +{ + return MCSTR(""); +} + +mailcore::String * HTMLRendererTemplateCallback::templateForAttachment(AbstractPart * part) +{ + return MCSTR("{{#HASSIZE}}\ + {{#HASFILENAME}}\ +
- {{FILENAME}}, {{SIZE}}
\ + {{/HASFILENAME}}\ + {{#NOFILENAME}}\ +
- Untitled, {{SIZE}}
\ + {{/NOFILENAME}}\ + {{/HASSIZE}}\ + {{#NOSIZE}}\ + {{#HASFILENAME}}\ +
- {{FILENAME}}
\ + {{/HASFILENAME}}\ + {{#NOFILENAME}}\ +
- Untitled
\ + {{/NOFILENAME}}\ + {{/NOSIZE}}\ + "); +} + +mailcore::String * HTMLRendererTemplateCallback::templateForMessage(AbstractMessage * message) +{ + return MCSTR("
{{HEADER}}
{{BODY}}
"); +} + + +mailcore::String * HTMLRendererTemplateCallback::templateForEmbeddedMessage(AbstractMessagePart * part) +{ + return MCSTR("
{{HEADER}}
{{BODY}}
"); +} + +mailcore::String * HTMLRendererTemplateCallback::templateForAttachmentSeparator() +{ + return MCSTR("
"); +} + +mailcore::String * HTMLRendererTemplateCallback::filterHTMLForMessage(mailcore::String * html) +{ + return html; +} + +mailcore::String * HTMLRendererTemplateCallback::cleanHTMLForPart(mailcore::String * html) +{ + return html->cleanedHTMLString(); +} + +mailcore::String * HTMLRendererTemplateCallback::filterHTMLForPart(mailcore::String * html) +{ + return html; +} + +bool HTMLRendererTemplateCallback::canPreviewPart(AbstractPart * part) +{ + return false; +} + +bool HTMLRendererTemplateCallback::shouldShowPart(AbstractPart * part) +{ + return true; +} diff --git a/src/core/renderer/MCHTMLRendererIMAPDataCallback.cc b/src/core/renderer/MCHTMLRendererIMAPDataCallback.cc deleted file mode 100644 index d438ef85..00000000 --- a/src/core/renderer/MCHTMLRendererIMAPDataCallback.cc +++ /dev/null @@ -1,28 +0,0 @@ -// -// MCHTMLRendererIMAPDataCallback.cc -// mailcore2 -// -// Created by Paul Young on 06/07/2013. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCHTMLRendererIMAPDataCallback.h" - -using namespace mailcore; - -HTMLRendererIMAPDataCallback::HTMLRendererIMAPDataCallback(IMAPSession * session, uint32_t uid) -{ - mSession = session; - mUid = uid; - mError = ErrorNone; -} - -Data * HTMLRendererIMAPDataCallback::dataForIMAPPart(String * folder, IMAPPart * part) -{ - return mSession->fetchMessageAttachmentByUID(folder, mUid, part->partID(), part->encoding(), NULL, &mError); -} - -ErrorCode HTMLRendererIMAPDataCallback::error() -{ - return mError; -} \ No newline at end of file diff --git a/src/core/renderer/MCHTMLRendererIMAPDataCallback.cpp b/src/core/renderer/MCHTMLRendererIMAPDataCallback.cpp new file mode 100644 index 00000000..d438ef85 --- /dev/null +++ b/src/core/renderer/MCHTMLRendererIMAPDataCallback.cpp @@ -0,0 +1,28 @@ +// +// MCHTMLRendererIMAPDataCallback.cc +// mailcore2 +// +// Created by Paul Young on 06/07/2013. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCHTMLRendererIMAPDataCallback.h" + +using namespace mailcore; + +HTMLRendererIMAPDataCallback::HTMLRendererIMAPDataCallback(IMAPSession * session, uint32_t uid) +{ + mSession = session; + mUid = uid; + mError = ErrorNone; +} + +Data * HTMLRendererIMAPDataCallback::dataForIMAPPart(String * folder, IMAPPart * part) +{ + return mSession->fetchMessageAttachmentByUID(folder, mUid, part->partID(), part->encoding(), NULL, &mError); +} + +ErrorCode HTMLRendererIMAPDataCallback::error() +{ + return mError; +} \ No newline at end of file diff --git a/src/core/renderer/MCSizeFormatter.cc b/src/core/renderer/MCSizeFormatter.cc deleted file mode 100644 index f0823075..00000000 --- a/src/core/renderer/MCSizeFormatter.cc +++ /dev/null @@ -1,43 +0,0 @@ -// -// MCSizeFormatter.cpp -// testUI -// -// Created by DINH Viêt Hoà on 1/29/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCSizeFormatter.h" - -#include - -using namespace mailcore; - -String * SizeFormatter::stringWithSize(unsigned int size) -{ - double divider; - String * unit; - - if (size >= 1024 * 1024 * 1024) { - divider = 1024 * 1024 * 1024; - unit = MCLOCALIZEDSTRING(MCSTR("GB")); - } - else if (size >= 1024 * 1024) { - divider = 1024 * 1024; - unit = MCLOCALIZEDSTRING(MCSTR("MB")); - } - else if (size >= 1024) { - divider = 1024; - unit = MCLOCALIZEDSTRING(MCSTR("KB")); - } - else { - divider = 1; - unit = MCLOCALIZEDSTRING(MCSTR("bytes")); - } - - if ((size / divider) - round(size / divider) < 0.1) { - return String::stringWithUTF8Format("%.0f %s", size / divider, unit->UTF8Characters()); - } - else { - return String::stringWithUTF8Format("%.1f %s", size / divider, unit->UTF8Characters()); - } -} diff --git a/src/core/renderer/MCSizeFormatter.cpp b/src/core/renderer/MCSizeFormatter.cpp new file mode 100644 index 00000000..f0823075 --- /dev/null +++ b/src/core/renderer/MCSizeFormatter.cpp @@ -0,0 +1,43 @@ +// +// MCSizeFormatter.cpp +// testUI +// +// Created by DINH Viêt Hoà on 1/29/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCSizeFormatter.h" + +#include + +using namespace mailcore; + +String * SizeFormatter::stringWithSize(unsigned int size) +{ + double divider; + String * unit; + + if (size >= 1024 * 1024 * 1024) { + divider = 1024 * 1024 * 1024; + unit = MCLOCALIZEDSTRING(MCSTR("GB")); + } + else if (size >= 1024 * 1024) { + divider = 1024 * 1024; + unit = MCLOCALIZEDSTRING(MCSTR("MB")); + } + else if (size >= 1024) { + divider = 1024; + unit = MCLOCALIZEDSTRING(MCSTR("KB")); + } + else { + divider = 1; + unit = MCLOCALIZEDSTRING(MCSTR("bytes")); + } + + if ((size / divider) - round(size / divider) < 0.1) { + return String::stringWithUTF8Format("%.0f %s", size / divider, unit->UTF8Characters()); + } + else { + return String::stringWithUTF8Format("%.1f %s", size / divider, unit->UTF8Characters()); + } +} diff --git a/src/core/rfc822/MCAttachment.cc b/src/core/rfc822/MCAttachment.cc deleted file mode 100644 index cbc66a39..00000000 --- a/src/core/rfc822/MCAttachment.cc +++ /dev/null @@ -1,607 +0,0 @@ -#include "MCWin32.h" // should be included first. - -#include "MCAttachment.h" - -#include "MCMultipart.h" -#include "MCMessagePart.h" -#include "MCMessageHeader.h" -#include "MCMessageConstants.h" -#include "MCLog.h" -#include "MCZip.h" - -#include -#include -#ifndef _MSC_VER -#include -#endif -#include -#include - -using namespace mailcore; - -static char * findBlank(const char * str) -{ - char * p = (char *) str; - while (!((* p == ' ') || (* p == '\t'))) { - if (* p == 0) - return NULL; - p ++; - } - return p; -} - -HashMap * Attachment::readMimeTypesFile(String * filename) -{ - HashMap * result = HashMap::hashMap(); - - char line[512]; - FILE * f = fopen(filename->fileSystemRepresentation(), "r"); - if (f == NULL) { - return result; - } - - while (fgets(line, sizeof(line), f)) { - char * p; - String * mimeType; - - if (line[0] == '#') { - continue; - } - - while ((p = strchr(line, '\r')) != NULL) { - * p = 0; - } - while ((p = strchr(line, '\n')) != NULL) { - * p = 0; - } - - p = findBlank(line); - if (p == NULL) { - continue; - } - - * p = 0; - p ++; - mimeType = String::stringWithUTF8Characters(line); - - while (1) { - while ((* p == ' ') || (* p == '\t')) { - p ++; - } - - char * ext_end = findBlank(p); - if (ext_end == NULL) { - String * ext = String::stringWithUTF8Characters(p); - result->setObjectForKey(ext, mimeType); - break; - } - else { - * ext_end = 0; - String * ext = String::stringWithUTF8Characters(p); - result->setObjectForKey(ext, mimeType); - p = ext_end + 1; - } - } - } - - fclose(f); - - return result; -} - -String * Attachment::mimeTypeForFilename(String * filename) -{ - if (filename == NULL) { - return NULL; - } - static HashMap * mimeTypes = NULL; - static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; - pthread_mutex_lock(&lock); - if (mimeTypes == NULL) { - mimeTypes = readMimeTypesFile(MCSTR("/etc/apache2/mime.types")); - mimeTypes->retain(); - } - pthread_mutex_unlock(&lock); - - String * ext; - String * result; - - ext = filename->pathExtension()->lowercaseString(); - result = (String *) mimeTypes->objectForKey(ext); - if (result != NULL) - return result; - - if (ext->isEqual(MCSTR("jpg"))) { - return MCSTR("image/jpeg"); - } - else if (ext->isEqual(MCSTR("jpeg"))) { - return MCSTR("image/jpeg"); - } - else if (ext->isEqual(MCSTR("png"))) { - return MCSTR("image/png"); - } - else if (ext->isEqual(MCSTR("gif"))) { - return MCSTR("image/gif"); - } - else if (ext->isEqual(MCSTR("html"))) { - return MCSTR("text/html"); - } - else if (ext->isEqual(MCSTR("txt"))) { - return MCSTR("text/plain"); - } - return NULL; -} - -Attachment * Attachment::attachmentWithContentsOfFile(String * filename) -{ - if (filename == NULL) { - return attachmentWithData(NULL, Data::data()); - } - - const char * cPath = filename->fileSystemRepresentation(); - struct stat statinfo; - int r; - - r = stat(cPath, &statinfo); - if (r < 0) { - return attachmentWithData(filename, Data::data()); - } - - if (S_ISDIR(statinfo.st_mode)) { - String * zipFilename = CreateTemporaryZipFileFromFolder(filename); - if (zipFilename == NULL) { - return NULL; - } - Attachment * result = attachmentWithContentsOfFile(zipFilename); - RemoveTemporaryZipFile(zipFilename); - return result; - } - else { - Data * data = Data::dataWithContentsOfFile(filename); - return attachmentWithData(filename, data); - } -} - -Attachment * Attachment::attachmentWithData(String * filename, Data * data) -{ - Attachment * attachment; - String * mimeType; - - attachment = new Attachment(); - mimeType = Attachment::mimeTypeForFilename(filename); - if (mimeType != NULL) { - attachment->setMimeType(mimeType); - } - if (filename != NULL) { - attachment->setFilename(filename->lastPathComponent()); - } - attachment->setData(data); - - return (Attachment *) attachment->autorelease(); -} - -Attachment * Attachment::attachmentWithHTMLString(String * htmlString) -{ - Data * data; - Attachment * attachment; - - attachment = new Attachment(); - attachment->setInlineAttachment(true); - attachment->setMimeType(MCSTR("text/html")); - data = htmlString->dataUsingEncoding("utf-8"); - attachment->setData(data); - - return (Attachment *) attachment->autorelease(); -} - -Attachment * Attachment::attachmentWithRFC822Message(Data * messageData) -{ - Attachment * attachment; - - attachment = new Attachment(); - attachment->setMimeType(MCSTR("message/rfc822")); - attachment->setData(messageData); - - return (Attachment *) attachment->autorelease(); -} - -Attachment * Attachment::attachmentWithText(String * text) -{ - Data * data; - Attachment * attachment; - - attachment = new Attachment(); - attachment->setInlineAttachment(true); - attachment->setMimeType(MCSTR("text/plain")); - data = text->dataUsingEncoding("utf-8"); - attachment->setData(data); - - return (Attachment *) attachment->autorelease(); -} - -void Attachment::init() -{ - mData = NULL; - setMimeType(MCSTR("application/octet-stream")); -} - -Attachment::Attachment() -{ - init(); -} - -Attachment::Attachment(Attachment * other) : AbstractPart(other) -{ - init(); - MC_SAFE_REPLACE_RETAIN(Data, mData, other->mData); -} - -Attachment::~Attachment() -{ - MC_SAFE_RELEASE(mData); -} - -String * Attachment::description() -{ - String * result = String::string(); - result->appendUTF8Format("<%s:%p\n", className()->UTF8Characters(), this); - if (filename() != NULL) { - result->appendUTF8Format("filename: %s\n", filename()->UTF8Characters()); - } - if (mimeType() != NULL) { - result->appendUTF8Format("mime type: %s\n", mimeType()->UTF8Characters()); - } - if (charset() != NULL) { - result->appendUTF8Format("charset: %s\n", charset()->UTF8Characters()); - } - if (contentID() != NULL) { - result->appendUTF8Format("content-ID: %s\n", contentID()->UTF8Characters()); - } - if (contentLocation() != NULL) { - result->appendUTF8Format("content-location: %s\n", contentLocation()->UTF8Characters()); - } - result->appendUTF8Format("inline: %i\n", isInlineAttachment()); - if (mData != NULL) { - result->appendUTF8Format("data: %i bytes\n", mData->length()); - } - else { - result->appendUTF8Format("no data\n"); - } - result->appendUTF8Format(">"); - - return result; -} - -Object * Attachment::copy() -{ - return new Attachment(this); -} - -void Attachment::setData(Data * data) -{ - MC_SAFE_REPLACE_RETAIN(Data, mData, data); -} - -Data * Attachment::data() -{ - return mData; -} - -String * Attachment::decodedString() -{ - if (mData) { - return decodedStringForData(mData); - } - else { - return NULL; - } -} - -AbstractPart * Attachment::attachmentsWithMIME(struct mailmime * mime) -{ - return attachmentsWithMIMEWithMain(mime, true); -} - -void Attachment::fillMultipartSubAttachments(AbstractMultipart * multipart, struct mailmime * mime) -{ - switch (mime->mm_type) { - case MAILMIME_MULTIPLE: - { - clistiter * cur; - Array * subAttachments = Array::array(); - for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; cur != NULL ; cur = clist_next(cur)) { - struct mailmime * submime; - AbstractPart * subAttachment; - - submime = (struct mailmime *) clist_content(cur); - subAttachment = attachmentsWithMIMEWithMain(submime, false); - subAttachments->addObject(subAttachment); - } - - multipart->setParts(subAttachments); - break; - } - } -} - -AbstractPart * Attachment::attachmentsWithMIMEWithMain(struct mailmime * mime, bool isMain) -{ - switch (mime->mm_type) { - case MAILMIME_SINGLE: - { - Attachment * attachment; - attachment = attachmentWithSingleMIME(mime); - return attachment; - } - case MAILMIME_MULTIPLE: - { - if ((mime->mm_content_type != NULL) && (mime->mm_content_type->ct_subtype != NULL) && - (strcasecmp(mime->mm_content_type->ct_subtype, "alternative") == 0)) { - Multipart * attachment; - attachment = new Multipart(); - attachment->setPartType(PartTypeMultipartAlternative); - fillMultipartSubAttachments(attachment, mime); - return (Multipart *) attachment->autorelease(); - } - else if ((mime->mm_content_type != NULL) && (mime->mm_content_type->ct_subtype != NULL) && - (strcasecmp(mime->mm_content_type->ct_subtype, "related") == 0)) { - Multipart * attachment; - attachment = new Multipart(); - attachment->setPartType(PartTypeMultipartRelated); - fillMultipartSubAttachments(attachment, mime); - return (Multipart *) attachment->autorelease(); - } - else if ((mime->mm_content_type != NULL) && (mime->mm_content_type->ct_subtype != NULL) && - (strcasecmp(mime->mm_content_type->ct_subtype, "signed") == 0)) { - Multipart * attachment; - attachment = new Multipart(); - attachment->setPartType(PartTypeMultipartSigned); - fillMultipartSubAttachments(attachment, mime); - return (Multipart *) attachment->autorelease(); - } - else { - Multipart * attachment; - attachment = new Multipart(); - fillMultipartSubAttachments(attachment, mime); - return (Multipart *) attachment->autorelease(); - } - } - case MAILMIME_MESSAGE: - { - if (isMain) { - AbstractPart * attachment; - attachment = attachmentsWithMIMEWithMain(mime->mm_data.mm_message.mm_msg_mime, false); - return attachment; - } - else { - MessagePart * messagePart; - messagePart = attachmentWithMessageMIME(mime); - return messagePart; - } - } - } - - return NULL; -} - -Encoding Attachment::encodingForMIMEEncoding(struct mailmime_mechanism * mechanism, int defaultMimeEncoding) -{ - Encoding mimeEncoding = (Encoding) defaultMimeEncoding; - - if (mechanism != NULL) { - mimeEncoding = (Encoding) mechanism->enc_type; - } - - switch ((int) mimeEncoding) { - default: - case MAILMIME_MECHANISM_ERROR: - return EncodingOther; - case MAILMIME_MECHANISM_7BIT: - return Encoding7Bit; - case MAILMIME_MECHANISM_8BIT: - return Encoding8Bit; - case MAILMIME_MECHANISM_BINARY: - return EncodingBinary; - case MAILMIME_MECHANISM_QUOTED_PRINTABLE: - return EncodingQuotedPrintable; - case MAILMIME_MECHANISM_BASE64: - return EncodingBase64; - case MAILMIME_MECHANISM_TOKEN: - if (mechanism == NULL) - return Encoding8Bit; - if (mechanism->enc_token == NULL) - return Encoding8Bit; - - if (strcasecmp(mechanism->enc_token, "x-uuencode") == 0) { - return EncodingUUEncode; - } - else { - return EncodingOther; - } - } -} - -static const char * get_discrete_type(struct mailmime_discrete_type * discrete_type) -{ - switch (discrete_type->dt_type) { - case MAILMIME_DISCRETE_TYPE_TEXT: - return "text"; - - case MAILMIME_DISCRETE_TYPE_IMAGE: - return "image"; - - case MAILMIME_DISCRETE_TYPE_AUDIO: - return "audio"; - - case MAILMIME_DISCRETE_TYPE_VIDEO: - return "video"; - - case MAILMIME_DISCRETE_TYPE_APPLICATION: - return "application"; - - case MAILMIME_DISCRETE_TYPE_EXTENSION: - return discrete_type->dt_extension; - } - - return NULL; -} - -static const char * -get_composite_type(struct mailmime_composite_type * composite_type) -{ - switch (composite_type->ct_type) { - case MAILMIME_COMPOSITE_TYPE_MESSAGE: - return "message"; - - case MAILMIME_COMPOSITE_TYPE_MULTIPART: - return "multipart"; - - case MAILMIME_COMPOSITE_TYPE_EXTENSION: - return composite_type->ct_token; - } - - return NULL; -} - -static char * get_content_type_str(struct mailmime_content * content) -{ - const char * str; - char * result; - const char * subtype; - - if (content == NULL) { - return strdup("unknown/unknown"); - } - - str = "unknown"; - - switch (content->ct_type->tp_type) { - case MAILMIME_TYPE_DISCRETE_TYPE: - str = get_discrete_type(content->ct_type->tp_data.tp_discrete_type); - break; - - case MAILMIME_TYPE_COMPOSITE_TYPE: - str = get_composite_type(content->ct_type->tp_data.tp_composite_type); - break; - } - - if (str == NULL) - str = "unknown"; - subtype = content->ct_subtype; - if (subtype == NULL) - subtype = "unknown"; - - size_t len = strlen(str) + strlen(subtype) + 2; - result = (char *) malloc(len); -#ifndef _MSC_VER - strcpy(result, str); - strcat(result, "/"); - strcat(result, subtype); -#else - strcpy_s(result, len, str); - strcat_s(result, len, "/"); - strcat_s(result, len, subtype); -#endif - - return result; -} - -Attachment * Attachment::attachmentWithSingleMIME(struct mailmime * mime) -{ - struct mailmime_data * data; - const char * bytes; - size_t length; - Attachment * result; - struct mailmime_single_fields single_fields; - char * str; - char * name; - char * filename; - char * content_id; - char * description; - char * loc; - Encoding encoding; - clist * ct_parameters; - - MCAssert(mime->mm_type == MAILMIME_SINGLE); - - result = new Attachment(); - result->setUniqueID(mailcore::String::uuidString()); - - data = mime->mm_data.mm_single; - bytes = data->dt_data.dt_text.dt_data; - length = data->dt_data.dt_text.dt_length; - - mailmime_single_fields_init(&single_fields, mime->mm_mime_fields, mime->mm_content_type); - - encoding = encodingForMIMEEncoding(single_fields.fld_encoding, data->dt_encoding); - - Data * mimeData; - mimeData = Data::dataWithBytes(bytes, (unsigned int) length); - mimeData = mimeData->decodedDataUsingEncoding(encoding); - result->setData(mimeData); - - str = get_content_type_str(mime->mm_content_type); - result->setMimeType(String::stringWithUTF8Characters(str)); - free(str); - - name = single_fields.fld_content_name; - filename = single_fields.fld_disposition_filename; - content_id = single_fields.fld_id; - description = single_fields.fld_description; - loc = single_fields.fld_location; - ct_parameters = single_fields.fld_content->ct_parameters; - - if (filename != NULL) { - result->setFilename(String::stringByDecodingMIMEHeaderValue(filename)); - } - else if (name != NULL) { - result->setFilename(String::stringByDecodingMIMEHeaderValue(name)); - } - if (content_id != NULL) { - result->setContentID(String::stringWithUTF8Characters(content_id)); - } - if (description != NULL) { - result->setContentDescription(String::stringWithUTF8Characters(description)); - } - if (single_fields.fld_content_charset != NULL) { - result->setCharset(String::stringByDecodingMIMEHeaderValue(single_fields.fld_content_charset)); - } - if (loc != NULL) { - result->setContentLocation(String::stringWithUTF8Characters(loc)); - } - - if (ct_parameters != NULL) { - clistiter * iter = clist_begin(ct_parameters); - struct mailmime_parameter * param; - while (iter != NULL) { - param = (struct mailmime_parameter *) clist_content(iter); - if (param != NULL) { - result->setContentTypeParameter(String::stringWithUTF8Characters(param->pa_name), String::stringWithUTF8Characters(param->pa_value)); - } - iter = clist_next(iter); - } - } - - if (single_fields.fld_disposition != NULL) { - if (single_fields.fld_disposition->dsp_type != NULL) { - if (single_fields.fld_disposition->dsp_type->dsp_type == MAILMIME_DISPOSITION_TYPE_INLINE) { - result->setInlineAttachment(true); - } - } - } - - return (Attachment *) result->autorelease(); -} - -MessagePart * Attachment::attachmentWithMessageMIME(struct mailmime * mime) -{ - MessagePart * attachment; - AbstractPart * mainPart; - - attachment = new MessagePart(); - attachment->header()->importIMFFields(mime->mm_data.mm_message.mm_fields); - mainPart = attachmentsWithMIMEWithMain(mime->mm_data.mm_message.mm_msg_mime, false); - attachment->setMainPart(mainPart); - - return (MessagePart *) attachment->autorelease(); -} diff --git a/src/core/rfc822/MCAttachment.cpp b/src/core/rfc822/MCAttachment.cpp new file mode 100644 index 00000000..cbc66a39 --- /dev/null +++ b/src/core/rfc822/MCAttachment.cpp @@ -0,0 +1,607 @@ +#include "MCWin32.h" // should be included first. + +#include "MCAttachment.h" + +#include "MCMultipart.h" +#include "MCMessagePart.h" +#include "MCMessageHeader.h" +#include "MCMessageConstants.h" +#include "MCLog.h" +#include "MCZip.h" + +#include +#include +#ifndef _MSC_VER +#include +#endif +#include +#include + +using namespace mailcore; + +static char * findBlank(const char * str) +{ + char * p = (char *) str; + while (!((* p == ' ') || (* p == '\t'))) { + if (* p == 0) + return NULL; + p ++; + } + return p; +} + +HashMap * Attachment::readMimeTypesFile(String * filename) +{ + HashMap * result = HashMap::hashMap(); + + char line[512]; + FILE * f = fopen(filename->fileSystemRepresentation(), "r"); + if (f == NULL) { + return result; + } + + while (fgets(line, sizeof(line), f)) { + char * p; + String * mimeType; + + if (line[0] == '#') { + continue; + } + + while ((p = strchr(line, '\r')) != NULL) { + * p = 0; + } + while ((p = strchr(line, '\n')) != NULL) { + * p = 0; + } + + p = findBlank(line); + if (p == NULL) { + continue; + } + + * p = 0; + p ++; + mimeType = String::stringWithUTF8Characters(line); + + while (1) { + while ((* p == ' ') || (* p == '\t')) { + p ++; + } + + char * ext_end = findBlank(p); + if (ext_end == NULL) { + String * ext = String::stringWithUTF8Characters(p); + result->setObjectForKey(ext, mimeType); + break; + } + else { + * ext_end = 0; + String * ext = String::stringWithUTF8Characters(p); + result->setObjectForKey(ext, mimeType); + p = ext_end + 1; + } + } + } + + fclose(f); + + return result; +} + +String * Attachment::mimeTypeForFilename(String * filename) +{ + if (filename == NULL) { + return NULL; + } + static HashMap * mimeTypes = NULL; + static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_lock(&lock); + if (mimeTypes == NULL) { + mimeTypes = readMimeTypesFile(MCSTR("/etc/apache2/mime.types")); + mimeTypes->retain(); + } + pthread_mutex_unlock(&lock); + + String * ext; + String * result; + + ext = filename->pathExtension()->lowercaseString(); + result = (String *) mimeTypes->objectForKey(ext); + if (result != NULL) + return result; + + if (ext->isEqual(MCSTR("jpg"))) { + return MCSTR("image/jpeg"); + } + else if (ext->isEqual(MCSTR("jpeg"))) { + return MCSTR("image/jpeg"); + } + else if (ext->isEqual(MCSTR("png"))) { + return MCSTR("image/png"); + } + else if (ext->isEqual(MCSTR("gif"))) { + return MCSTR("image/gif"); + } + else if (ext->isEqual(MCSTR("html"))) { + return MCSTR("text/html"); + } + else if (ext->isEqual(MCSTR("txt"))) { + return MCSTR("text/plain"); + } + return NULL; +} + +Attachment * Attachment::attachmentWithContentsOfFile(String * filename) +{ + if (filename == NULL) { + return attachmentWithData(NULL, Data::data()); + } + + const char * cPath = filename->fileSystemRepresentation(); + struct stat statinfo; + int r; + + r = stat(cPath, &statinfo); + if (r < 0) { + return attachmentWithData(filename, Data::data()); + } + + if (S_ISDIR(statinfo.st_mode)) { + String * zipFilename = CreateTemporaryZipFileFromFolder(filename); + if (zipFilename == NULL) { + return NULL; + } + Attachment * result = attachmentWithContentsOfFile(zipFilename); + RemoveTemporaryZipFile(zipFilename); + return result; + } + else { + Data * data = Data::dataWithContentsOfFile(filename); + return attachmentWithData(filename, data); + } +} + +Attachment * Attachment::attachmentWithData(String * filename, Data * data) +{ + Attachment * attachment; + String * mimeType; + + attachment = new Attachment(); + mimeType = Attachment::mimeTypeForFilename(filename); + if (mimeType != NULL) { + attachment->setMimeType(mimeType); + } + if (filename != NULL) { + attachment->setFilename(filename->lastPathComponent()); + } + attachment->setData(data); + + return (Attachment *) attachment->autorelease(); +} + +Attachment * Attachment::attachmentWithHTMLString(String * htmlString) +{ + Data * data; + Attachment * attachment; + + attachment = new Attachment(); + attachment->setInlineAttachment(true); + attachment->setMimeType(MCSTR("text/html")); + data = htmlString->dataUsingEncoding("utf-8"); + attachment->setData(data); + + return (Attachment *) attachment->autorelease(); +} + +Attachment * Attachment::attachmentWithRFC822Message(Data * messageData) +{ + Attachment * attachment; + + attachment = new Attachment(); + attachment->setMimeType(MCSTR("message/rfc822")); + attachment->setData(messageData); + + return (Attachment *) attachment->autorelease(); +} + +Attachment * Attachment::attachmentWithText(String * text) +{ + Data * data; + Attachment * attachment; + + attachment = new Attachment(); + attachment->setInlineAttachment(true); + attachment->setMimeType(MCSTR("text/plain")); + data = text->dataUsingEncoding("utf-8"); + attachment->setData(data); + + return (Attachment *) attachment->autorelease(); +} + +void Attachment::init() +{ + mData = NULL; + setMimeType(MCSTR("application/octet-stream")); +} + +Attachment::Attachment() +{ + init(); +} + +Attachment::Attachment(Attachment * other) : AbstractPart(other) +{ + init(); + MC_SAFE_REPLACE_RETAIN(Data, mData, other->mData); +} + +Attachment::~Attachment() +{ + MC_SAFE_RELEASE(mData); +} + +String * Attachment::description() +{ + String * result = String::string(); + result->appendUTF8Format("<%s:%p\n", className()->UTF8Characters(), this); + if (filename() != NULL) { + result->appendUTF8Format("filename: %s\n", filename()->UTF8Characters()); + } + if (mimeType() != NULL) { + result->appendUTF8Format("mime type: %s\n", mimeType()->UTF8Characters()); + } + if (charset() != NULL) { + result->appendUTF8Format("charset: %s\n", charset()->UTF8Characters()); + } + if (contentID() != NULL) { + result->appendUTF8Format("content-ID: %s\n", contentID()->UTF8Characters()); + } + if (contentLocation() != NULL) { + result->appendUTF8Format("content-location: %s\n", contentLocation()->UTF8Characters()); + } + result->appendUTF8Format("inline: %i\n", isInlineAttachment()); + if (mData != NULL) { + result->appendUTF8Format("data: %i bytes\n", mData->length()); + } + else { + result->appendUTF8Format("no data\n"); + } + result->appendUTF8Format(">"); + + return result; +} + +Object * Attachment::copy() +{ + return new Attachment(this); +} + +void Attachment::setData(Data * data) +{ + MC_SAFE_REPLACE_RETAIN(Data, mData, data); +} + +Data * Attachment::data() +{ + return mData; +} + +String * Attachment::decodedString() +{ + if (mData) { + return decodedStringForData(mData); + } + else { + return NULL; + } +} + +AbstractPart * Attachment::attachmentsWithMIME(struct mailmime * mime) +{ + return attachmentsWithMIMEWithMain(mime, true); +} + +void Attachment::fillMultipartSubAttachments(AbstractMultipart * multipart, struct mailmime * mime) +{ + switch (mime->mm_type) { + case MAILMIME_MULTIPLE: + { + clistiter * cur; + Array * subAttachments = Array::array(); + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailmime * submime; + AbstractPart * subAttachment; + + submime = (struct mailmime *) clist_content(cur); + subAttachment = attachmentsWithMIMEWithMain(submime, false); + subAttachments->addObject(subAttachment); + } + + multipart->setParts(subAttachments); + break; + } + } +} + +AbstractPart * Attachment::attachmentsWithMIMEWithMain(struct mailmime * mime, bool isMain) +{ + switch (mime->mm_type) { + case MAILMIME_SINGLE: + { + Attachment * attachment; + attachment = attachmentWithSingleMIME(mime); + return attachment; + } + case MAILMIME_MULTIPLE: + { + if ((mime->mm_content_type != NULL) && (mime->mm_content_type->ct_subtype != NULL) && + (strcasecmp(mime->mm_content_type->ct_subtype, "alternative") == 0)) { + Multipart * attachment; + attachment = new Multipart(); + attachment->setPartType(PartTypeMultipartAlternative); + fillMultipartSubAttachments(attachment, mime); + return (Multipart *) attachment->autorelease(); + } + else if ((mime->mm_content_type != NULL) && (mime->mm_content_type->ct_subtype != NULL) && + (strcasecmp(mime->mm_content_type->ct_subtype, "related") == 0)) { + Multipart * attachment; + attachment = new Multipart(); + attachment->setPartType(PartTypeMultipartRelated); + fillMultipartSubAttachments(attachment, mime); + return (Multipart *) attachment->autorelease(); + } + else if ((mime->mm_content_type != NULL) && (mime->mm_content_type->ct_subtype != NULL) && + (strcasecmp(mime->mm_content_type->ct_subtype, "signed") == 0)) { + Multipart * attachment; + attachment = new Multipart(); + attachment->setPartType(PartTypeMultipartSigned); + fillMultipartSubAttachments(attachment, mime); + return (Multipart *) attachment->autorelease(); + } + else { + Multipart * attachment; + attachment = new Multipart(); + fillMultipartSubAttachments(attachment, mime); + return (Multipart *) attachment->autorelease(); + } + } + case MAILMIME_MESSAGE: + { + if (isMain) { + AbstractPart * attachment; + attachment = attachmentsWithMIMEWithMain(mime->mm_data.mm_message.mm_msg_mime, false); + return attachment; + } + else { + MessagePart * messagePart; + messagePart = attachmentWithMessageMIME(mime); + return messagePart; + } + } + } + + return NULL; +} + +Encoding Attachment::encodingForMIMEEncoding(struct mailmime_mechanism * mechanism, int defaultMimeEncoding) +{ + Encoding mimeEncoding = (Encoding) defaultMimeEncoding; + + if (mechanism != NULL) { + mimeEncoding = (Encoding) mechanism->enc_type; + } + + switch ((int) mimeEncoding) { + default: + case MAILMIME_MECHANISM_ERROR: + return EncodingOther; + case MAILMIME_MECHANISM_7BIT: + return Encoding7Bit; + case MAILMIME_MECHANISM_8BIT: + return Encoding8Bit; + case MAILMIME_MECHANISM_BINARY: + return EncodingBinary; + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + return EncodingQuotedPrintable; + case MAILMIME_MECHANISM_BASE64: + return EncodingBase64; + case MAILMIME_MECHANISM_TOKEN: + if (mechanism == NULL) + return Encoding8Bit; + if (mechanism->enc_token == NULL) + return Encoding8Bit; + + if (strcasecmp(mechanism->enc_token, "x-uuencode") == 0) { + return EncodingUUEncode; + } + else { + return EncodingOther; + } + } +} + +static const char * get_discrete_type(struct mailmime_discrete_type * discrete_type) +{ + switch (discrete_type->dt_type) { + case MAILMIME_DISCRETE_TYPE_TEXT: + return "text"; + + case MAILMIME_DISCRETE_TYPE_IMAGE: + return "image"; + + case MAILMIME_DISCRETE_TYPE_AUDIO: + return "audio"; + + case MAILMIME_DISCRETE_TYPE_VIDEO: + return "video"; + + case MAILMIME_DISCRETE_TYPE_APPLICATION: + return "application"; + + case MAILMIME_DISCRETE_TYPE_EXTENSION: + return discrete_type->dt_extension; + } + + return NULL; +} + +static const char * +get_composite_type(struct mailmime_composite_type * composite_type) +{ + switch (composite_type->ct_type) { + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + return "message"; + + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + return "multipart"; + + case MAILMIME_COMPOSITE_TYPE_EXTENSION: + return composite_type->ct_token; + } + + return NULL; +} + +static char * get_content_type_str(struct mailmime_content * content) +{ + const char * str; + char * result; + const char * subtype; + + if (content == NULL) { + return strdup("unknown/unknown"); + } + + str = "unknown"; + + switch (content->ct_type->tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + str = get_discrete_type(content->ct_type->tp_data.tp_discrete_type); + break; + + case MAILMIME_TYPE_COMPOSITE_TYPE: + str = get_composite_type(content->ct_type->tp_data.tp_composite_type); + break; + } + + if (str == NULL) + str = "unknown"; + subtype = content->ct_subtype; + if (subtype == NULL) + subtype = "unknown"; + + size_t len = strlen(str) + strlen(subtype) + 2; + result = (char *) malloc(len); +#ifndef _MSC_VER + strcpy(result, str); + strcat(result, "/"); + strcat(result, subtype); +#else + strcpy_s(result, len, str); + strcat_s(result, len, "/"); + strcat_s(result, len, subtype); +#endif + + return result; +} + +Attachment * Attachment::attachmentWithSingleMIME(struct mailmime * mime) +{ + struct mailmime_data * data; + const char * bytes; + size_t length; + Attachment * result; + struct mailmime_single_fields single_fields; + char * str; + char * name; + char * filename; + char * content_id; + char * description; + char * loc; + Encoding encoding; + clist * ct_parameters; + + MCAssert(mime->mm_type == MAILMIME_SINGLE); + + result = new Attachment(); + result->setUniqueID(mailcore::String::uuidString()); + + data = mime->mm_data.mm_single; + bytes = data->dt_data.dt_text.dt_data; + length = data->dt_data.dt_text.dt_length; + + mailmime_single_fields_init(&single_fields, mime->mm_mime_fields, mime->mm_content_type); + + encoding = encodingForMIMEEncoding(single_fields.fld_encoding, data->dt_encoding); + + Data * mimeData; + mimeData = Data::dataWithBytes(bytes, (unsigned int) length); + mimeData = mimeData->decodedDataUsingEncoding(encoding); + result->setData(mimeData); + + str = get_content_type_str(mime->mm_content_type); + result->setMimeType(String::stringWithUTF8Characters(str)); + free(str); + + name = single_fields.fld_content_name; + filename = single_fields.fld_disposition_filename; + content_id = single_fields.fld_id; + description = single_fields.fld_description; + loc = single_fields.fld_location; + ct_parameters = single_fields.fld_content->ct_parameters; + + if (filename != NULL) { + result->setFilename(String::stringByDecodingMIMEHeaderValue(filename)); + } + else if (name != NULL) { + result->setFilename(String::stringByDecodingMIMEHeaderValue(name)); + } + if (content_id != NULL) { + result->setContentID(String::stringWithUTF8Characters(content_id)); + } + if (description != NULL) { + result->setContentDescription(String::stringWithUTF8Characters(description)); + } + if (single_fields.fld_content_charset != NULL) { + result->setCharset(String::stringByDecodingMIMEHeaderValue(single_fields.fld_content_charset)); + } + if (loc != NULL) { + result->setContentLocation(String::stringWithUTF8Characters(loc)); + } + + if (ct_parameters != NULL) { + clistiter * iter = clist_begin(ct_parameters); + struct mailmime_parameter * param; + while (iter != NULL) { + param = (struct mailmime_parameter *) clist_content(iter); + if (param != NULL) { + result->setContentTypeParameter(String::stringWithUTF8Characters(param->pa_name), String::stringWithUTF8Characters(param->pa_value)); + } + iter = clist_next(iter); + } + } + + if (single_fields.fld_disposition != NULL) { + if (single_fields.fld_disposition->dsp_type != NULL) { + if (single_fields.fld_disposition->dsp_type->dsp_type == MAILMIME_DISPOSITION_TYPE_INLINE) { + result->setInlineAttachment(true); + } + } + } + + return (Attachment *) result->autorelease(); +} + +MessagePart * Attachment::attachmentWithMessageMIME(struct mailmime * mime) +{ + MessagePart * attachment; + AbstractPart * mainPart; + + attachment = new MessagePart(); + attachment->header()->importIMFFields(mime->mm_data.mm_message.mm_fields); + mainPart = attachmentsWithMIMEWithMain(mime->mm_data.mm_message.mm_msg_mime, false); + attachment->setMainPart(mainPart); + + return (MessagePart *) attachment->autorelease(); +} diff --git a/src/core/rfc822/MCMessageBuilder.cc b/src/core/rfc822/MCMessageBuilder.cc deleted file mode 100644 index a98cefd1..00000000 --- a/src/core/rfc822/MCMessageBuilder.cc +++ /dev/null @@ -1,959 +0,0 @@ -#include "MCWin32.h" // Should be included first. - -#include "MCMessageBuilder.h" - -#include "MCMessageHeader.h" -#include "MCAttachment.h" -#include "MCMessageParser.h" - -#include -#ifndef _MSC_VER -#include -#endif -#include -#include - -using namespace mailcore; - -static char * generate_boundary(const char * boundary_prefix); -struct mailmime * part_multiple_new(MessageBuilder * builder, const char * type, const char * boundary_prefix); -static struct mailmime * -part_new_empty(MessageBuilder * builder, struct mailmime_content * content, - struct mailmime_fields * mime_fields, - const char * boundary_prefix, - int force_single); - -static struct mailmime * get_multipart_alternative(MessageBuilder * builder, const char * boundary_prefix) -{ - struct mailmime * mime; - - mime = part_multiple_new(builder, "multipart/alternative", boundary_prefix); - - return mime; -} - -static struct mailmime * get_multipart_related(MessageBuilder * builder, const char * boundary_prefix) -{ - struct mailmime * mime; - - mime = part_multiple_new(builder, "multipart/related", boundary_prefix); - - return mime; -} - -static struct mailmime * get_multipart_signed_pgp(MessageBuilder * builder, const char * boundary_prefix) -{ - struct mailmime * mime; - - mime = part_multiple_new(builder, "multipart/signed", boundary_prefix); - struct mailmime_parameter * param = mailmime_param_new_with_data((char *) "protocol", (char *) "application/pgp-signature"); - clist_append(mime->mm_content_type->ct_parameters, param); - - return mime; -} - -static struct mailmime * get_multipart_encrypted_pgp(MessageBuilder * builder, const char * boundary_prefix) -{ - struct mailmime * mime; - - mime = part_multiple_new(builder, "multipart/encrypted", boundary_prefix); - struct mailmime_parameter * param = mailmime_param_new_with_data((char *) "protocol", (char *) "application/pgp-encrypted"); - clist_append(mime->mm_content_type->ct_parameters, param); - - return mime; -} - -static int add_attachment(MessageBuilder * builder, struct mailmime * mime, - struct mailmime * mime_sub, - const char * boundary_prefix) -{ - struct mailmime * saved_sub; - struct mailmime * mp; - int res; - int r; - - switch (mime->mm_type) { - case MAILMIME_SINGLE: - res = MAILIMF_ERROR_INVAL; - goto err; - - case MAILMIME_MULTIPLE: - r = mailmime_add_part(mime, mime_sub); - if (r != MAILIMF_NO_ERROR) { - res = MAILIMF_ERROR_MEMORY; - goto err; - } - - return MAILIMF_NO_ERROR; - } - - /* MAILMIME_MESSAGE */ - - if (mime->mm_data.mm_message.mm_msg_mime == NULL) { - /* there is no subpart, we can simply attach it */ - - r = mailmime_add_part(mime, mime_sub); - if (r != MAILIMF_NO_ERROR) { - res = MAILIMF_ERROR_MEMORY; - goto err; - } - - return MAILIMF_NO_ERROR; - } - - if (mime->mm_data.mm_message.mm_msg_mime->mm_type == MAILMIME_MULTIPLE && - strcasecmp(mime->mm_data.mm_message.mm_msg_mime->mm_content_type->ct_subtype, "alternative") != 0) { - /* in case the subpart is multipart, simply attach it to the subpart */ - - return mailmime_add_part(mime->mm_data.mm_message.mm_msg_mime, mime_sub); - } - - /* we save the current subpart, ... */ - - saved_sub = mime->mm_data.mm_message.mm_msg_mime; - - /* create a multipart */ - - mp = part_multiple_new(builder, "multipart/mixed", boundary_prefix); - if (mp == NULL) { - res = MAILIMF_ERROR_MEMORY; - goto err; - } - - /* detach the saved subpart from the parent */ - - mailmime_remove_part(saved_sub); - - /* the created multipart is the new child of the parent */ - - r = mailmime_add_part(mime, mp); - if (r != MAILIMF_NO_ERROR) { - res = MAILIMF_ERROR_MEMORY; - goto free_mp; - } - - /* then, attach the saved subpart and ... */ - - r = mailmime_add_part(mp, saved_sub); - if (r != MAILIMF_NO_ERROR) { - res = MAILIMF_ERROR_MEMORY; - goto free_saved_sub; - } - - /* the given part to the parent */ - - r = mailmime_add_part(mp, mime_sub); - if (r != MAILIMF_NO_ERROR) { - res = MAILIMF_ERROR_MEMORY; - goto free_saved_sub; - } - - return MAILIMF_NO_ERROR; - -free_mp: - mailmime_free(mp); -free_saved_sub: - mailmime_free(saved_sub); -err: - return res; -} - -static struct mailmime * get_text_part(MessageBuilder * builder, - const char * mime_type, const char * charset, const char * content_id, - const char * description, - const char * text, size_t length, int encoding_type, clist * contentTypeParameters) -{ - struct mailmime_fields * mime_fields; - struct mailmime * mime; - struct mailmime_content * content; - struct mailmime_parameter * param; - struct mailmime_disposition * disposition; - struct mailmime_mechanism * encoding; - char * dup_content_id; - char * dup_description; - - encoding = mailmime_mechanism_new(encoding_type, NULL); - disposition = mailmime_disposition_new_with_data(MAILMIME_DISPOSITION_TYPE_INLINE, - NULL, NULL, NULL, NULL, (size_t) -1); - dup_content_id = NULL; - if (content_id != NULL) - dup_content_id = strdup(content_id); - dup_description = NULL; - if (dup_description != NULL) - dup_description = strdup(description); - mime_fields = mailmime_fields_new_with_data(encoding, - dup_content_id, dup_description, disposition, NULL); - - content = mailmime_content_new_with_str(mime_type); - if (charset == NULL) { - param = mailmime_param_new_with_data((char *) "charset", (char *) "utf-8"); - } - else { - param = mailmime_param_new_with_data((char *) "charset", (char *) charset); - } - clist_append(content->ct_parameters, param); - if (contentTypeParameters != NULL) { - clist_concat(content->ct_parameters, contentTypeParameters); - } - - mime = part_new_empty(builder, content, mime_fields, NULL, 1); - mailmime_set_body_text(mime, (char *) text, length); - - return mime; -} - -static struct mailmime * get_plain_text_part(MessageBuilder * builder, - const char * mime_type, const char * charset, const char * content_id, - const char * description, - const char * text, size_t length, clist * contentTypeParameters, bool forEncryption) -{ - bool needsQuotedPrintable; - int mechanism; - - needsQuotedPrintable = false; - if (forEncryption) { - needsQuotedPrintable = true; - } - if (!needsQuotedPrintable) { - for(size_t i = 0 ; i < length ; i ++) { - if ((text[i] & (1 << 7)) != 0) { - needsQuotedPrintable = true; - break; - } - } - } - - mechanism = MAILMIME_MECHANISM_7BIT; - if (needsQuotedPrintable) { - mechanism = MAILMIME_MECHANISM_QUOTED_PRINTABLE; - } - return get_text_part(builder, mime_type, charset, content_id, description, text, length, mechanism, contentTypeParameters); -} - -static struct mailmime * get_other_text_part(MessageBuilder * builder, - const char * mime_type, const char * charset, const char * content_id, - const char * description, - const char * text, size_t length, clist * contentTypeParameters) -{ - return get_text_part(builder, mime_type, charset, content_id, description, text, length, MAILMIME_MECHANISM_QUOTED_PRINTABLE, contentTypeParameters); -} - -static struct mailmime * get_file_part(MessageBuilder * builder, - const char * filename, const char * mime_type, int is_inline, - const char * content_id, - const char * content_description, - const char * text, size_t length, clist * contentTypeParameters) -{ - char * disposition_name; - int encoding_type; - struct mailmime_disposition * disposition; - struct mailmime_mechanism * encoding; - struct mailmime_content * content; - struct mailmime * mime; - struct mailmime_fields * mime_fields; - char * dup_content_id; - char * dup_content_description; - - disposition_name = NULL; - if (filename != NULL) { - disposition_name = strdup(filename); - } - if (is_inline) { - disposition = mailmime_disposition_new_with_data(MAILMIME_DISPOSITION_TYPE_INLINE, - disposition_name, NULL, NULL, NULL, (size_t) -1); - } - else { - disposition = mailmime_disposition_new_with_data(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, - disposition_name, NULL, NULL, NULL, (size_t) -1); - } - content = mailmime_content_new_with_str(mime_type); - - encoding_type = MAILMIME_MECHANISM_BASE64; - encoding = mailmime_mechanism_new(encoding_type, NULL); - dup_content_id = NULL; - if (content_id != NULL) - dup_content_id = strdup(content_id); - dup_content_description = NULL; - if (content_description != NULL) - dup_content_description = strdup(content_description); - mime_fields = mailmime_fields_new_with_data(encoding, - dup_content_id, dup_content_description, disposition, NULL); - - if (contentTypeParameters != NULL) { - clist_concat(content->ct_parameters, contentTypeParameters); - } - - mime = part_new_empty(builder, content, mime_fields, NULL, 1); - mailmime_set_body_text(mime, (char *) text, length); - - return mime; -} - -#define MIME_ENCODED_STR(str) (str != NULL ? str->encodedMIMEHeaderValue()->bytes() : NULL) - -static clist * content_type_parameters_from_attachment(Attachment * att) -{ - clist * contentTypeParameters = NULL; - struct mailmime_parameter * param; - - mc_foreacharray(String, name, att->allContentTypeParametersNames()) { - if (contentTypeParameters == NULL) { - contentTypeParameters = clist_new(); - } - String * value = att->contentTypeParameterValueForName(name); - param = mailmime_param_new_with_data((char *)name->UTF8Characters(), (char *)value->UTF8Characters()); - clist_append(contentTypeParameters, param); - } - - return contentTypeParameters; -} - -static struct mailmime * mime_from_attachment(MessageBuilder * builder, Attachment * att, bool forEncryption) -{ - struct mailmime * mime; - Data * data; - int r; - - data = att->data(); - if (data == NULL) { - data = Data::data(); - } - if (att->mimeType()->lowercaseString()->isEqual(MCSTR("message/rfc822"))) { - size_t indx = 0; - r = mailmime_parse(data->bytes(), data->length(), &indx, &mime); - if (r != MAILIMF_NO_ERROR) - return NULL; - } - else { - clist * contentTypeParameters = content_type_parameters_from_attachment(att); - if (att->isInlineAttachment() && att->mimeType()->lowercaseString()->isEqual(MCSTR("text/plain"))) { - mime = get_plain_text_part(builder, MCUTF8(att->mimeType()), MCUTF8(att->charset()), - MCUTF8(att->contentID()), - MIME_ENCODED_STR(att->contentDescription()), - data->bytes(), data->length(), - contentTypeParameters, - forEncryption); - } - else if (att->isInlineAttachment() && att->mimeType()->lowercaseString()->hasPrefix(MCSTR("text/"))) { - mime = get_other_text_part(builder, MCUTF8(att->mimeType()), MCUTF8(att->charset()), - MCUTF8(att->contentID()), - MIME_ENCODED_STR(att->contentDescription()), - data->bytes(), data->length(), - contentTypeParameters); - } - else { - mime = get_file_part(builder, MIME_ENCODED_STR(att->filename()), - MCUTF8(att->mimeType()), att->isInlineAttachment(), - MCUTF8(att->contentID()), - MIME_ENCODED_STR(att->contentDescription()), - data->bytes(), data->length(), - contentTypeParameters); - } - if (contentTypeParameters != NULL) { - clist_free(contentTypeParameters); - } - } - return mime; -} - -static struct mailmime * multipart_related_from_attachments(MessageBuilder * builder, - Attachment * htmlAttachment, - Array * attachments, const char * boundary_prefix, bool forEncryption) -{ - if ((attachments != NULL) && (attachments->count() > 0)) { - struct mailmime * submime; - struct mailmime * mime; - - mime = get_multipart_related(builder, boundary_prefix); - - submime = mime_from_attachment(builder, htmlAttachment, forEncryption); - add_attachment(builder, mime, submime, boundary_prefix); - - for(unsigned int i = 0 ; i < attachments->count() ; i ++) { - Attachment * attachment; - - attachment = (Attachment *) attachments->objectAtIndex(i); - submime = mime_from_attachment(builder, attachment, forEncryption); - add_attachment(builder, mime, submime, boundary_prefix); - } - - return mime; - } - else { - struct mailmime * mime; - - mime = mime_from_attachment(builder, htmlAttachment, forEncryption); - - return mime; - } -} - -static struct mailmime * -part_new_empty(MessageBuilder * builder, struct mailmime_content * content, - struct mailmime_fields * mime_fields, - const char * boundary_prefix, - int force_single) -{ - struct mailmime * build_info; - clist * list; - int r; - int mime_type; - - list = NULL; - - if (force_single) { - mime_type = MAILMIME_SINGLE; - } - else { - switch (content->ct_type->tp_type) { - case MAILMIME_TYPE_DISCRETE_TYPE: - mime_type = MAILMIME_SINGLE; - break; - - case MAILMIME_TYPE_COMPOSITE_TYPE: - switch (content->ct_type->tp_data.tp_composite_type->ct_type) { - case MAILMIME_COMPOSITE_TYPE_MULTIPART: - mime_type = MAILMIME_MULTIPLE; - break; - - case MAILMIME_COMPOSITE_TYPE_MESSAGE: - if (strcasecmp(content->ct_subtype, "rfc822") == 0) - mime_type = MAILMIME_MESSAGE; - else - mime_type = MAILMIME_SINGLE; - break; - - default: - goto err; - } - break; - - default: - goto err; - } - } - - if (mime_type == MAILMIME_MULTIPLE) { - char * attr_name; - char * attr_value; - struct mailmime_parameter * param; - clist * parameters; - char * boundary; - - list = clist_new(); - if (list == NULL) - goto err; - - attr_name = strdup("boundary"); - if (attr_name == NULL) - goto free_list; - - if (builder != NULL) { - String * boundaryString = builder->nextBoundary(); - boundary = strdup(boundaryString->UTF8Characters()); - } - else { - boundary = generate_boundary(boundary_prefix); - } - attr_value = boundary; - if (attr_name == NULL) { - free(attr_name); - goto free_list; - } - - param = mailmime_parameter_new(attr_name, attr_value); - if (param == NULL) { - free(attr_value); - free(attr_name); - goto free_list; - } - - if (content->ct_parameters == NULL) { - parameters = clist_new(); - if (parameters == NULL) { - mailmime_parameter_free(param); - goto free_list; - } - } - else - parameters = content->ct_parameters; - - r = clist_append(parameters, param); - if (r != 0) { - clist_free(parameters); - mailmime_parameter_free(param); - goto free_list; - } - - if (content->ct_parameters == NULL) - content->ct_parameters = parameters; - } - - build_info = mailmime_new(mime_type, - NULL, 0, mime_fields, content, - NULL, NULL, NULL, list, - NULL, NULL); - if (build_info == NULL) { - clist_free(list); - return NULL; - } - - return build_info; - -free_list: - clist_free(list); -err: - return NULL; -} - -struct mailmime * part_multiple_new(MessageBuilder * builder, const char * type, const char * boundary_prefix) -{ - struct mailmime_fields * mime_fields; - struct mailmime_content * content; - struct mailmime * mp; - - mime_fields = mailmime_fields_new_empty(); - if (mime_fields == NULL) - goto err; - - content = mailmime_content_new_with_str(type); - if (content == NULL) - goto free_fields; - - mp = part_new_empty(builder, content, mime_fields, boundary_prefix, 0); - if (mp == NULL) - goto free_content; - - return mp; - -free_content: - mailmime_content_free(content); -free_fields: - mailmime_fields_free(mime_fields); -err: - return NULL; -} - -#define MAX_MESSAGE_ID 512 - -static char * generate_boundary(const char * boundary_prefix) -{ - char id[MAX_MESSAGE_ID]; - time_t now; - char name[MAX_MESSAGE_ID]; - long value; - - now = time(NULL); - value = random(); - - gethostname(name, MAX_MESSAGE_ID); - - if (boundary_prefix == NULL) - boundary_prefix = ""; - - snprintf(id, MAX_MESSAGE_ID, "%s%lx_%lx_%x", boundary_prefix, now, value, getpid()); - - return strdup(id); -} - -void MessageBuilder::init() -{ - mHTMLBody = NULL; - mTextBody = NULL; - mAttachments = NULL; - mRelatedAttachments = NULL; - mBoundaryPrefix = NULL; - mBoundaries = new Array(); - mCurrentBoundaryIndex = 0; -} - -MessageBuilder::MessageBuilder() -{ - init(); -} - -MessageBuilder::MessageBuilder(MessageBuilder * other) : AbstractMessage(other) -{ - init(); - setHTMLBody(other->mHTMLBody); - setTextBody(other->mTextBody); - setAttachments(other->mAttachments); - setRelatedAttachments(other->mRelatedAttachments); - MC_SAFE_REPLACE_COPY(String, mBoundaryPrefix, other->mBoundaryPrefix); -} - -MessageBuilder::~MessageBuilder() -{ - MC_SAFE_RELEASE(mHTMLBody); - MC_SAFE_RELEASE(mTextBody); - MC_SAFE_RELEASE(mAttachments); - MC_SAFE_RELEASE(mRelatedAttachments); - MC_SAFE_RELEASE(mBoundaryPrefix); - MC_SAFE_RELEASE(mBoundaries); -} - -String * MessageBuilder::description() -{ - String * result = String::string(); - result->appendUTF8Format("<%s:%p\n", className()->UTF8Characters(), this); - if (header() != NULL) { - result->appendString(header()->description()); - result->appendUTF8Characters("\n"); - } - if (mHTMLBody != NULL) { - result->appendUTF8Characters("-- html body --\n"); - result->appendString(mHTMLBody); - result->appendUTF8Characters("\n"); - } - if (mTextBody != NULL) { - result->appendUTF8Characters("-- text body --\n"); - result->appendString(mTextBody); - result->appendUTF8Characters("\n"); - } - if (mAttachments != NULL) { - result->appendUTF8Characters("-- attachments --\n"); - result->appendString(mAttachments->description()); - result->appendUTF8Characters("\n"); - } - if (mRelatedAttachments != NULL) { - result->appendUTF8Characters("-- related attachments --\n"); - result->appendString(mRelatedAttachments->description()); - result->appendUTF8Characters("\n"); - } - result->appendUTF8Characters(">"); - - return result; -} - -Object * MessageBuilder::copy() -{ - return new MessageBuilder(this); -} - -void MessageBuilder::setHTMLBody(String * htmlBody) -{ - MC_SAFE_REPLACE_COPY(String, mHTMLBody, htmlBody); -} - -String * MessageBuilder::htmlBody() -{ - return mHTMLBody; -} - -void MessageBuilder::setTextBody(String * textBody) -{ - MC_SAFE_REPLACE_COPY(String, mTextBody, textBody); -} - -String * MessageBuilder::textBody() -{ - return mTextBody; -} - -void MessageBuilder::setAttachments(Array * attachments) -{ - MC_SAFE_REPLACE_COPY(Array, mAttachments, attachments); -} - -Array * MessageBuilder::attachments() -{ - return mAttachments; -} - -void MessageBuilder::addAttachment(Attachment * attachment) -{ - if (attachment == NULL) { - return; - } - if (mAttachments == NULL) { - mAttachments = new Array(); - } - mAttachments->addObject(attachment); -} - -void MessageBuilder::setRelatedAttachments(Array * attachments) -{ - MC_SAFE_REPLACE_COPY(Array, mRelatedAttachments, attachments); -} - -Array * MessageBuilder::relatedAttachments() -{ - return mRelatedAttachments; -} - -void MessageBuilder::addRelatedAttachment(Attachment * attachment) -{ - if (attachment == NULL) { - return; - } - if (mRelatedAttachments == NULL) { - mRelatedAttachments = new Array(); - } - mRelatedAttachments->addObject(attachment); -} - -void MessageBuilder::setBoundaryPrefix(String * boundaryPrefix) -{ - MC_SAFE_REPLACE_COPY(String, mBoundaryPrefix, boundaryPrefix); -} - -String * MessageBuilder::boundaryPrefix() -{ - return mBoundaryPrefix; -} - -struct mailmime * MessageBuilder::mimeAndFilterBccAndForEncryption(bool filterBcc, bool forEncryption) -{ - struct mailmime * htmlPart; - struct mailmime * textPart; - struct mailmime * altPart; - struct mailmime * mainPart; - - mCurrentBoundaryIndex = 0; - htmlPart = NULL; - textPart = NULL; - altPart = NULL; - mainPart = NULL; - - if (htmlBody() != NULL) { - Attachment * htmlAttachment; - - htmlAttachment = Attachment::attachmentWithHTMLString(htmlBody()); - htmlPart = multipart_related_from_attachments(this, htmlAttachment, mRelatedAttachments, - MCUTF8(mBoundaryPrefix), forEncryption); - } - - if (textBody() != NULL) { - Attachment * textAttachment; - - textAttachment = Attachment::attachmentWithText(textBody()); - textPart = mime_from_attachment(this, textAttachment, forEncryption); - } - else if (htmlBody() != NULL) { - Attachment * textAttachment; - - textAttachment = Attachment::attachmentWithText(htmlBody()->flattenHTML()); - textPart = mime_from_attachment(this, textAttachment, forEncryption); - } - - if ((textPart != NULL) && (htmlPart != NULL)) { - altPart = get_multipart_alternative(this, MCUTF8(mBoundaryPrefix)); - mailmime_smart_add_part(altPart, textPart); - mailmime_smart_add_part(altPart, htmlPart); - mainPart = altPart; - } - else if (textPart != NULL) { - mainPart = textPart; - } - else if (htmlPart != NULL) { - mainPart = htmlPart; - } - - struct mailimf_fields * fields; - unsigned int i; - struct mailmime * mime; - - fields = header()->createIMFFieldsAndFilterBcc(filterBcc); - - mime = mailmime_new_message_data(NULL); - mailmime_set_imf_fields(mime, fields); - - if (mainPart != NULL) { - add_attachment(this, mime, mainPart, MCUTF8(mBoundaryPrefix)); - } - - if (attachments() != NULL) { - for(i = 0 ; i < attachments()->count() ; i ++) { - Attachment * attachment; - struct mailmime * submime; - - attachment = (Attachment *) attachments()->objectAtIndex(i); - submime = mime_from_attachment(this, attachment, forEncryption); - add_attachment(this, mime, submime, MCUTF8(mBoundaryPrefix)); - } - } - - struct mailmime * result = mime; - if (forEncryption) { - result = mime->mm_data.mm_message.mm_msg_mime; - mime->mm_data.mm_message.mm_msg_mime = NULL; - mailmime_free(mime); - } - - return result; -} - -Data * MessageBuilder::dataAndFilterBccAndForEncryption(bool filterBcc, bool forEncryption) -{ - Data * data; - MMAPString * str; - int col; - - str = mmap_string_new(""); - col = 0; - struct mailmime * mime = mimeAndFilterBccAndForEncryption(filterBcc, forEncryption); - mailmime_write_mem(str, &col, mime); - data = Data::dataWithBytes(str->str, (unsigned int) str->len); - mmap_string_free(str); - mailmime_free(mime); - - return data; -} - -Data * MessageBuilder::data() -{ - return dataAndFilterBccAndForEncryption(false, false); -} - -Data * MessageBuilder::dataForEncryption() -{ - return dataAndFilterBccAndForEncryption(false, true); -} - -String * MessageBuilder::htmlRendering(HTMLRendererTemplateCallback * htmlCallback) -{ - MessageParser * message = MessageParser::messageParserWithData(data()); - return message->htmlRendering(htmlCallback); -} - -String * MessageBuilder::htmlBodyRendering() -{ - MessageParser * message = MessageParser::messageParserWithData(data()); - return message->htmlBodyRendering(); -} - -String * MessageBuilder::plainTextRendering() -{ - MessageParser * message = MessageParser::messageParserWithData(data()); - return message->plainTextRendering(); -} - -String * MessageBuilder::plainTextBodyRendering(bool stripWhitespace) -{ - MessageParser * message = MessageParser::messageParserWithData(data()); - return message->plainTextBodyRendering(stripWhitespace); -} - -struct mailmime * get_signature_part(Data * signature) -{ - struct mailmime * mime; - struct mailmime_content * content; - - content = mailmime_content_new_with_str("application/pgp-signature"); - struct mailmime_fields * mime_fields = mailmime_fields_new_empty(); - mime = part_new_empty(NULL, content, mime_fields, NULL, 1); - mailmime_set_body_text(mime, signature->bytes(), signature->length()); - - return mime; -} - -Data * MessageBuilder::openPGPSignedMessageDataWithSignatureData(Data * signature) -{ - struct mailimf_fields * fields; - struct mailmime * mime; - - fields = header()->createIMFFieldsAndFilterBcc(false); - - mime = mailmime_new_message_data(NULL); - mailmime_set_imf_fields(mime, fields); - - struct mailmime * multipart = get_multipart_signed_pgp(NULL, MCUTF8(boundaryPrefix())); - add_attachment(NULL, mime, multipart, MCUTF8(boundaryPrefix())); - struct mailmime * part_to_sign = mimeAndFilterBccAndForEncryption(false, true); - add_attachment(NULL, multipart, part_to_sign, MCUTF8(boundaryPrefix())); - struct mailmime * signature_part = get_signature_part(signature); - add_attachment(NULL, multipart, signature_part, MCUTF8(boundaryPrefix())); - - MMAPString * str = mmap_string_new(""); - int col = 0; - - mailmime_write_mem(str, &col, mime); - Data * data = Data::dataWithBytes(str->str, (unsigned int) str->len); - mmap_string_free(str); - mailmime_free(mime); - - return data; -} - -static struct mailmime * get_pgp_version_part(void) -{ - struct mailmime * mime; - struct mailmime_content * content; - - content = mailmime_content_new_with_str("application/pgp-encrypted"); - struct mailmime_fields * mime_fields = mailmime_fields_new_empty(); - mime = part_new_empty(NULL, content, mime_fields, NULL, 1); - const char * version = "Version: 1\r\n"; - mailmime_set_body_text(mime, (char *) version, strlen(version)); - - return mime; -} - -static struct mailmime * get_encrypted_part(Data * encryptedData) -{ - struct mailmime * mime; - struct mailmime_content * content; - - content = mailmime_content_new_with_str("application/octet-stream"); - struct mailmime_fields * mime_fields = mailmime_fields_new_empty(); - mime = part_new_empty(NULL, content, mime_fields, NULL, 1); - mailmime_set_body_text(mime, encryptedData->bytes(), encryptedData->length()); - - return mime; -} - -Data * MessageBuilder::openPGPEncryptedMessageDataWithEncryptedData(Data * encryptedData) -{ - struct mailimf_fields * fields; - struct mailmime * mime; - - fields = header()->createIMFFieldsAndFilterBcc(false); - - mime = mailmime_new_message_data(NULL); - mailmime_set_imf_fields(mime, fields); - - struct mailmime * multipart = get_multipart_encrypted_pgp(NULL, MCUTF8(boundaryPrefix())); - add_attachment(NULL, mime, multipart, MCUTF8(boundaryPrefix())); - - struct mailmime * version_part = get_pgp_version_part(); - add_attachment(NULL, multipart, version_part, MCUTF8(boundaryPrefix())); - struct mailmime * encrypted_part = get_encrypted_part(encryptedData); - add_attachment(NULL, multipart, encrypted_part, MCUTF8(boundaryPrefix())); - - MMAPString * str = mmap_string_new(""); - int col = 0; - - mailmime_write_mem(str, &col, mime); - Data * data = Data::dataWithBytes(str->str, (unsigned int) str->len); - mmap_string_free(str); - mailmime_free(mime); - - return data; -} - -String * MessageBuilder::nextBoundary() -{ - unsigned int idx = mCurrentBoundaryIndex; - mCurrentBoundaryIndex ++; - if (idx < mBoundaries->count()) { - return (String *) mBoundaries->objectAtIndex(idx); - } - - char * boundary = generate_boundary(MCUTF8(mBoundaryPrefix)); - String * boundaryString = String::stringWithUTF8Characters(boundary); - mBoundaries->addObject(boundaryString); - free(boundary); - - return boundaryString; -} - -void MessageBuilder::resetBoundaries() -{ - mBoundaries->removeAllObjects(); -} - -void MessageBuilder::setBoundaries(Array * boundaries) -{ - resetBoundaries(); - mBoundaries->addObjectsFromArray(boundaries); -} diff --git a/src/core/rfc822/MCMessageBuilder.cpp b/src/core/rfc822/MCMessageBuilder.cpp new file mode 100644 index 00000000..a98cefd1 --- /dev/null +++ b/src/core/rfc822/MCMessageBuilder.cpp @@ -0,0 +1,959 @@ +#include "MCWin32.h" // Should be included first. + +#include "MCMessageBuilder.h" + +#include "MCMessageHeader.h" +#include "MCAttachment.h" +#include "MCMessageParser.h" + +#include +#ifndef _MSC_VER +#include +#endif +#include +#include + +using namespace mailcore; + +static char * generate_boundary(const char * boundary_prefix); +struct mailmime * part_multiple_new(MessageBuilder * builder, const char * type, const char * boundary_prefix); +static struct mailmime * +part_new_empty(MessageBuilder * builder, struct mailmime_content * content, + struct mailmime_fields * mime_fields, + const char * boundary_prefix, + int force_single); + +static struct mailmime * get_multipart_alternative(MessageBuilder * builder, const char * boundary_prefix) +{ + struct mailmime * mime; + + mime = part_multiple_new(builder, "multipart/alternative", boundary_prefix); + + return mime; +} + +static struct mailmime * get_multipart_related(MessageBuilder * builder, const char * boundary_prefix) +{ + struct mailmime * mime; + + mime = part_multiple_new(builder, "multipart/related", boundary_prefix); + + return mime; +} + +static struct mailmime * get_multipart_signed_pgp(MessageBuilder * builder, const char * boundary_prefix) +{ + struct mailmime * mime; + + mime = part_multiple_new(builder, "multipart/signed", boundary_prefix); + struct mailmime_parameter * param = mailmime_param_new_with_data((char *) "protocol", (char *) "application/pgp-signature"); + clist_append(mime->mm_content_type->ct_parameters, param); + + return mime; +} + +static struct mailmime * get_multipart_encrypted_pgp(MessageBuilder * builder, const char * boundary_prefix) +{ + struct mailmime * mime; + + mime = part_multiple_new(builder, "multipart/encrypted", boundary_prefix); + struct mailmime_parameter * param = mailmime_param_new_with_data((char *) "protocol", (char *) "application/pgp-encrypted"); + clist_append(mime->mm_content_type->ct_parameters, param); + + return mime; +} + +static int add_attachment(MessageBuilder * builder, struct mailmime * mime, + struct mailmime * mime_sub, + const char * boundary_prefix) +{ + struct mailmime * saved_sub; + struct mailmime * mp; + int res; + int r; + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + res = MAILIMF_ERROR_INVAL; + goto err; + + case MAILMIME_MULTIPLE: + r = mailmime_add_part(mime, mime_sub); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + return MAILIMF_NO_ERROR; + } + + /* MAILMIME_MESSAGE */ + + if (mime->mm_data.mm_message.mm_msg_mime == NULL) { + /* there is no subpart, we can simply attach it */ + + r = mailmime_add_part(mime, mime_sub); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + return MAILIMF_NO_ERROR; + } + + if (mime->mm_data.mm_message.mm_msg_mime->mm_type == MAILMIME_MULTIPLE && + strcasecmp(mime->mm_data.mm_message.mm_msg_mime->mm_content_type->ct_subtype, "alternative") != 0) { + /* in case the subpart is multipart, simply attach it to the subpart */ + + return mailmime_add_part(mime->mm_data.mm_message.mm_msg_mime, mime_sub); + } + + /* we save the current subpart, ... */ + + saved_sub = mime->mm_data.mm_message.mm_msg_mime; + + /* create a multipart */ + + mp = part_multiple_new(builder, "multipart/mixed", boundary_prefix); + if (mp == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + /* detach the saved subpart from the parent */ + + mailmime_remove_part(saved_sub); + + /* the created multipart is the new child of the parent */ + + r = mailmime_add_part(mime, mp); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_MEMORY; + goto free_mp; + } + + /* then, attach the saved subpart and ... */ + + r = mailmime_add_part(mp, saved_sub); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_MEMORY; + goto free_saved_sub; + } + + /* the given part to the parent */ + + r = mailmime_add_part(mp, mime_sub); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_MEMORY; + goto free_saved_sub; + } + + return MAILIMF_NO_ERROR; + +free_mp: + mailmime_free(mp); +free_saved_sub: + mailmime_free(saved_sub); +err: + return res; +} + +static struct mailmime * get_text_part(MessageBuilder * builder, + const char * mime_type, const char * charset, const char * content_id, + const char * description, + const char * text, size_t length, int encoding_type, clist * contentTypeParameters) +{ + struct mailmime_fields * mime_fields; + struct mailmime * mime; + struct mailmime_content * content; + struct mailmime_parameter * param; + struct mailmime_disposition * disposition; + struct mailmime_mechanism * encoding; + char * dup_content_id; + char * dup_description; + + encoding = mailmime_mechanism_new(encoding_type, NULL); + disposition = mailmime_disposition_new_with_data(MAILMIME_DISPOSITION_TYPE_INLINE, + NULL, NULL, NULL, NULL, (size_t) -1); + dup_content_id = NULL; + if (content_id != NULL) + dup_content_id = strdup(content_id); + dup_description = NULL; + if (dup_description != NULL) + dup_description = strdup(description); + mime_fields = mailmime_fields_new_with_data(encoding, + dup_content_id, dup_description, disposition, NULL); + + content = mailmime_content_new_with_str(mime_type); + if (charset == NULL) { + param = mailmime_param_new_with_data((char *) "charset", (char *) "utf-8"); + } + else { + param = mailmime_param_new_with_data((char *) "charset", (char *) charset); + } + clist_append(content->ct_parameters, param); + if (contentTypeParameters != NULL) { + clist_concat(content->ct_parameters, contentTypeParameters); + } + + mime = part_new_empty(builder, content, mime_fields, NULL, 1); + mailmime_set_body_text(mime, (char *) text, length); + + return mime; +} + +static struct mailmime * get_plain_text_part(MessageBuilder * builder, + const char * mime_type, const char * charset, const char * content_id, + const char * description, + const char * text, size_t length, clist * contentTypeParameters, bool forEncryption) +{ + bool needsQuotedPrintable; + int mechanism; + + needsQuotedPrintable = false; + if (forEncryption) { + needsQuotedPrintable = true; + } + if (!needsQuotedPrintable) { + for(size_t i = 0 ; i < length ; i ++) { + if ((text[i] & (1 << 7)) != 0) { + needsQuotedPrintable = true; + break; + } + } + } + + mechanism = MAILMIME_MECHANISM_7BIT; + if (needsQuotedPrintable) { + mechanism = MAILMIME_MECHANISM_QUOTED_PRINTABLE; + } + return get_text_part(builder, mime_type, charset, content_id, description, text, length, mechanism, contentTypeParameters); +} + +static struct mailmime * get_other_text_part(MessageBuilder * builder, + const char * mime_type, const char * charset, const char * content_id, + const char * description, + const char * text, size_t length, clist * contentTypeParameters) +{ + return get_text_part(builder, mime_type, charset, content_id, description, text, length, MAILMIME_MECHANISM_QUOTED_PRINTABLE, contentTypeParameters); +} + +static struct mailmime * get_file_part(MessageBuilder * builder, + const char * filename, const char * mime_type, int is_inline, + const char * content_id, + const char * content_description, + const char * text, size_t length, clist * contentTypeParameters) +{ + char * disposition_name; + int encoding_type; + struct mailmime_disposition * disposition; + struct mailmime_mechanism * encoding; + struct mailmime_content * content; + struct mailmime * mime; + struct mailmime_fields * mime_fields; + char * dup_content_id; + char * dup_content_description; + + disposition_name = NULL; + if (filename != NULL) { + disposition_name = strdup(filename); + } + if (is_inline) { + disposition = mailmime_disposition_new_with_data(MAILMIME_DISPOSITION_TYPE_INLINE, + disposition_name, NULL, NULL, NULL, (size_t) -1); + } + else { + disposition = mailmime_disposition_new_with_data(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + disposition_name, NULL, NULL, NULL, (size_t) -1); + } + content = mailmime_content_new_with_str(mime_type); + + encoding_type = MAILMIME_MECHANISM_BASE64; + encoding = mailmime_mechanism_new(encoding_type, NULL); + dup_content_id = NULL; + if (content_id != NULL) + dup_content_id = strdup(content_id); + dup_content_description = NULL; + if (content_description != NULL) + dup_content_description = strdup(content_description); + mime_fields = mailmime_fields_new_with_data(encoding, + dup_content_id, dup_content_description, disposition, NULL); + + if (contentTypeParameters != NULL) { + clist_concat(content->ct_parameters, contentTypeParameters); + } + + mime = part_new_empty(builder, content, mime_fields, NULL, 1); + mailmime_set_body_text(mime, (char *) text, length); + + return mime; +} + +#define MIME_ENCODED_STR(str) (str != NULL ? str->encodedMIMEHeaderValue()->bytes() : NULL) + +static clist * content_type_parameters_from_attachment(Attachment * att) +{ + clist * contentTypeParameters = NULL; + struct mailmime_parameter * param; + + mc_foreacharray(String, name, att->allContentTypeParametersNames()) { + if (contentTypeParameters == NULL) { + contentTypeParameters = clist_new(); + } + String * value = att->contentTypeParameterValueForName(name); + param = mailmime_param_new_with_data((char *)name->UTF8Characters(), (char *)value->UTF8Characters()); + clist_append(contentTypeParameters, param); + } + + return contentTypeParameters; +} + +static struct mailmime * mime_from_attachment(MessageBuilder * builder, Attachment * att, bool forEncryption) +{ + struct mailmime * mime; + Data * data; + int r; + + data = att->data(); + if (data == NULL) { + data = Data::data(); + } + if (att->mimeType()->lowercaseString()->isEqual(MCSTR("message/rfc822"))) { + size_t indx = 0; + r = mailmime_parse(data->bytes(), data->length(), &indx, &mime); + if (r != MAILIMF_NO_ERROR) + return NULL; + } + else { + clist * contentTypeParameters = content_type_parameters_from_attachment(att); + if (att->isInlineAttachment() && att->mimeType()->lowercaseString()->isEqual(MCSTR("text/plain"))) { + mime = get_plain_text_part(builder, MCUTF8(att->mimeType()), MCUTF8(att->charset()), + MCUTF8(att->contentID()), + MIME_ENCODED_STR(att->contentDescription()), + data->bytes(), data->length(), + contentTypeParameters, + forEncryption); + } + else if (att->isInlineAttachment() && att->mimeType()->lowercaseString()->hasPrefix(MCSTR("text/"))) { + mime = get_other_text_part(builder, MCUTF8(att->mimeType()), MCUTF8(att->charset()), + MCUTF8(att->contentID()), + MIME_ENCODED_STR(att->contentDescription()), + data->bytes(), data->length(), + contentTypeParameters); + } + else { + mime = get_file_part(builder, MIME_ENCODED_STR(att->filename()), + MCUTF8(att->mimeType()), att->isInlineAttachment(), + MCUTF8(att->contentID()), + MIME_ENCODED_STR(att->contentDescription()), + data->bytes(), data->length(), + contentTypeParameters); + } + if (contentTypeParameters != NULL) { + clist_free(contentTypeParameters); + } + } + return mime; +} + +static struct mailmime * multipart_related_from_attachments(MessageBuilder * builder, + Attachment * htmlAttachment, + Array * attachments, const char * boundary_prefix, bool forEncryption) +{ + if ((attachments != NULL) && (attachments->count() > 0)) { + struct mailmime * submime; + struct mailmime * mime; + + mime = get_multipart_related(builder, boundary_prefix); + + submime = mime_from_attachment(builder, htmlAttachment, forEncryption); + add_attachment(builder, mime, submime, boundary_prefix); + + for(unsigned int i = 0 ; i < attachments->count() ; i ++) { + Attachment * attachment; + + attachment = (Attachment *) attachments->objectAtIndex(i); + submime = mime_from_attachment(builder, attachment, forEncryption); + add_attachment(builder, mime, submime, boundary_prefix); + } + + return mime; + } + else { + struct mailmime * mime; + + mime = mime_from_attachment(builder, htmlAttachment, forEncryption); + + return mime; + } +} + +static struct mailmime * +part_new_empty(MessageBuilder * builder, struct mailmime_content * content, + struct mailmime_fields * mime_fields, + const char * boundary_prefix, + int force_single) +{ + struct mailmime * build_info; + clist * list; + int r; + int mime_type; + + list = NULL; + + if (force_single) { + mime_type = MAILMIME_SINGLE; + } + else { + switch (content->ct_type->tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + mime_type = MAILMIME_SINGLE; + break; + + case MAILMIME_TYPE_COMPOSITE_TYPE: + switch (content->ct_type->tp_data.tp_composite_type->ct_type) { + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + mime_type = MAILMIME_MULTIPLE; + break; + + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + if (strcasecmp(content->ct_subtype, "rfc822") == 0) + mime_type = MAILMIME_MESSAGE; + else + mime_type = MAILMIME_SINGLE; + break; + + default: + goto err; + } + break; + + default: + goto err; + } + } + + if (mime_type == MAILMIME_MULTIPLE) { + char * attr_name; + char * attr_value; + struct mailmime_parameter * param; + clist * parameters; + char * boundary; + + list = clist_new(); + if (list == NULL) + goto err; + + attr_name = strdup("boundary"); + if (attr_name == NULL) + goto free_list; + + if (builder != NULL) { + String * boundaryString = builder->nextBoundary(); + boundary = strdup(boundaryString->UTF8Characters()); + } + else { + boundary = generate_boundary(boundary_prefix); + } + attr_value = boundary; + if (attr_name == NULL) { + free(attr_name); + goto free_list; + } + + param = mailmime_parameter_new(attr_name, attr_value); + if (param == NULL) { + free(attr_value); + free(attr_name); + goto free_list; + } + + if (content->ct_parameters == NULL) { + parameters = clist_new(); + if (parameters == NULL) { + mailmime_parameter_free(param); + goto free_list; + } + } + else + parameters = content->ct_parameters; + + r = clist_append(parameters, param); + if (r != 0) { + clist_free(parameters); + mailmime_parameter_free(param); + goto free_list; + } + + if (content->ct_parameters == NULL) + content->ct_parameters = parameters; + } + + build_info = mailmime_new(mime_type, + NULL, 0, mime_fields, content, + NULL, NULL, NULL, list, + NULL, NULL); + if (build_info == NULL) { + clist_free(list); + return NULL; + } + + return build_info; + +free_list: + clist_free(list); +err: + return NULL; +} + +struct mailmime * part_multiple_new(MessageBuilder * builder, const char * type, const char * boundary_prefix) +{ + struct mailmime_fields * mime_fields; + struct mailmime_content * content; + struct mailmime * mp; + + mime_fields = mailmime_fields_new_empty(); + if (mime_fields == NULL) + goto err; + + content = mailmime_content_new_with_str(type); + if (content == NULL) + goto free_fields; + + mp = part_new_empty(builder, content, mime_fields, boundary_prefix, 0); + if (mp == NULL) + goto free_content; + + return mp; + +free_content: + mailmime_content_free(content); +free_fields: + mailmime_fields_free(mime_fields); +err: + return NULL; +} + +#define MAX_MESSAGE_ID 512 + +static char * generate_boundary(const char * boundary_prefix) +{ + char id[MAX_MESSAGE_ID]; + time_t now; + char name[MAX_MESSAGE_ID]; + long value; + + now = time(NULL); + value = random(); + + gethostname(name, MAX_MESSAGE_ID); + + if (boundary_prefix == NULL) + boundary_prefix = ""; + + snprintf(id, MAX_MESSAGE_ID, "%s%lx_%lx_%x", boundary_prefix, now, value, getpid()); + + return strdup(id); +} + +void MessageBuilder::init() +{ + mHTMLBody = NULL; + mTextBody = NULL; + mAttachments = NULL; + mRelatedAttachments = NULL; + mBoundaryPrefix = NULL; + mBoundaries = new Array(); + mCurrentBoundaryIndex = 0; +} + +MessageBuilder::MessageBuilder() +{ + init(); +} + +MessageBuilder::MessageBuilder(MessageBuilder * other) : AbstractMessage(other) +{ + init(); + setHTMLBody(other->mHTMLBody); + setTextBody(other->mTextBody); + setAttachments(other->mAttachments); + setRelatedAttachments(other->mRelatedAttachments); + MC_SAFE_REPLACE_COPY(String, mBoundaryPrefix, other->mBoundaryPrefix); +} + +MessageBuilder::~MessageBuilder() +{ + MC_SAFE_RELEASE(mHTMLBody); + MC_SAFE_RELEASE(mTextBody); + MC_SAFE_RELEASE(mAttachments); + MC_SAFE_RELEASE(mRelatedAttachments); + MC_SAFE_RELEASE(mBoundaryPrefix); + MC_SAFE_RELEASE(mBoundaries); +} + +String * MessageBuilder::description() +{ + String * result = String::string(); + result->appendUTF8Format("<%s:%p\n", className()->UTF8Characters(), this); + if (header() != NULL) { + result->appendString(header()->description()); + result->appendUTF8Characters("\n"); + } + if (mHTMLBody != NULL) { + result->appendUTF8Characters("-- html body --\n"); + result->appendString(mHTMLBody); + result->appendUTF8Characters("\n"); + } + if (mTextBody != NULL) { + result->appendUTF8Characters("-- text body --\n"); + result->appendString(mTextBody); + result->appendUTF8Characters("\n"); + } + if (mAttachments != NULL) { + result->appendUTF8Characters("-- attachments --\n"); + result->appendString(mAttachments->description()); + result->appendUTF8Characters("\n"); + } + if (mRelatedAttachments != NULL) { + result->appendUTF8Characters("-- related attachments --\n"); + result->appendString(mRelatedAttachments->description()); + result->appendUTF8Characters("\n"); + } + result->appendUTF8Characters(">"); + + return result; +} + +Object * MessageBuilder::copy() +{ + return new MessageBuilder(this); +} + +void MessageBuilder::setHTMLBody(String * htmlBody) +{ + MC_SAFE_REPLACE_COPY(String, mHTMLBody, htmlBody); +} + +String * MessageBuilder::htmlBody() +{ + return mHTMLBody; +} + +void MessageBuilder::setTextBody(String * textBody) +{ + MC_SAFE_REPLACE_COPY(String, mTextBody, textBody); +} + +String * MessageBuilder::textBody() +{ + return mTextBody; +} + +void MessageBuilder::setAttachments(Array * attachments) +{ + MC_SAFE_REPLACE_COPY(Array, mAttachments, attachments); +} + +Array * MessageBuilder::attachments() +{ + return mAttachments; +} + +void MessageBuilder::addAttachment(Attachment * attachment) +{ + if (attachment == NULL) { + return; + } + if (mAttachments == NULL) { + mAttachments = new Array(); + } + mAttachments->addObject(attachment); +} + +void MessageBuilder::setRelatedAttachments(Array * attachments) +{ + MC_SAFE_REPLACE_COPY(Array, mRelatedAttachments, attachments); +} + +Array * MessageBuilder::relatedAttachments() +{ + return mRelatedAttachments; +} + +void MessageBuilder::addRelatedAttachment(Attachment * attachment) +{ + if (attachment == NULL) { + return; + } + if (mRelatedAttachments == NULL) { + mRelatedAttachments = new Array(); + } + mRelatedAttachments->addObject(attachment); +} + +void MessageBuilder::setBoundaryPrefix(String * boundaryPrefix) +{ + MC_SAFE_REPLACE_COPY(String, mBoundaryPrefix, boundaryPrefix); +} + +String * MessageBuilder::boundaryPrefix() +{ + return mBoundaryPrefix; +} + +struct mailmime * MessageBuilder::mimeAndFilterBccAndForEncryption(bool filterBcc, bool forEncryption) +{ + struct mailmime * htmlPart; + struct mailmime * textPart; + struct mailmime * altPart; + struct mailmime * mainPart; + + mCurrentBoundaryIndex = 0; + htmlPart = NULL; + textPart = NULL; + altPart = NULL; + mainPart = NULL; + + if (htmlBody() != NULL) { + Attachment * htmlAttachment; + + htmlAttachment = Attachment::attachmentWithHTMLString(htmlBody()); + htmlPart = multipart_related_from_attachments(this, htmlAttachment, mRelatedAttachments, + MCUTF8(mBoundaryPrefix), forEncryption); + } + + if (textBody() != NULL) { + Attachment * textAttachment; + + textAttachment = Attachment::attachmentWithText(textBody()); + textPart = mime_from_attachment(this, textAttachment, forEncryption); + } + else if (htmlBody() != NULL) { + Attachment * textAttachment; + + textAttachment = Attachment::attachmentWithText(htmlBody()->flattenHTML()); + textPart = mime_from_attachment(this, textAttachment, forEncryption); + } + + if ((textPart != NULL) && (htmlPart != NULL)) { + altPart = get_multipart_alternative(this, MCUTF8(mBoundaryPrefix)); + mailmime_smart_add_part(altPart, textPart); + mailmime_smart_add_part(altPart, htmlPart); + mainPart = altPart; + } + else if (textPart != NULL) { + mainPart = textPart; + } + else if (htmlPart != NULL) { + mainPart = htmlPart; + } + + struct mailimf_fields * fields; + unsigned int i; + struct mailmime * mime; + + fields = header()->createIMFFieldsAndFilterBcc(filterBcc); + + mime = mailmime_new_message_data(NULL); + mailmime_set_imf_fields(mime, fields); + + if (mainPart != NULL) { + add_attachment(this, mime, mainPart, MCUTF8(mBoundaryPrefix)); + } + + if (attachments() != NULL) { + for(i = 0 ; i < attachments()->count() ; i ++) { + Attachment * attachment; + struct mailmime * submime; + + attachment = (Attachment *) attachments()->objectAtIndex(i); + submime = mime_from_attachment(this, attachment, forEncryption); + add_attachment(this, mime, submime, MCUTF8(mBoundaryPrefix)); + } + } + + struct mailmime * result = mime; + if (forEncryption) { + result = mime->mm_data.mm_message.mm_msg_mime; + mime->mm_data.mm_message.mm_msg_mime = NULL; + mailmime_free(mime); + } + + return result; +} + +Data * MessageBuilder::dataAndFilterBccAndForEncryption(bool filterBcc, bool forEncryption) +{ + Data * data; + MMAPString * str; + int col; + + str = mmap_string_new(""); + col = 0; + struct mailmime * mime = mimeAndFilterBccAndForEncryption(filterBcc, forEncryption); + mailmime_write_mem(str, &col, mime); + data = Data::dataWithBytes(str->str, (unsigned int) str->len); + mmap_string_free(str); + mailmime_free(mime); + + return data; +} + +Data * MessageBuilder::data() +{ + return dataAndFilterBccAndForEncryption(false, false); +} + +Data * MessageBuilder::dataForEncryption() +{ + return dataAndFilterBccAndForEncryption(false, true); +} + +String * MessageBuilder::htmlRendering(HTMLRendererTemplateCallback * htmlCallback) +{ + MessageParser * message = MessageParser::messageParserWithData(data()); + return message->htmlRendering(htmlCallback); +} + +String * MessageBuilder::htmlBodyRendering() +{ + MessageParser * message = MessageParser::messageParserWithData(data()); + return message->htmlBodyRendering(); +} + +String * MessageBuilder::plainTextRendering() +{ + MessageParser * message = MessageParser::messageParserWithData(data()); + return message->plainTextRendering(); +} + +String * MessageBuilder::plainTextBodyRendering(bool stripWhitespace) +{ + MessageParser * message = MessageParser::messageParserWithData(data()); + return message->plainTextBodyRendering(stripWhitespace); +} + +struct mailmime * get_signature_part(Data * signature) +{ + struct mailmime * mime; + struct mailmime_content * content; + + content = mailmime_content_new_with_str("application/pgp-signature"); + struct mailmime_fields * mime_fields = mailmime_fields_new_empty(); + mime = part_new_empty(NULL, content, mime_fields, NULL, 1); + mailmime_set_body_text(mime, signature->bytes(), signature->length()); + + return mime; +} + +Data * MessageBuilder::openPGPSignedMessageDataWithSignatureData(Data * signature) +{ + struct mailimf_fields * fields; + struct mailmime * mime; + + fields = header()->createIMFFieldsAndFilterBcc(false); + + mime = mailmime_new_message_data(NULL); + mailmime_set_imf_fields(mime, fields); + + struct mailmime * multipart = get_multipart_signed_pgp(NULL, MCUTF8(boundaryPrefix())); + add_attachment(NULL, mime, multipart, MCUTF8(boundaryPrefix())); + struct mailmime * part_to_sign = mimeAndFilterBccAndForEncryption(false, true); + add_attachment(NULL, multipart, part_to_sign, MCUTF8(boundaryPrefix())); + struct mailmime * signature_part = get_signature_part(signature); + add_attachment(NULL, multipart, signature_part, MCUTF8(boundaryPrefix())); + + MMAPString * str = mmap_string_new(""); + int col = 0; + + mailmime_write_mem(str, &col, mime); + Data * data = Data::dataWithBytes(str->str, (unsigned int) str->len); + mmap_string_free(str); + mailmime_free(mime); + + return data; +} + +static struct mailmime * get_pgp_version_part(void) +{ + struct mailmime * mime; + struct mailmime_content * content; + + content = mailmime_content_new_with_str("application/pgp-encrypted"); + struct mailmime_fields * mime_fields = mailmime_fields_new_empty(); + mime = part_new_empty(NULL, content, mime_fields, NULL, 1); + const char * version = "Version: 1\r\n"; + mailmime_set_body_text(mime, (char *) version, strlen(version)); + + return mime; +} + +static struct mailmime * get_encrypted_part(Data * encryptedData) +{ + struct mailmime * mime; + struct mailmime_content * content; + + content = mailmime_content_new_with_str("application/octet-stream"); + struct mailmime_fields * mime_fields = mailmime_fields_new_empty(); + mime = part_new_empty(NULL, content, mime_fields, NULL, 1); + mailmime_set_body_text(mime, encryptedData->bytes(), encryptedData->length()); + + return mime; +} + +Data * MessageBuilder::openPGPEncryptedMessageDataWithEncryptedData(Data * encryptedData) +{ + struct mailimf_fields * fields; + struct mailmime * mime; + + fields = header()->createIMFFieldsAndFilterBcc(false); + + mime = mailmime_new_message_data(NULL); + mailmime_set_imf_fields(mime, fields); + + struct mailmime * multipart = get_multipart_encrypted_pgp(NULL, MCUTF8(boundaryPrefix())); + add_attachment(NULL, mime, multipart, MCUTF8(boundaryPrefix())); + + struct mailmime * version_part = get_pgp_version_part(); + add_attachment(NULL, multipart, version_part, MCUTF8(boundaryPrefix())); + struct mailmime * encrypted_part = get_encrypted_part(encryptedData); + add_attachment(NULL, multipart, encrypted_part, MCUTF8(boundaryPrefix())); + + MMAPString * str = mmap_string_new(""); + int col = 0; + + mailmime_write_mem(str, &col, mime); + Data * data = Data::dataWithBytes(str->str, (unsigned int) str->len); + mmap_string_free(str); + mailmime_free(mime); + + return data; +} + +String * MessageBuilder::nextBoundary() +{ + unsigned int idx = mCurrentBoundaryIndex; + mCurrentBoundaryIndex ++; + if (idx < mBoundaries->count()) { + return (String *) mBoundaries->objectAtIndex(idx); + } + + char * boundary = generate_boundary(MCUTF8(mBoundaryPrefix)); + String * boundaryString = String::stringWithUTF8Characters(boundary); + mBoundaries->addObject(boundaryString); + free(boundary); + + return boundaryString; +} + +void MessageBuilder::resetBoundaries() +{ + mBoundaries->removeAllObjects(); +} + +void MessageBuilder::setBoundaries(Array * boundaries) +{ + resetBoundaries(); + mBoundaries->addObjectsFromArray(boundaries); +} diff --git a/src/core/rfc822/MCMessageParser.cc b/src/core/rfc822/MCMessageParser.cc deleted file mode 100644 index 404bc862..00000000 --- a/src/core/rfc822/MCMessageParser.cc +++ /dev/null @@ -1,179 +0,0 @@ -#include "MCMessageParser.h" - -#include -#if __APPLE__ -#include -#endif - -#include "MCAttachment.h" -#include "MCMessageHeader.h" -#include "MCHTMLRenderer.h" -#include "MCHTMLBodyRendererTemplateCallback.h" - -using namespace mailcore; - -MessageParser * MessageParser::messageParserWithData(Data * data) -{ - MessageParser * parser = new MessageParser(data); - return (MessageParser *) parser->autorelease(); -} - -MessageParser * MessageParser::messageParserWithContentsOfFile(String * filename) -{ - Data * data = Data::dataWithContentsOfFile(filename); - return messageParserWithData(data); -} - -void MessageParser::init() -{ - mData = NULL; - mMainPart = NULL; -#if __APPLE__ - mNSData = NULL; -#endif -} - -void MessageParser::setBytes(char * dataBytes, unsigned int dataLength) -{ - const char * start = NULL; - unsigned int length = 0; - if (dataLength > 5) { - if (strncmp(dataBytes, "From ", 5) == 0) { - start = dataBytes; - for(unsigned int i = 0 ; i < dataLength ; i ++) { - if (start[i] == '\n') { - start = start + i + 1; - length = dataLength - (i + 1); - break; - } - } - } - } - if (start != NULL) { - dataBytes = (char *) start; - dataLength = length; - } - - mailmessage * msg; - struct mailmime * mime; - - msg = data_message_init(dataBytes, dataLength); - mailmessage_get_bodystructure(msg, &mime); - mMainPart = (AbstractPart *) Attachment::attachmentsWithMIME(msg->msg_mime)->retain(); - mMainPart->applyUniquePartID(); - - size_t cur_token = 0; - struct mailimf_fields * fields; - int r = mailimf_envelope_and_optional_fields_parse(dataBytes, dataLength, &cur_token, &fields); - if (r == MAILIMAP_NO_ERROR) { - header()->importIMFFields(fields); - mailimf_fields_free(fields); - } - mailmessage_free(msg); -} - -MessageParser::MessageParser(Data * data) -{ - init(); - - setBytes(data->bytes(), data->length()); - mData = (Data *) data->retain(); -} - -MessageParser::MessageParser(MessageParser * other) : AbstractMessage(other) -{ - init(); - MC_SAFE_REPLACE_RETAIN(Data, mData, other->mData); - MC_SAFE_REPLACE_RETAIN(AbstractPart, mMainPart, other->mMainPart); -} - -MessageParser::~MessageParser() -{ - MC_SAFE_RELEASE(mMainPart); - MC_SAFE_RELEASE(mData); -#if __APPLE__ - if (mNSData != NULL) { - CFRelease(mNSData); - } -#endif -} - -AbstractPart * MessageParser::mainPart() -{ - return mMainPart; -} - -Data * MessageParser::data() -{ -#if __APPLE__ - if (mNSData != NULL) { - return dataFromNSData(); - } -#endif - return mData; -} - -String * MessageParser::description() -{ - String * result = String::string(); - result->appendUTF8Format("<%s:%p ", MCUTF8(className()), this); - result->appendUTF8Format("<%p>", mMainPart); - result->appendString(mMainPart->description()); - result->appendUTF8Characters(">"); - - return result; -} - -HashMap * MessageParser::serializable() -{ - HashMap * result = AbstractMessage::serializable(); - if (mMainPart != NULL) { - result->setObjectForKey(MCSTR("mainPart"), mMainPart->serializable()); - } - return result; -} - -Object * MessageParser::copy() -{ - return new MessageParser(this); -} - -AbstractPart * MessageParser::partForContentID(String * contentID) -{ - return mainPart()->partForContentID(contentID); -} - -AbstractPart * MessageParser::partForUniqueID(String * uniqueID) -{ - return mainPart()->partForUniqueID(uniqueID); -} - -String * MessageParser::htmlRendering(HTMLRendererTemplateCallback * htmlCallback) -{ - return HTMLRenderer::htmlForRFC822Message(this, htmlCallback); -} - -String * MessageParser::htmlBodyRendering() -{ - HTMLBodyRendererTemplateCallback * callback = new HTMLBodyRendererTemplateCallback(); - String * result = htmlRendering(callback); - MC_SAFE_RELEASE(callback); - return result; -} - -String * MessageParser::plainTextRendering() -{ - String * html = htmlRendering(NULL); - return html->flattenHTML(); -} - -String * MessageParser::plainTextBodyRendering(bool stripWhitespace) -{ - String * html = htmlBodyRendering(); - String * plainTextBodyString = html->flattenHTML(); - - if (stripWhitespace) { - plainTextBodyString = plainTextBodyString->stripWhitespace(); - } - return plainTextBodyString; -} diff --git a/src/core/rfc822/MCMessageParser.cpp b/src/core/rfc822/MCMessageParser.cpp new file mode 100644 index 00000000..404bc862 --- /dev/null +++ b/src/core/rfc822/MCMessageParser.cpp @@ -0,0 +1,179 @@ +#include "MCMessageParser.h" + +#include +#if __APPLE__ +#include +#endif + +#include "MCAttachment.h" +#include "MCMessageHeader.h" +#include "MCHTMLRenderer.h" +#include "MCHTMLBodyRendererTemplateCallback.h" + +using namespace mailcore; + +MessageParser * MessageParser::messageParserWithData(Data * data) +{ + MessageParser * parser = new MessageParser(data); + return (MessageParser *) parser->autorelease(); +} + +MessageParser * MessageParser::messageParserWithContentsOfFile(String * filename) +{ + Data * data = Data::dataWithContentsOfFile(filename); + return messageParserWithData(data); +} + +void MessageParser::init() +{ + mData = NULL; + mMainPart = NULL; +#if __APPLE__ + mNSData = NULL; +#endif +} + +void MessageParser::setBytes(char * dataBytes, unsigned int dataLength) +{ + const char * start = NULL; + unsigned int length = 0; + if (dataLength > 5) { + if (strncmp(dataBytes, "From ", 5) == 0) { + start = dataBytes; + for(unsigned int i = 0 ; i < dataLength ; i ++) { + if (start[i] == '\n') { + start = start + i + 1; + length = dataLength - (i + 1); + break; + } + } + } + } + if (start != NULL) { + dataBytes = (char *) start; + dataLength = length; + } + + mailmessage * msg; + struct mailmime * mime; + + msg = data_message_init(dataBytes, dataLength); + mailmessage_get_bodystructure(msg, &mime); + mMainPart = (AbstractPart *) Attachment::attachmentsWithMIME(msg->msg_mime)->retain(); + mMainPart->applyUniquePartID(); + + size_t cur_token = 0; + struct mailimf_fields * fields; + int r = mailimf_envelope_and_optional_fields_parse(dataBytes, dataLength, &cur_token, &fields); + if (r == MAILIMAP_NO_ERROR) { + header()->importIMFFields(fields); + mailimf_fields_free(fields); + } + mailmessage_free(msg); +} + +MessageParser::MessageParser(Data * data) +{ + init(); + + setBytes(data->bytes(), data->length()); + mData = (Data *) data->retain(); +} + +MessageParser::MessageParser(MessageParser * other) : AbstractMessage(other) +{ + init(); + MC_SAFE_REPLACE_RETAIN(Data, mData, other->mData); + MC_SAFE_REPLACE_RETAIN(AbstractPart, mMainPart, other->mMainPart); +} + +MessageParser::~MessageParser() +{ + MC_SAFE_RELEASE(mMainPart); + MC_SAFE_RELEASE(mData); +#if __APPLE__ + if (mNSData != NULL) { + CFRelease(mNSData); + } +#endif +} + +AbstractPart * MessageParser::mainPart() +{ + return mMainPart; +} + +Data * MessageParser::data() +{ +#if __APPLE__ + if (mNSData != NULL) { + return dataFromNSData(); + } +#endif + return mData; +} + +String * MessageParser::description() +{ + String * result = String::string(); + result->appendUTF8Format("<%s:%p ", MCUTF8(className()), this); + result->appendUTF8Format("<%p>", mMainPart); + result->appendString(mMainPart->description()); + result->appendUTF8Characters(">"); + + return result; +} + +HashMap * MessageParser::serializable() +{ + HashMap * result = AbstractMessage::serializable(); + if (mMainPart != NULL) { + result->setObjectForKey(MCSTR("mainPart"), mMainPart->serializable()); + } + return result; +} + +Object * MessageParser::copy() +{ + return new MessageParser(this); +} + +AbstractPart * MessageParser::partForContentID(String * contentID) +{ + return mainPart()->partForContentID(contentID); +} + +AbstractPart * MessageParser::partForUniqueID(String * uniqueID) +{ + return mainPart()->partForUniqueID(uniqueID); +} + +String * MessageParser::htmlRendering(HTMLRendererTemplateCallback * htmlCallback) +{ + return HTMLRenderer::htmlForRFC822Message(this, htmlCallback); +} + +String * MessageParser::htmlBodyRendering() +{ + HTMLBodyRendererTemplateCallback * callback = new HTMLBodyRendererTemplateCallback(); + String * result = htmlRendering(callback); + MC_SAFE_RELEASE(callback); + return result; +} + +String * MessageParser::plainTextRendering() +{ + String * html = htmlRendering(NULL); + return html->flattenHTML(); +} + +String * MessageParser::plainTextBodyRendering(bool stripWhitespace) +{ + String * html = htmlBodyRendering(); + String * plainTextBodyString = html->flattenHTML(); + + if (stripWhitespace) { + plainTextBodyString = plainTextBodyString->stripWhitespace(); + } + return plainTextBodyString; +} diff --git a/src/core/rfc822/MCMessagePart.cc b/src/core/rfc822/MCMessagePart.cc deleted file mode 100644 index 21d61181..00000000 --- a/src/core/rfc822/MCMessagePart.cc +++ /dev/null @@ -1,20 +0,0 @@ -#include "MCMessagePart.h" - -using namespace mailcore; - -MessagePart::MessagePart() -{ -} - -MessagePart::MessagePart(MessagePart * other) : AbstractMessagePart(other) -{ -} - -MessagePart::~MessagePart() -{ -} - -Object * MessagePart::copy() -{ - return new MessagePart(this); -} diff --git a/src/core/rfc822/MCMessagePart.cpp b/src/core/rfc822/MCMessagePart.cpp new file mode 100644 index 00000000..21d61181 --- /dev/null +++ b/src/core/rfc822/MCMessagePart.cpp @@ -0,0 +1,20 @@ +#include "MCMessagePart.h" + +using namespace mailcore; + +MessagePart::MessagePart() +{ +} + +MessagePart::MessagePart(MessagePart * other) : AbstractMessagePart(other) +{ +} + +MessagePart::~MessagePart() +{ +} + +Object * MessagePart::copy() +{ + return new MessagePart(this); +} diff --git a/src/core/rfc822/MCMultipart.cc b/src/core/rfc822/MCMultipart.cc deleted file mode 100644 index e048669e..00000000 --- a/src/core/rfc822/MCMultipart.cc +++ /dev/null @@ -1,21 +0,0 @@ -#include "MCMultipart.h" - -using namespace mailcore; - -Multipart::Multipart() -{ -} - -Multipart::Multipart(Multipart * other) : AbstractMultipart(other) -{ -} - -Multipart::~Multipart() -{ -} - -Object * Multipart::copy() -{ - return new Multipart(this); -} - diff --git a/src/core/rfc822/MCMultipart.cpp b/src/core/rfc822/MCMultipart.cpp new file mode 100644 index 00000000..e048669e --- /dev/null +++ b/src/core/rfc822/MCMultipart.cpp @@ -0,0 +1,21 @@ +#include "MCMultipart.h" + +using namespace mailcore; + +Multipart::Multipart() +{ +} + +Multipart::Multipart(Multipart * other) : AbstractMultipart(other) +{ +} + +Multipart::~Multipart() +{ +} + +Object * Multipart::copy() +{ + return new Multipart(this); +} + diff --git a/src/core/security/MCCertificateUtils.cc b/src/core/security/MCCertificateUtils.cc deleted file mode 100644 index 42b75916..00000000 --- a/src/core/security/MCCertificateUtils.cc +++ /dev/null @@ -1,162 +0,0 @@ -// -// MCCertificateUtils.cc -// mailcore2 -// -// Created by DINH Viêt Hoà on 7/25/13. -// Copyright (c) 2013 MailCore. All rights reserved. -// - -#include "MCCertificateUtils.h" - -#if __APPLE__ -#include -#include -#else -#include -#include -#include -#include -#include -#endif - -#include "MCLog.h" - -bool mailcore::checkCertificate(mailstream * stream, String * hostname) -{ -#if __APPLE__ - bool result = false; - CFStringRef hostnameCFString; - SecPolicyRef policy; - CFMutableArrayRef certificates; - SecTrustRef trust = NULL; - SecTrustResultType trustResult; - OSStatus status; - - carray * cCerts = mailstream_get_certificate_chain(stream); - if (cCerts == NULL) { - fprintf(stderr, "warning: No certificate chain retrieved"); - goto err; - } - - hostnameCFString = CFStringCreateWithCharacters(NULL, (const UniChar *) hostname->unicodeCharacters(), - hostname->length()); - policy = SecPolicyCreateSSL(true, hostnameCFString); - certificates = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - - for(unsigned int i = 0 ; i < carray_count(cCerts) ; i ++) { - MMAPString * str; - str = (MMAPString *) carray_get(cCerts, i); - CFDataRef data = CFDataCreate(NULL, (const UInt8 *) str->str, (CFIndex) str->len); - SecCertificateRef cert = SecCertificateCreateWithData(NULL, data); - CFArrayAppendValue(certificates, cert); - CFRelease(data); - CFRelease(cert); - } - - static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; - - // The below API calls are not thread safe. We're making sure not to call the concurrently. - pthread_mutex_lock(&lock); - - status = SecTrustCreateWithCertificates(certificates, policy, &trust); - if (status != noErr) { - pthread_mutex_unlock(&lock); - goto free_certs; - } - - status = SecTrustEvaluate(trust, &trustResult); - if (status != noErr) { - pthread_mutex_unlock(&lock); - goto free_certs; - } - - pthread_mutex_unlock(&lock); - - switch (trustResult) { - case kSecTrustResultUnspecified: - case kSecTrustResultProceed: - // certificate chain is ok - result = true; - break; - - default: - // certificate chain is invalid - break; - } - - CFRelease(trust); -free_certs: - CFRelease(certificates); - mailstream_certificate_chain_free(cCerts); - CFRelease(policy); - CFRelease(hostnameCFString); -err: - return result; -#else - bool result = false; - X509_STORE * store = NULL; - X509_STORE_CTX * storectx = NULL; - STACK_OF(X509) * certificates = NULL; - int status; - - carray * cCerts = mailstream_get_certificate_chain(stream); - if (cCerts == NULL) { - fprintf(stderr, "warning: No certificate chain retrieved"); - goto err; - } - - store = X509_STORE_new(); - if (store == NULL) { - goto free_certs; - } - - status = X509_STORE_set_default_paths(store); - if (status != 1) { - printf("Error loading the system-wide CA certificates"); - } - - certificates = sk_X509_new_null(); - for(unsigned int i = 0 ; i < carray_count(cCerts) ; i ++) { - MMAPString * str; - str = (MMAPString *) carray_get(cCerts, i); - if (str == NULL) { - goto free_certs; - } - BIO *bio = BIO_new_mem_buf((void *) str->str, str->len); - X509 *certificate = d2i_X509_bio(bio, NULL); - BIO_free(bio); - if (!sk_X509_push(certificates, certificate)) { - goto free_certs; - } - } - - storectx = X509_STORE_CTX_new(); - if (storectx == NULL) { - goto free_certs; - } - - status = X509_STORE_CTX_init(storectx, store, sk_X509_value(certificates, 0), certificates); - if (status != 1) { - goto free_certs; - } - - status = X509_verify_cert(storectx); - if (status == 1) { - result = true; - } - -free_certs: - mailstream_certificate_chain_free(cCerts); - if (certificates != NULL) { - sk_X509_pop_free((STACK_OF(X509) *) certificates, X509_free); - } - if (storectx != NULL) { - X509_STORE_CTX_free(storectx); - } - if (store != NULL) { - X509_STORE_free(store); - } -err: - return result; -#endif -} diff --git a/src/core/security/MCCertificateUtils.cpp b/src/core/security/MCCertificateUtils.cpp new file mode 100644 index 00000000..42b75916 --- /dev/null +++ b/src/core/security/MCCertificateUtils.cpp @@ -0,0 +1,162 @@ +// +// MCCertificateUtils.cc +// mailcore2 +// +// Created by DINH Viêt Hoà on 7/25/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCCertificateUtils.h" + +#if __APPLE__ +#include +#include +#else +#include +#include +#include +#include +#include +#endif + +#include "MCLog.h" + +bool mailcore::checkCertificate(mailstream * stream, String * hostname) +{ +#if __APPLE__ + bool result = false; + CFStringRef hostnameCFString; + SecPolicyRef policy; + CFMutableArrayRef certificates; + SecTrustRef trust = NULL; + SecTrustResultType trustResult; + OSStatus status; + + carray * cCerts = mailstream_get_certificate_chain(stream); + if (cCerts == NULL) { + fprintf(stderr, "warning: No certificate chain retrieved"); + goto err; + } + + hostnameCFString = CFStringCreateWithCharacters(NULL, (const UniChar *) hostname->unicodeCharacters(), + hostname->length()); + policy = SecPolicyCreateSSL(true, hostnameCFString); + certificates = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + + for(unsigned int i = 0 ; i < carray_count(cCerts) ; i ++) { + MMAPString * str; + str = (MMAPString *) carray_get(cCerts, i); + CFDataRef data = CFDataCreate(NULL, (const UInt8 *) str->str, (CFIndex) str->len); + SecCertificateRef cert = SecCertificateCreateWithData(NULL, data); + CFArrayAppendValue(certificates, cert); + CFRelease(data); + CFRelease(cert); + } + + static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + + // The below API calls are not thread safe. We're making sure not to call the concurrently. + pthread_mutex_lock(&lock); + + status = SecTrustCreateWithCertificates(certificates, policy, &trust); + if (status != noErr) { + pthread_mutex_unlock(&lock); + goto free_certs; + } + + status = SecTrustEvaluate(trust, &trustResult); + if (status != noErr) { + pthread_mutex_unlock(&lock); + goto free_certs; + } + + pthread_mutex_unlock(&lock); + + switch (trustResult) { + case kSecTrustResultUnspecified: + case kSecTrustResultProceed: + // certificate chain is ok + result = true; + break; + + default: + // certificate chain is invalid + break; + } + + CFRelease(trust); +free_certs: + CFRelease(certificates); + mailstream_certificate_chain_free(cCerts); + CFRelease(policy); + CFRelease(hostnameCFString); +err: + return result; +#else + bool result = false; + X509_STORE * store = NULL; + X509_STORE_CTX * storectx = NULL; + STACK_OF(X509) * certificates = NULL; + int status; + + carray * cCerts = mailstream_get_certificate_chain(stream); + if (cCerts == NULL) { + fprintf(stderr, "warning: No certificate chain retrieved"); + goto err; + } + + store = X509_STORE_new(); + if (store == NULL) { + goto free_certs; + } + + status = X509_STORE_set_default_paths(store); + if (status != 1) { + printf("Error loading the system-wide CA certificates"); + } + + certificates = sk_X509_new_null(); + for(unsigned int i = 0 ; i < carray_count(cCerts) ; i ++) { + MMAPString * str; + str = (MMAPString *) carray_get(cCerts, i); + if (str == NULL) { + goto free_certs; + } + BIO *bio = BIO_new_mem_buf((void *) str->str, str->len); + X509 *certificate = d2i_X509_bio(bio, NULL); + BIO_free(bio); + if (!sk_X509_push(certificates, certificate)) { + goto free_certs; + } + } + + storectx = X509_STORE_CTX_new(); + if (storectx == NULL) { + goto free_certs; + } + + status = X509_STORE_CTX_init(storectx, store, sk_X509_value(certificates, 0), certificates); + if (status != 1) { + goto free_certs; + } + + status = X509_verify_cert(storectx); + if (status == 1) { + result = true; + } + +free_certs: + mailstream_certificate_chain_free(cCerts); + if (certificates != NULL) { + sk_X509_pop_free((STACK_OF(X509) *) certificates, X509_free); + } + if (storectx != NULL) { + X509_STORE_CTX_free(storectx); + } + if (store != NULL) { + X509_STORE_free(store); + } +err: + return result; +#endif +} diff --git a/src/core/smtp/MCSMTPSession.cc b/src/core/smtp/MCSMTPSession.cc deleted file mode 100644 index ad8b19e0..00000000 --- a/src/core/smtp/MCSMTPSession.cc +++ /dev/null @@ -1,804 +0,0 @@ -#include "MCWin32.h" // Should be included first. - -#include "MCSMTPSession.h" - -#include -#include - -#include "MCAddress.h" -#include "MCMessageBuilder.h" -#include "MCMessageParser.h" -#include "MCMessageHeader.h" -#include "MCSMTPProgressCallback.h" -#include "MCConnectionLoggerUtils.h" -#include "MCCertificateUtils.h" - -using namespace mailcore; - -enum { - STATE_DISCONNECTED, - STATE_CONNECTED, - STATE_LOGGEDIN, -}; - -void SMTPSession::init() -{ - mHostname = NULL; - mPort = 0; - mUsername = NULL; - mPassword = NULL; - mOAuth2Token = NULL; - mAuthType = AuthTypeSASLNone; - mConnectionType = ConnectionTypeClear; - mTimeout = 30; - mCheckCertificateEnabled = true; - mUseHeloIPEnabled = false; - mShouldDisconnect = false; - - mSmtp = NULL; - mProgressCallback = NULL; - mState = STATE_DISCONNECTED; - mLastSMTPResponse = NULL; - mLastLibetpanError = 0; - mLastSMTPResponseCode = 0; - mConnectionLogger = NULL; -} - -SMTPSession::SMTPSession() -{ - init(); -} - -SMTPSession::~SMTPSession() -{ - MC_SAFE_RELEASE(mLastSMTPResponse); - MC_SAFE_RELEASE(mHostname); - MC_SAFE_RELEASE(mUsername); - MC_SAFE_RELEASE(mPassword); - MC_SAFE_RELEASE(mOAuth2Token); -} - -void SMTPSession::setHostname(String * hostname) -{ - MC_SAFE_REPLACE_COPY(String, mHostname, hostname); -} - -String * SMTPSession::hostname() -{ - return mHostname; -} - -void SMTPSession::setPort(unsigned int port) -{ - mPort = port; -} - -unsigned int SMTPSession::port() -{ - return mPort; -} - -void SMTPSession::setUsername(String * username) -{ - MC_SAFE_REPLACE_COPY(String, mUsername, username); -} - -String * SMTPSession::username() -{ - return mUsername; -} - -void SMTPSession::setPassword(String * password) -{ - MC_SAFE_REPLACE_COPY(String, mPassword, password); -} - -String * SMTPSession::password() -{ - return mPassword; -} - -void SMTPSession::setOAuth2Token(String * token) -{ - MC_SAFE_REPLACE_COPY(String, mOAuth2Token, token); -} - -String * SMTPSession::OAuth2Token() -{ - return mOAuth2Token; -} - -void SMTPSession::setAuthType(AuthType authType) -{ - mAuthType = authType; -} - -AuthType SMTPSession::authType() -{ - return mAuthType; -} - -void SMTPSession::setConnectionType(ConnectionType connectionType) -{ - mConnectionType = connectionType; -} - -ConnectionType SMTPSession::connectionType() -{ - return mConnectionType; -} - -void SMTPSession::setTimeout(time_t timeout) -{ - mTimeout = timeout; -} - -time_t SMTPSession::timeout() -{ - return mTimeout; -} - -void SMTPSession::setCheckCertificateEnabled(bool enabled) -{ - mCheckCertificateEnabled = enabled; -} - -bool SMTPSession::isCheckCertificateEnabled() -{ - return mCheckCertificateEnabled; -} - -bool SMTPSession::checkCertificate() -{ - if (!isCheckCertificateEnabled()) - return true; - return mailcore::checkCertificate(mSmtp->stream, hostname()); -} - -void SMTPSession::setUseHeloIPEnabled(bool enabled) -{ - mUseHeloIPEnabled = enabled; -} - -bool SMTPSession::useHeloIPEnabled() -{ - return mUseHeloIPEnabled; -} - -void SMTPSession::body_progress(size_t current, size_t maximum, void * context) -{ - SMTPSession * session; - - session = (SMTPSession *) context; - session->bodyProgress((unsigned int) current, (unsigned int) maximum); -} - -void SMTPSession::bodyProgress(unsigned int current, unsigned int maximum) -{ - if (mProgressCallback != NULL) { - mProgressCallback->bodyProgress(this, current, maximum); - } -} - - -static void logger(mailsmtp * smtp, int log_type, const char * buffer, size_t size, void * context) -{ - SMTPSession * session = (SMTPSession *) context; - - if (session->connectionLogger() == NULL) - return; - - ConnectionLogType type = getConnectionType(log_type); - bool isBuffer = isBufferFromLogType(log_type); - - if (isBuffer) { - Data * data = Data::dataWithBytes(buffer, (unsigned int) size); - session->connectionLogger()->log(session, type, data); - } - else { - session->connectionLogger()->log(session, type, NULL); - } -} - - -void SMTPSession::setup() -{ - mSmtp = mailsmtp_new(0, NULL); - mailsmtp_set_timeout(mSmtp, timeout()); - mailsmtp_set_progress_callback(mSmtp, body_progress, this); - mailsmtp_set_logger(mSmtp, logger, this); -} - -void SMTPSession::unsetup() -{ - mailsmtp_free(mSmtp); - mSmtp = NULL; -} - -void SMTPSession::connectIfNeeded(ErrorCode * pError) -{ - if (mSmtp != NULL) { - // In case pipelining is available, libetpan will disconnect the session. - if (mSmtp->stream == NULL) { - mShouldDisconnect = true; - } - } - if (mShouldDisconnect) { - disconnect(); - mShouldDisconnect = false; - } - - if (mState == STATE_DISCONNECTED) { - connect(pError); - } - else { - * pError = ErrorNone; - } -} - -void SMTPSession::connect(ErrorCode * pError) -{ - int r; - - setup(); - - switch (mConnectionType) { - case ConnectionTypeStartTLS: - MCLog("connect %s %u", MCUTF8(hostname()), (unsigned int) port()); - r = mailsmtp_socket_connect(mSmtp, MCUTF8(hostname()), port()); - if (r != MAILSMTP_NO_ERROR) { - * pError = ErrorConnection; - goto close; - } - - MCLog("init"); - if (useHeloIPEnabled()) { - r = mailsmtp_init_with_ip(mSmtp, 1); - } else { - r = mailsmtp_init(mSmtp); - } - if (r == MAILSMTP_ERROR_STREAM) { - * pError = ErrorConnection; - goto close; - } - else if (r != MAILSMTP_NO_ERROR) { - * pError = ErrorConnection; - goto close; - } - - MCLog("start TLS"); - r = mailsmtp_socket_starttls(mSmtp); - if (r != MAILSMTP_NO_ERROR) { - * pError = ErrorStartTLSNotAvailable; - goto close; - } - MCLog("done"); - if (!checkCertificate()) { - * pError = ErrorCertificate; - goto close; - } - - MCLog("init after starttls"); - if (useHeloIPEnabled()) { - r = mailsmtp_init_with_ip(mSmtp, 1); - } else { - r = mailsmtp_init(mSmtp); - } - if (r == MAILSMTP_ERROR_STREAM) { - * pError = ErrorConnection; - goto close; - } - else if (r != MAILSMTP_NO_ERROR) { - * pError = ErrorConnection; - goto close; - } - - break; - - case ConnectionTypeTLS: - r = mailsmtp_ssl_connect(mSmtp, MCUTF8(mHostname), port()); - if (r != MAILSMTP_NO_ERROR) { - * pError = ErrorConnection; - goto close; - } - if (!checkCertificate()) { - * pError = ErrorCertificate; - goto close; - } - - MCLog("init"); - if (useHeloIPEnabled()) { - r = mailsmtp_init_with_ip(mSmtp, 1); - } else { - r = mailsmtp_init(mSmtp); - } - if (r == MAILSMTP_ERROR_STREAM) { - * pError = ErrorConnection; - goto close; - } - else if (r != MAILSMTP_NO_ERROR) { - * pError = ErrorConnection; - goto close; - } - - break; - - default: - r = mailsmtp_socket_connect(mSmtp, MCUTF8(hostname()), port()); - if (r != MAILSMTP_NO_ERROR) { - * pError = ErrorConnection; - goto close; - } - - MCLog("init"); - if (useHeloIPEnabled()) { - r = mailsmtp_init_with_ip(mSmtp, 1); - } else { - r = mailsmtp_init(mSmtp); - } - if (r == MAILSMTP_ERROR_STREAM) { - * pError = ErrorConnection; - goto close; - } - else if (r != MAILSMTP_NO_ERROR) { - * pError = ErrorConnection; - goto close; - } - - break; - } - - mailstream_low * low; - String * identifierString; - char * identifier; - - low = mailstream_get_low(mSmtp->stream); - if (mUsername != NULL) { - identifierString = String::stringWithUTF8Format("%s@%s:%u", MCUTF8(mUsername), MCUTF8(mHostname), port()); - } - else { - identifierString = String::stringWithUTF8Format("%s:%u", MCUTF8(mHostname), port()); - } - identifier = strdup(identifierString->UTF8Characters()); - mailstream_low_set_identifier(low, identifier); - - mState = STATE_CONNECTED; - * pError = ErrorNone; - return; - -close: - unsetup(); -} - -void SMTPSession::disconnect() -{ - if (mSmtp == NULL) - return; - - if (mSmtp->stream != NULL) { - mailsmtp_quit(mSmtp); - } - - unsetup(); - - mState = STATE_DISCONNECTED; -} - -void SMTPSession::loginIfNeeded(ErrorCode * pError) -{ - connectIfNeeded(pError); - if (* pError != ErrorNone) - return; - - if (mState == STATE_CONNECTED) { - login(pError); - } - else { - * pError = ErrorNone; - } -} - -void SMTPSession::login(ErrorCode * pError) -{ - int r; - - if ((authType() != AuthTypeXOAuth2) && (authType() != AuthTypeXOAuth2Outlook) && - ((username() == NULL) || (password() == NULL))) { - mState = STATE_LOGGEDIN; - * pError = ErrorNone; - return; - } - - if (authType() == 0) { - if (mSmtp->auth & MAILSMTP_AUTH_DIGEST_MD5) { - setAuthType((AuthType) (authType() | AuthTypeSASLDIGESTMD5)); - } - else if (mSmtp->auth & MAILSMTP_AUTH_CRAM_MD5) { - setAuthType((AuthType) (authType() | AuthTypeSASLCRAMMD5)); - } - else if (mSmtp->auth & MAILSMTP_AUTH_GSSAPI) { - setAuthType((AuthType) (authType() | AuthTypeSASLGSSAPI)); - } - else if (mSmtp->auth & MAILSMTP_AUTH_SRP) { - setAuthType((AuthType) (authType() | AuthTypeSASLSRP)); - } - else if (mSmtp->auth & MAILSMTP_AUTH_NTLM) { - setAuthType((AuthType) (authType() | AuthTypeSASLNTLM)); - } - else if (mSmtp->auth & MAILSMTP_AUTH_KERBEROS_V4) { - setAuthType((AuthType) (authType() | AuthTypeSASLKerberosV4)); - } - else if (mSmtp->auth & MAILSMTP_AUTH_PLAIN) { - setAuthType((AuthType) (authType() | AuthTypeSASLPlain)); - } - else if (mSmtp->auth & MAILSMTP_AUTH_LOGIN) { - setAuthType((AuthType) (authType() | AuthTypeSASLLogin)); - } - } - - switch (authType()) { - case 0: - default: - r = mailesmtp_auth_sasl(mSmtp, "PLAIN", - MCUTF8(mHostname), - NULL, - NULL, - MCUTF8(mUsername), MCUTF8(mUsername), - MCUTF8(mPassword), NULL); - break; - - case AuthTypeSASLCRAMMD5: - r = mailesmtp_auth_sasl(mSmtp, "CRAM-MD5", - MCUTF8(mHostname), - NULL, - NULL, - MCUTF8(mUsername), MCUTF8(mUsername), - MCUTF8(mPassword), NULL); - break; - - case AuthTypeSASLPlain: - r = mailesmtp_auth_sasl(mSmtp, "PLAIN", - MCUTF8(mHostname), - NULL, - NULL, - MCUTF8(mUsername), MCUTF8(mUsername), - MCUTF8(mPassword), NULL); - break; - - case AuthTypeSASLGSSAPI: - // needs to be tested - r = mailesmtp_auth_sasl(mSmtp, "GSSAPI", - MCUTF8(mHostname), - NULL, - NULL, - MCUTF8(mUsername), MCUTF8(mUsername), - MCUTF8(mPassword), NULL); - break; - - case AuthTypeSASLDIGESTMD5: - r = mailesmtp_auth_sasl(mSmtp, "DIGEST-MD5", - MCUTF8(mHostname), - NULL, - NULL, - MCUTF8(mUsername), MCUTF8(mUsername), - MCUTF8(mPassword), NULL); - break; - - case AuthTypeSASLLogin: - r = mailesmtp_auth_sasl(mSmtp, "LOGIN", - MCUTF8(mHostname), - NULL, - NULL, - MCUTF8(mUsername), MCUTF8(mUsername), - MCUTF8(mPassword), NULL); - break; - - case AuthTypeSASLSRP: - r = mailesmtp_auth_sasl(mSmtp, "SRP", - MCUTF8(mHostname), - NULL, - NULL, - MCUTF8(mUsername), MCUTF8(mUsername), - MCUTF8(mPassword), NULL); - break; - - case AuthTypeSASLNTLM: - r = mailesmtp_auth_sasl(mSmtp, "NTLM", - MCUTF8(mHostname), - NULL, - NULL, - MCUTF8(mUsername), MCUTF8(mUsername), - MCUTF8(mPassword), NULL /* realm */); - break; - - case AuthTypeSASLKerberosV4: - r = mailesmtp_auth_sasl(mSmtp, "KERBEROS_V4", - MCUTF8(mHostname), - NULL, - NULL, - MCUTF8(mUsername), MCUTF8(mUsername), - MCUTF8(mPassword), NULL /* realm */); - break; - - case AuthTypeXOAuth2: { - const char * utf8Username = MCUTF8(mUsername); - if (utf8Username == NULL) { - utf8Username = ""; - } - r = mailsmtp_oauth2_authenticate(mSmtp, utf8Username, MCUTF8(mOAuth2Token)); - break; - } - - case AuthTypeXOAuth2Outlook: { - const char * utf8Username = MCUTF8(mUsername); - if (utf8Username == NULL) { - utf8Username = ""; - } - r = mailsmtp_oauth2_outlook_authenticate(mSmtp, utf8Username, MCUTF8(mOAuth2Token)); - break; - } - } - if (r == MAILSMTP_ERROR_STREAM) { - * pError = ErrorConnection; - mShouldDisconnect = true; - return; - } - else if (r != MAILSMTP_NO_ERROR) { - * pError = ErrorAuthentication; - return; - } - - mState = STATE_LOGGEDIN; - * pError = ErrorNone; -} - -void SMTPSession::checkAccount(Address * from, ErrorCode * pError) -{ - int r; - - loginIfNeeded(pError); - if (* pError != ErrorNone) { - return; - } - r = mailsmtp_mail(mSmtp, MCUTF8(from->mailbox())); - if (r == MAILSMTP_ERROR_STREAM) { - * pError = ErrorConnection; - mShouldDisconnect = true; - return; - } - else if (r != MAILSMTP_NO_ERROR) { - * pError = ErrorInvalidAccount; - return; - } - - r = mailsmtp_rcpt(mSmtp, "email@invalid.com"); - if (r == MAILSMTP_ERROR_STREAM) { - * pError = ErrorConnection; - mShouldDisconnect = true; - return; - } - else if (r != MAILSMTP_NO_ERROR) { - * pError = ErrorInvalidAccount; - return; - } - - * pError = ErrorNone; -} - -void SMTPSession::sendMessage(Address * from, Array * recipients, Data * messageData, - SMTPProgressCallback * callback, ErrorCode * pError) -{ - clist * address_list; - int r; - - if (from == NULL) { - * pError = ErrorNoSender; - return; - } - if ((recipients == NULL) || (recipients->count() == 0)) { - * pError = ErrorNoRecipient; - return; - } - - messageData = dataWithFilteredBcc(messageData); - - mProgressCallback = callback; - bodyProgress(0, messageData->length()); - - MCLog("setup"); - - MCLog("connect"); - loginIfNeeded(pError); - if (* pError != ErrorNone) { - goto err; - } - - // disable DSN feature for more compatibility - mSmtp->esmtp &= ~MAILSMTP_ESMTP_DSN; - - address_list = esmtp_address_list_new(); - for(unsigned int i = 0 ; i < recipients->count() ; i ++) { - Address * addr = (Address *) recipients->objectAtIndex(i); - esmtp_address_list_add(address_list, (char *) MCUTF8(addr->mailbox()), 0, NULL); - } - MCLog("send"); - if ((mSmtp->esmtp & MAILSMTP_ESMTP_PIPELINING) != 0) { - r = mailesmtp_send_quit(mSmtp, MCUTF8(from->mailbox()), 0, NULL, - address_list, - messageData->bytes(), messageData->length()); - } - else { - r = mailesmtp_send(mSmtp, MCUTF8(from->mailbox()), 0, NULL, - address_list, - messageData->bytes(), messageData->length()); - mailsmtp_quit(mSmtp); - } - esmtp_address_list_free(address_list); - - String * response; - int responseCode; - - response = NULL; - if (mSmtp->response != NULL) { - response = String::stringWithUTF8Characters(mSmtp->response); - } - responseCode = mSmtp->response_code; - - if ((r == MAILSMTP_ERROR_STREAM) || (r == MAILSMTP_ERROR_CONNECTION_REFUSED)) { - * pError = ErrorConnection; - mShouldDisconnect = true; - goto err; - } - else if (r == MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION) { - if (response->locationOfString(MCSTR("5.7.0")) != -1) { - * pError = ErrorSendMessageIllegalAttachment; - } - else { - * pError = ErrorStorageLimit; - } - goto err; - } - else if (r == MAILSMTP_ERROR_MAILBOX_UNAVAILABLE) { - * pError = ErrorSendMessageNotAllowed; - goto err; - } - else if (r == MAILSMTP_ERROR_AUTH_REQUIRED) { - * pError = ErrorAuthenticationRequired; - goto err; - } - else if (r != MAILSMTP_NO_ERROR) { - if ((responseCode == 550) && (response->hasPrefix(MCSTR("5.3.4")))) { - * pError = ErrorNeedsConnectToWebmail; - goto err; - } - else { - * pError = ErrorSendMessage; - MC_SAFE_REPLACE_COPY(String, mLastSMTPResponse, response); - mLastLibetpanError = r; - mLastSMTPResponseCode = responseCode; - goto err; - } - } - - bodyProgress(messageData->length(), messageData->length()); - * pError = ErrorNone; - - err: - mProgressCallback = NULL; -} - -Data * SMTPSession::dataWithFilteredBcc(Data * data) -{ - int r; - size_t idx; - struct mailimf_message * msg; - MMAPString * str; - - idx = 0; - r = mailimf_message_parse(data->bytes(), data->length(), &idx, &msg); - if (r != MAILIMF_NO_ERROR) { - return Data::data(); - } - - struct mailimf_fields * fields = msg->msg_fields; - int col = 0; - - str = mmap_string_new(""); - for(clistiter * cur = clist_begin(fields->fld_list) ; cur != NULL ; cur = clist_next(cur)) { - struct mailimf_field * field = (struct mailimf_field *) clist_content(cur); - if (field->fld_type == MAILIMF_FIELD_BCC) { - mailimf_field_free(field); - clist_delete(fields->fld_list, cur); - break; - } - } - mailimf_fields_write_mem(str, &col, fields); - mmap_string_append(str, "\n"); - mmap_string_append_len(str, msg->msg_body->bd_text, msg->msg_body->bd_size); - - Data * result = Data::dataWithBytes(str->str, (unsigned int) str->len); - - mmap_string_free(str); - mailimf_message_free(msg); - - return result; -} - -void SMTPSession::sendMessage(Data * messageData, SMTPProgressCallback * callback, ErrorCode * pError) -{ - AutoreleasePool * pool = new AutoreleasePool(); - MessageParser * parser = new MessageParser(messageData); - Array * recipients = new Array(); - - if (parser->header()->to() != NULL) { - recipients->addObjectsFromArray(parser->header()->to()); - } - if (parser->header()->cc() != NULL) { - recipients->addObjectsFromArray(parser->header()->cc()); - } - if (parser->header()->bcc() != NULL) { - recipients->addObjectsFromArray(parser->header()->bcc()); - } - Address * from = parser->header()->from(); - - sendMessage(from, recipients, messageData, callback, pError); - - recipients->release(); - parser->release(); - pool->release(); -} - -void SMTPSession::sendMessage(MessageBuilder * msg, SMTPProgressCallback * callback, ErrorCode * pError) -{ - Array * recipients = new Array(); - if (msg->header()->to() != NULL) { - recipients->addObjectsFromArray(msg->header()->to()); - } - if (msg->header()->cc() != NULL) { - recipients->addObjectsFromArray(msg->header()->cc()); - } - if (msg->header()->bcc() != NULL) { - recipients->addObjectsFromArray(msg->header()->bcc()); - } - Address * from = msg->header()->from(); - Data * data = msg->data(); - MCAssert(from != NULL); - MCAssert(recipients->count() > 0); - sendMessage(from, recipients, data, callback, pError); - recipients->release(); -} - -void SMTPSession::noop(ErrorCode * pError) -{ - int r; - - if (mSmtp == NULL) - return; - - MCLog("connect"); - loginIfNeeded(pError); - if (* pError != ErrorNone) { - return; - } - if (mSmtp->stream != NULL) { - r = mailsmtp_noop(mSmtp); - if (r == MAILSMTP_ERROR_STREAM) { - * pError = ErrorConnection; - } - } -} - -bool SMTPSession::isDisconnected() -{ - return mState == STATE_DISCONNECTED; -} - -void SMTPSession::setConnectionLogger(ConnectionLogger * logger) -{ - mConnectionLogger = logger; -} - -ConnectionLogger * SMTPSession::connectionLogger() -{ - return mConnectionLogger; -} diff --git a/src/core/smtp/MCSMTPSession.cpp b/src/core/smtp/MCSMTPSession.cpp new file mode 100644 index 00000000..ad8b19e0 --- /dev/null +++ b/src/core/smtp/MCSMTPSession.cpp @@ -0,0 +1,804 @@ +#include "MCWin32.h" // Should be included first. + +#include "MCSMTPSession.h" + +#include +#include + +#include "MCAddress.h" +#include "MCMessageBuilder.h" +#include "MCMessageParser.h" +#include "MCMessageHeader.h" +#include "MCSMTPProgressCallback.h" +#include "MCConnectionLoggerUtils.h" +#include "MCCertificateUtils.h" + +using namespace mailcore; + +enum { + STATE_DISCONNECTED, + STATE_CONNECTED, + STATE_LOGGEDIN, +}; + +void SMTPSession::init() +{ + mHostname = NULL; + mPort = 0; + mUsername = NULL; + mPassword = NULL; + mOAuth2Token = NULL; + mAuthType = AuthTypeSASLNone; + mConnectionType = ConnectionTypeClear; + mTimeout = 30; + mCheckCertificateEnabled = true; + mUseHeloIPEnabled = false; + mShouldDisconnect = false; + + mSmtp = NULL; + mProgressCallback = NULL; + mState = STATE_DISCONNECTED; + mLastSMTPResponse = NULL; + mLastLibetpanError = 0; + mLastSMTPResponseCode = 0; + mConnectionLogger = NULL; +} + +SMTPSession::SMTPSession() +{ + init(); +} + +SMTPSession::~SMTPSession() +{ + MC_SAFE_RELEASE(mLastSMTPResponse); + MC_SAFE_RELEASE(mHostname); + MC_SAFE_RELEASE(mUsername); + MC_SAFE_RELEASE(mPassword); + MC_SAFE_RELEASE(mOAuth2Token); +} + +void SMTPSession::setHostname(String * hostname) +{ + MC_SAFE_REPLACE_COPY(String, mHostname, hostname); +} + +String * SMTPSession::hostname() +{ + return mHostname; +} + +void SMTPSession::setPort(unsigned int port) +{ + mPort = port; +} + +unsigned int SMTPSession::port() +{ + return mPort; +} + +void SMTPSession::setUsername(String * username) +{ + MC_SAFE_REPLACE_COPY(String, mUsername, username); +} + +String * SMTPSession::username() +{ + return mUsername; +} + +void SMTPSession::setPassword(String * password) +{ + MC_SAFE_REPLACE_COPY(String, mPassword, password); +} + +String * SMTPSession::password() +{ + return mPassword; +} + +void SMTPSession::setOAuth2Token(String * token) +{ + MC_SAFE_REPLACE_COPY(String, mOAuth2Token, token); +} + +String * SMTPSession::OAuth2Token() +{ + return mOAuth2Token; +} + +void SMTPSession::setAuthType(AuthType authType) +{ + mAuthType = authType; +} + +AuthType SMTPSession::authType() +{ + return mAuthType; +} + +void SMTPSession::setConnectionType(ConnectionType connectionType) +{ + mConnectionType = connectionType; +} + +ConnectionType SMTPSession::connectionType() +{ + return mConnectionType; +} + +void SMTPSession::setTimeout(time_t timeout) +{ + mTimeout = timeout; +} + +time_t SMTPSession::timeout() +{ + return mTimeout; +} + +void SMTPSession::setCheckCertificateEnabled(bool enabled) +{ + mCheckCertificateEnabled = enabled; +} + +bool SMTPSession::isCheckCertificateEnabled() +{ + return mCheckCertificateEnabled; +} + +bool SMTPSession::checkCertificate() +{ + if (!isCheckCertificateEnabled()) + return true; + return mailcore::checkCertificate(mSmtp->stream, hostname()); +} + +void SMTPSession::setUseHeloIPEnabled(bool enabled) +{ + mUseHeloIPEnabled = enabled; +} + +bool SMTPSession::useHeloIPEnabled() +{ + return mUseHeloIPEnabled; +} + +void SMTPSession::body_progress(size_t current, size_t maximum, void * context) +{ + SMTPSession * session; + + session = (SMTPSession *) context; + session->bodyProgress((unsigned int) current, (unsigned int) maximum); +} + +void SMTPSession::bodyProgress(unsigned int current, unsigned int maximum) +{ + if (mProgressCallback != NULL) { + mProgressCallback->bodyProgress(this, current, maximum); + } +} + + +static void logger(mailsmtp * smtp, int log_type, const char * buffer, size_t size, void * context) +{ + SMTPSession * session = (SMTPSession *) context; + + if (session->connectionLogger() == NULL) + return; + + ConnectionLogType type = getConnectionType(log_type); + bool isBuffer = isBufferFromLogType(log_type); + + if (isBuffer) { + Data * data = Data::dataWithBytes(buffer, (unsigned int) size); + session->connectionLogger()->log(session, type, data); + } + else { + session->connectionLogger()->log(session, type, NULL); + } +} + + +void SMTPSession::setup() +{ + mSmtp = mailsmtp_new(0, NULL); + mailsmtp_set_timeout(mSmtp, timeout()); + mailsmtp_set_progress_callback(mSmtp, body_progress, this); + mailsmtp_set_logger(mSmtp, logger, this); +} + +void SMTPSession::unsetup() +{ + mailsmtp_free(mSmtp); + mSmtp = NULL; +} + +void SMTPSession::connectIfNeeded(ErrorCode * pError) +{ + if (mSmtp != NULL) { + // In case pipelining is available, libetpan will disconnect the session. + if (mSmtp->stream == NULL) { + mShouldDisconnect = true; + } + } + if (mShouldDisconnect) { + disconnect(); + mShouldDisconnect = false; + } + + if (mState == STATE_DISCONNECTED) { + connect(pError); + } + else { + * pError = ErrorNone; + } +} + +void SMTPSession::connect(ErrorCode * pError) +{ + int r; + + setup(); + + switch (mConnectionType) { + case ConnectionTypeStartTLS: + MCLog("connect %s %u", MCUTF8(hostname()), (unsigned int) port()); + r = mailsmtp_socket_connect(mSmtp, MCUTF8(hostname()), port()); + if (r != MAILSMTP_NO_ERROR) { + * pError = ErrorConnection; + goto close; + } + + MCLog("init"); + if (useHeloIPEnabled()) { + r = mailsmtp_init_with_ip(mSmtp, 1); + } else { + r = mailsmtp_init(mSmtp); + } + if (r == MAILSMTP_ERROR_STREAM) { + * pError = ErrorConnection; + goto close; + } + else if (r != MAILSMTP_NO_ERROR) { + * pError = ErrorConnection; + goto close; + } + + MCLog("start TLS"); + r = mailsmtp_socket_starttls(mSmtp); + if (r != MAILSMTP_NO_ERROR) { + * pError = ErrorStartTLSNotAvailable; + goto close; + } + MCLog("done"); + if (!checkCertificate()) { + * pError = ErrorCertificate; + goto close; + } + + MCLog("init after starttls"); + if (useHeloIPEnabled()) { + r = mailsmtp_init_with_ip(mSmtp, 1); + } else { + r = mailsmtp_init(mSmtp); + } + if (r == MAILSMTP_ERROR_STREAM) { + * pError = ErrorConnection; + goto close; + } + else if (r != MAILSMTP_NO_ERROR) { + * pError = ErrorConnection; + goto close; + } + + break; + + case ConnectionTypeTLS: + r = mailsmtp_ssl_connect(mSmtp, MCUTF8(mHostname), port()); + if (r != MAILSMTP_NO_ERROR) { + * pError = ErrorConnection; + goto close; + } + if (!checkCertificate()) { + * pError = ErrorCertificate; + goto close; + } + + MCLog("init"); + if (useHeloIPEnabled()) { + r = mailsmtp_init_with_ip(mSmtp, 1); + } else { + r = mailsmtp_init(mSmtp); + } + if (r == MAILSMTP_ERROR_STREAM) { + * pError = ErrorConnection; + goto close; + } + else if (r != MAILSMTP_NO_ERROR) { + * pError = ErrorConnection; + goto close; + } + + break; + + default: + r = mailsmtp_socket_connect(mSmtp, MCUTF8(hostname()), port()); + if (r != MAILSMTP_NO_ERROR) { + * pError = ErrorConnection; + goto close; + } + + MCLog("init"); + if (useHeloIPEnabled()) { + r = mailsmtp_init_with_ip(mSmtp, 1); + } else { + r = mailsmtp_init(mSmtp); + } + if (r == MAILSMTP_ERROR_STREAM) { + * pError = ErrorConnection; + goto close; + } + else if (r != MAILSMTP_NO_ERROR) { + * pError = ErrorConnection; + goto close; + } + + break; + } + + mailstream_low * low; + String * identifierString; + char * identifier; + + low = mailstream_get_low(mSmtp->stream); + if (mUsername != NULL) { + identifierString = String::stringWithUTF8Format("%s@%s:%u", MCUTF8(mUsername), MCUTF8(mHostname), port()); + } + else { + identifierString = String::stringWithUTF8Format("%s:%u", MCUTF8(mHostname), port()); + } + identifier = strdup(identifierString->UTF8Characters()); + mailstream_low_set_identifier(low, identifier); + + mState = STATE_CONNECTED; + * pError = ErrorNone; + return; + +close: + unsetup(); +} + +void SMTPSession::disconnect() +{ + if (mSmtp == NULL) + return; + + if (mSmtp->stream != NULL) { + mailsmtp_quit(mSmtp); + } + + unsetup(); + + mState = STATE_DISCONNECTED; +} + +void SMTPSession::loginIfNeeded(ErrorCode * pError) +{ + connectIfNeeded(pError); + if (* pError != ErrorNone) + return; + + if (mState == STATE_CONNECTED) { + login(pError); + } + else { + * pError = ErrorNone; + } +} + +void SMTPSession::login(ErrorCode * pError) +{ + int r; + + if ((authType() != AuthTypeXOAuth2) && (authType() != AuthTypeXOAuth2Outlook) && + ((username() == NULL) || (password() == NULL))) { + mState = STATE_LOGGEDIN; + * pError = ErrorNone; + return; + } + + if (authType() == 0) { + if (mSmtp->auth & MAILSMTP_AUTH_DIGEST_MD5) { + setAuthType((AuthType) (authType() | AuthTypeSASLDIGESTMD5)); + } + else if (mSmtp->auth & MAILSMTP_AUTH_CRAM_MD5) { + setAuthType((AuthType) (authType() | AuthTypeSASLCRAMMD5)); + } + else if (mSmtp->auth & MAILSMTP_AUTH_GSSAPI) { + setAuthType((AuthType) (authType() | AuthTypeSASLGSSAPI)); + } + else if (mSmtp->auth & MAILSMTP_AUTH_SRP) { + setAuthType((AuthType) (authType() | AuthTypeSASLSRP)); + } + else if (mSmtp->auth & MAILSMTP_AUTH_NTLM) { + setAuthType((AuthType) (authType() | AuthTypeSASLNTLM)); + } + else if (mSmtp->auth & MAILSMTP_AUTH_KERBEROS_V4) { + setAuthType((AuthType) (authType() | AuthTypeSASLKerberosV4)); + } + else if (mSmtp->auth & MAILSMTP_AUTH_PLAIN) { + setAuthType((AuthType) (authType() | AuthTypeSASLPlain)); + } + else if (mSmtp->auth & MAILSMTP_AUTH_LOGIN) { + setAuthType((AuthType) (authType() | AuthTypeSASLLogin)); + } + } + + switch (authType()) { + case 0: + default: + r = mailesmtp_auth_sasl(mSmtp, "PLAIN", + MCUTF8(mHostname), + NULL, + NULL, + MCUTF8(mUsername), MCUTF8(mUsername), + MCUTF8(mPassword), NULL); + break; + + case AuthTypeSASLCRAMMD5: + r = mailesmtp_auth_sasl(mSmtp, "CRAM-MD5", + MCUTF8(mHostname), + NULL, + NULL, + MCUTF8(mUsername), MCUTF8(mUsername), + MCUTF8(mPassword), NULL); + break; + + case AuthTypeSASLPlain: + r = mailesmtp_auth_sasl(mSmtp, "PLAIN", + MCUTF8(mHostname), + NULL, + NULL, + MCUTF8(mUsername), MCUTF8(mUsername), + MCUTF8(mPassword), NULL); + break; + + case AuthTypeSASLGSSAPI: + // needs to be tested + r = mailesmtp_auth_sasl(mSmtp, "GSSAPI", + MCUTF8(mHostname), + NULL, + NULL, + MCUTF8(mUsername), MCUTF8(mUsername), + MCUTF8(mPassword), NULL); + break; + + case AuthTypeSASLDIGESTMD5: + r = mailesmtp_auth_sasl(mSmtp, "DIGEST-MD5", + MCUTF8(mHostname), + NULL, + NULL, + MCUTF8(mUsername), MCUTF8(mUsername), + MCUTF8(mPassword), NULL); + break; + + case AuthTypeSASLLogin: + r = mailesmtp_auth_sasl(mSmtp, "LOGIN", + MCUTF8(mHostname), + NULL, + NULL, + MCUTF8(mUsername), MCUTF8(mUsername), + MCUTF8(mPassword), NULL); + break; + + case AuthTypeSASLSRP: + r = mailesmtp_auth_sasl(mSmtp, "SRP", + MCUTF8(mHostname), + NULL, + NULL, + MCUTF8(mUsername), MCUTF8(mUsername), + MCUTF8(mPassword), NULL); + break; + + case AuthTypeSASLNTLM: + r = mailesmtp_auth_sasl(mSmtp, "NTLM", + MCUTF8(mHostname), + NULL, + NULL, + MCUTF8(mUsername), MCUTF8(mUsername), + MCUTF8(mPassword), NULL /* realm */); + break; + + case AuthTypeSASLKerberosV4: + r = mailesmtp_auth_sasl(mSmtp, "KERBEROS_V4", + MCUTF8(mHostname), + NULL, + NULL, + MCUTF8(mUsername), MCUTF8(mUsername), + MCUTF8(mPassword), NULL /* realm */); + break; + + case AuthTypeXOAuth2: { + const char * utf8Username = MCUTF8(mUsername); + if (utf8Username == NULL) { + utf8Username = ""; + } + r = mailsmtp_oauth2_authenticate(mSmtp, utf8Username, MCUTF8(mOAuth2Token)); + break; + } + + case AuthTypeXOAuth2Outlook: { + const char * utf8Username = MCUTF8(mUsername); + if (utf8Username == NULL) { + utf8Username = ""; + } + r = mailsmtp_oauth2_outlook_authenticate(mSmtp, utf8Username, MCUTF8(mOAuth2Token)); + break; + } + } + if (r == MAILSMTP_ERROR_STREAM) { + * pError = ErrorConnection; + mShouldDisconnect = true; + return; + } + else if (r != MAILSMTP_NO_ERROR) { + * pError = ErrorAuthentication; + return; + } + + mState = STATE_LOGGEDIN; + * pError = ErrorNone; +} + +void SMTPSession::checkAccount(Address * from, ErrorCode * pError) +{ + int r; + + loginIfNeeded(pError); + if (* pError != ErrorNone) { + return; + } + r = mailsmtp_mail(mSmtp, MCUTF8(from->mailbox())); + if (r == MAILSMTP_ERROR_STREAM) { + * pError = ErrorConnection; + mShouldDisconnect = true; + return; + } + else if (r != MAILSMTP_NO_ERROR) { + * pError = ErrorInvalidAccount; + return; + } + + r = mailsmtp_rcpt(mSmtp, "email@invalid.com"); + if (r == MAILSMTP_ERROR_STREAM) { + * pError = ErrorConnection; + mShouldDisconnect = true; + return; + } + else if (r != MAILSMTP_NO_ERROR) { + * pError = ErrorInvalidAccount; + return; + } + + * pError = ErrorNone; +} + +void SMTPSession::sendMessage(Address * from, Array * recipients, Data * messageData, + SMTPProgressCallback * callback, ErrorCode * pError) +{ + clist * address_list; + int r; + + if (from == NULL) { + * pError = ErrorNoSender; + return; + } + if ((recipients == NULL) || (recipients->count() == 0)) { + * pError = ErrorNoRecipient; + return; + } + + messageData = dataWithFilteredBcc(messageData); + + mProgressCallback = callback; + bodyProgress(0, messageData->length()); + + MCLog("setup"); + + MCLog("connect"); + loginIfNeeded(pError); + if (* pError != ErrorNone) { + goto err; + } + + // disable DSN feature for more compatibility + mSmtp->esmtp &= ~MAILSMTP_ESMTP_DSN; + + address_list = esmtp_address_list_new(); + for(unsigned int i = 0 ; i < recipients->count() ; i ++) { + Address * addr = (Address *) recipients->objectAtIndex(i); + esmtp_address_list_add(address_list, (char *) MCUTF8(addr->mailbox()), 0, NULL); + } + MCLog("send"); + if ((mSmtp->esmtp & MAILSMTP_ESMTP_PIPELINING) != 0) { + r = mailesmtp_send_quit(mSmtp, MCUTF8(from->mailbox()), 0, NULL, + address_list, + messageData->bytes(), messageData->length()); + } + else { + r = mailesmtp_send(mSmtp, MCUTF8(from->mailbox()), 0, NULL, + address_list, + messageData->bytes(), messageData->length()); + mailsmtp_quit(mSmtp); + } + esmtp_address_list_free(address_list); + + String * response; + int responseCode; + + response = NULL; + if (mSmtp->response != NULL) { + response = String::stringWithUTF8Characters(mSmtp->response); + } + responseCode = mSmtp->response_code; + + if ((r == MAILSMTP_ERROR_STREAM) || (r == MAILSMTP_ERROR_CONNECTION_REFUSED)) { + * pError = ErrorConnection; + mShouldDisconnect = true; + goto err; + } + else if (r == MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION) { + if (response->locationOfString(MCSTR("5.7.0")) != -1) { + * pError = ErrorSendMessageIllegalAttachment; + } + else { + * pError = ErrorStorageLimit; + } + goto err; + } + else if (r == MAILSMTP_ERROR_MAILBOX_UNAVAILABLE) { + * pError = ErrorSendMessageNotAllowed; + goto err; + } + else if (r == MAILSMTP_ERROR_AUTH_REQUIRED) { + * pError = ErrorAuthenticationRequired; + goto err; + } + else if (r != MAILSMTP_NO_ERROR) { + if ((responseCode == 550) && (response->hasPrefix(MCSTR("5.3.4")))) { + * pError = ErrorNeedsConnectToWebmail; + goto err; + } + else { + * pError = ErrorSendMessage; + MC_SAFE_REPLACE_COPY(String, mLastSMTPResponse, response); + mLastLibetpanError = r; + mLastSMTPResponseCode = responseCode; + goto err; + } + } + + bodyProgress(messageData->length(), messageData->length()); + * pError = ErrorNone; + + err: + mProgressCallback = NULL; +} + +Data * SMTPSession::dataWithFilteredBcc(Data * data) +{ + int r; + size_t idx; + struct mailimf_message * msg; + MMAPString * str; + + idx = 0; + r = mailimf_message_parse(data->bytes(), data->length(), &idx, &msg); + if (r != MAILIMF_NO_ERROR) { + return Data::data(); + } + + struct mailimf_fields * fields = msg->msg_fields; + int col = 0; + + str = mmap_string_new(""); + for(clistiter * cur = clist_begin(fields->fld_list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimf_field * field = (struct mailimf_field *) clist_content(cur); + if (field->fld_type == MAILIMF_FIELD_BCC) { + mailimf_field_free(field); + clist_delete(fields->fld_list, cur); + break; + } + } + mailimf_fields_write_mem(str, &col, fields); + mmap_string_append(str, "\n"); + mmap_string_append_len(str, msg->msg_body->bd_text, msg->msg_body->bd_size); + + Data * result = Data::dataWithBytes(str->str, (unsigned int) str->len); + + mmap_string_free(str); + mailimf_message_free(msg); + + return result; +} + +void SMTPSession::sendMessage(Data * messageData, SMTPProgressCallback * callback, ErrorCode * pError) +{ + AutoreleasePool * pool = new AutoreleasePool(); + MessageParser * parser = new MessageParser(messageData); + Array * recipients = new Array(); + + if (parser->header()->to() != NULL) { + recipients->addObjectsFromArray(parser->header()->to()); + } + if (parser->header()->cc() != NULL) { + recipients->addObjectsFromArray(parser->header()->cc()); + } + if (parser->header()->bcc() != NULL) { + recipients->addObjectsFromArray(parser->header()->bcc()); + } + Address * from = parser->header()->from(); + + sendMessage(from, recipients, messageData, callback, pError); + + recipients->release(); + parser->release(); + pool->release(); +} + +void SMTPSession::sendMessage(MessageBuilder * msg, SMTPProgressCallback * callback, ErrorCode * pError) +{ + Array * recipients = new Array(); + if (msg->header()->to() != NULL) { + recipients->addObjectsFromArray(msg->header()->to()); + } + if (msg->header()->cc() != NULL) { + recipients->addObjectsFromArray(msg->header()->cc()); + } + if (msg->header()->bcc() != NULL) { + recipients->addObjectsFromArray(msg->header()->bcc()); + } + Address * from = msg->header()->from(); + Data * data = msg->data(); + MCAssert(from != NULL); + MCAssert(recipients->count() > 0); + sendMessage(from, recipients, data, callback, pError); + recipients->release(); +} + +void SMTPSession::noop(ErrorCode * pError) +{ + int r; + + if (mSmtp == NULL) + return; + + MCLog("connect"); + loginIfNeeded(pError); + if (* pError != ErrorNone) { + return; + } + if (mSmtp->stream != NULL) { + r = mailsmtp_noop(mSmtp); + if (r == MAILSMTP_ERROR_STREAM) { + * pError = ErrorConnection; + } + } +} + +bool SMTPSession::isDisconnected() +{ + return mState == STATE_DISCONNECTED; +} + +void SMTPSession::setConnectionLogger(ConnectionLogger * logger) +{ + mConnectionLogger = logger; +} + +ConnectionLogger * SMTPSession::connectionLogger() +{ + return mConnectionLogger; +} diff --git a/src/core/zip/MCZip.cc b/src/core/zip/MCZip.cc deleted file mode 100644 index 6e700732..00000000 --- a/src/core/zip/MCZip.cc +++ /dev/null @@ -1,170 +0,0 @@ -#include "MCWin32.h" // Should be included first. - -#include "MCZip.h" - -#include "zip.h" -#include "unzip.h" - -#include -#ifndef _MSC_VER -#include -#endif -#include -#include - -#ifdef _MSC_VER -#define USEWIN32IOAPI -#include "ioapi.h" -#include "iowin32.h" -#endif - -using namespace mailcore; - -static ErrorCode addFile(zipFile file, String * path); - -ErrorCode mailcore::CreateZipFileFromFolder(String * zipFilename, String * path) -{ -#ifdef _MSC_VER - zlib_filefunc64_def ffunc; - fill_win32_filefunc64A(&ffunc); - zipFile file = zipOpen2_64(zipFilename->fileSystemRepresentation(), APPEND_STATUS_CREATE, NULL, &ffunc); -#else - zipFile file = zipOpen(zipFilename->fileSystemRepresentation(), APPEND_STATUS_CREATE); -#endif - if (file == NULL) { - return ErrorFile; - } - - addFile(file, path); - - int err = zipClose(file, NULL); - if (err != ZIP_OK) { - return ErrorFile; - } - - return ErrorNone; -} - -static ErrorCode addFile(zipFile file, String * path) -{ - const char * cPath = path->fileSystemRepresentation(); - struct stat statinfo; - int r; - int err; - - r = stat(cPath, &statinfo); - if (r < 0) - return ErrorFile; - -#ifndef _MSC_VER - if (S_ISDIR(statinfo.st_mode)) { - DIR * dir = opendir(cPath); - if (dir == NULL) { - return ErrorFile; - } - - struct dirent * ent; - while ((ent = readdir(dir)) != NULL) { - if ((strcmp(ent->d_name, ".") == 0) || (strcmp(ent->d_name, "..") == 0)) { - continue; - } - - String * subpath = path->stringByAppendingPathComponent(String::stringWithFileSystemRepresentation(ent->d_name)); - addFile(file, subpath); - } - closedir(dir); - - return ErrorNone; - } -#else - // XXX - should be implemented on Win32. -#endif - - time_t clock; - time(&clock); - - struct tm timevalue; - zip_fileinfo zi; - gmtime_r(&clock, &timevalue); - zi.tmz_date.tm_sec = timevalue.tm_sec; - zi.tmz_date.tm_min = timevalue.tm_min; - zi.tmz_date.tm_hour = timevalue.tm_hour; - zi.tmz_date.tm_mday = timevalue.tm_mday; - zi.tmz_date.tm_mon = timevalue.tm_mon; - zi.tmz_date.tm_year = timevalue.tm_year; - zi.internal_fa = 0; - zi.external_fa = 0; - zi.dosDate = 0; - - err = zipOpenNewFileInZip3(file, path->lastPathComponent()->fileSystemRepresentation(), - &zi, NULL, 0, NULL, 0, NULL, - Z_DEFLATED, - -1, 0, - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0); - if (err != ZIP_OK) { - return ErrorFile; - } - - FILE * f = fopen(cPath, "rb"); - if (f == NULL) { - return ErrorFile; - } - - char * bytes = (char *) malloc(4096); - - size_t count; - do { - count = fread(bytes, 1, 4096, f); - - err = zipWriteInFileInZip(file, bytes, (unsigned) count); - if (err != ZIP_OK) { - free(bytes); - zipCloseFileInZip(file); - return ErrorFile; - } - } while (count > 0); - - free(bytes); - - if (ferror(f)) { - return ErrorFile; - } - - fclose(f); - - err = zipCloseFileInZip(file); - if (err != ZIP_OK) { - return ErrorFile; - } - - return ErrorNone; -} - -String * mailcore::CreateTemporaryZipFileFromFolder(String * folder) -{ - char tempdir[] = "/tmp/mailcore2-XXXXXX"; - char * result = mkdtemp(tempdir); - if (result == NULL) { - return NULL; - } - - String * tempDirectoryString = String::stringWithFileSystemRepresentation(tempdir); - String * path = tempDirectoryString->stringByAppendingPathComponent(folder->lastPathComponent())->stringByAppendingUTF8Format(".zip"); - - ErrorCode err = CreateZipFileFromFolder(path, folder); - if (err != ErrorNone) { - unlink(path->fileSystemRepresentation()); - unlink(tempdir); - return NULL; - } - - return path; -} - -void mailcore::RemoveTemporaryZipFile(String * zipFilename) -{ - String * tempDir = zipFilename->stringByDeletingLastPathComponent(); - unlink(zipFilename->fileSystemRepresentation()); - unlink(tempDir->fileSystemRepresentation()); -} diff --git a/src/core/zip/MCZip.cpp b/src/core/zip/MCZip.cpp new file mode 100644 index 00000000..6e700732 --- /dev/null +++ b/src/core/zip/MCZip.cpp @@ -0,0 +1,170 @@ +#include "MCWin32.h" // Should be included first. + +#include "MCZip.h" + +#include "zip.h" +#include "unzip.h" + +#include +#ifndef _MSC_VER +#include +#endif +#include +#include + +#ifdef _MSC_VER +#define USEWIN32IOAPI +#include "ioapi.h" +#include "iowin32.h" +#endif + +using namespace mailcore; + +static ErrorCode addFile(zipFile file, String * path); + +ErrorCode mailcore::CreateZipFileFromFolder(String * zipFilename, String * path) +{ +#ifdef _MSC_VER + zlib_filefunc64_def ffunc; + fill_win32_filefunc64A(&ffunc); + zipFile file = zipOpen2_64(zipFilename->fileSystemRepresentation(), APPEND_STATUS_CREATE, NULL, &ffunc); +#else + zipFile file = zipOpen(zipFilename->fileSystemRepresentation(), APPEND_STATUS_CREATE); +#endif + if (file == NULL) { + return ErrorFile; + } + + addFile(file, path); + + int err = zipClose(file, NULL); + if (err != ZIP_OK) { + return ErrorFile; + } + + return ErrorNone; +} + +static ErrorCode addFile(zipFile file, String * path) +{ + const char * cPath = path->fileSystemRepresentation(); + struct stat statinfo; + int r; + int err; + + r = stat(cPath, &statinfo); + if (r < 0) + return ErrorFile; + +#ifndef _MSC_VER + if (S_ISDIR(statinfo.st_mode)) { + DIR * dir = opendir(cPath); + if (dir == NULL) { + return ErrorFile; + } + + struct dirent * ent; + while ((ent = readdir(dir)) != NULL) { + if ((strcmp(ent->d_name, ".") == 0) || (strcmp(ent->d_name, "..") == 0)) { + continue; + } + + String * subpath = path->stringByAppendingPathComponent(String::stringWithFileSystemRepresentation(ent->d_name)); + addFile(file, subpath); + } + closedir(dir); + + return ErrorNone; + } +#else + // XXX - should be implemented on Win32. +#endif + + time_t clock; + time(&clock); + + struct tm timevalue; + zip_fileinfo zi; + gmtime_r(&clock, &timevalue); + zi.tmz_date.tm_sec = timevalue.tm_sec; + zi.tmz_date.tm_min = timevalue.tm_min; + zi.tmz_date.tm_hour = timevalue.tm_hour; + zi.tmz_date.tm_mday = timevalue.tm_mday; + zi.tmz_date.tm_mon = timevalue.tm_mon; + zi.tmz_date.tm_year = timevalue.tm_year; + zi.internal_fa = 0; + zi.external_fa = 0; + zi.dosDate = 0; + + err = zipOpenNewFileInZip3(file, path->lastPathComponent()->fileSystemRepresentation(), + &zi, NULL, 0, NULL, 0, NULL, + Z_DEFLATED, + -1, 0, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0); + if (err != ZIP_OK) { + return ErrorFile; + } + + FILE * f = fopen(cPath, "rb"); + if (f == NULL) { + return ErrorFile; + } + + char * bytes = (char *) malloc(4096); + + size_t count; + do { + count = fread(bytes, 1, 4096, f); + + err = zipWriteInFileInZip(file, bytes, (unsigned) count); + if (err != ZIP_OK) { + free(bytes); + zipCloseFileInZip(file); + return ErrorFile; + } + } while (count > 0); + + free(bytes); + + if (ferror(f)) { + return ErrorFile; + } + + fclose(f); + + err = zipCloseFileInZip(file); + if (err != ZIP_OK) { + return ErrorFile; + } + + return ErrorNone; +} + +String * mailcore::CreateTemporaryZipFileFromFolder(String * folder) +{ + char tempdir[] = "/tmp/mailcore2-XXXXXX"; + char * result = mkdtemp(tempdir); + if (result == NULL) { + return NULL; + } + + String * tempDirectoryString = String::stringWithFileSystemRepresentation(tempdir); + String * path = tempDirectoryString->stringByAppendingPathComponent(folder->lastPathComponent())->stringByAppendingUTF8Format(".zip"); + + ErrorCode err = CreateZipFileFromFolder(path, folder); + if (err != ErrorNone) { + unlink(path->fileSystemRepresentation()); + unlink(tempdir); + return NULL; + } + + return path; +} + +void mailcore::RemoveTemporaryZipFile(String * zipFilename) +{ + String * tempDir = zipFilename->stringByDeletingLastPathComponent(); + unlink(zipFilename->fileSystemRepresentation()); + unlink(tempDir->fileSystemRepresentation()); +} -- cgit v1.2.3