diff options
-rwxr-xr-x | build-mac/mailcore2.xcodeproj/project.pbxproj | 24 | ||||
-rw-r--r-- | src/async/nntp/MCAsyncNNTP.h | 1 | ||||
-rw-r--r-- | src/async/nntp/MCNNTPAsyncSession.cpp | 19 | ||||
-rw-r--r-- | src/async/nntp/MCNNTPAsyncSession.h | 4 | ||||
-rw-r--r-- | src/async/nntp/MCNNTPSendOperation.cpp | 58 | ||||
-rw-r--r-- | src/async/nntp/MCNNTPSendOperation.h | 44 | ||||
-rw-r--r-- | src/core/nntp/MCNNTPSession.cpp | 135 | ||||
-rw-r--r-- | src/core/nntp/MCNNTPSession.h | 7 | ||||
-rw-r--r-- | src/objc/nntp/MCONNTP.h | 1 | ||||
-rw-r--r-- | src/objc/nntp/MCONNTPSendOperation.h | 41 | ||||
-rw-r--r-- | src/objc/nntp/MCONNTPSendOperation.mm | 116 | ||||
-rw-r--r-- | src/objc/nntp/MCONNTPSession.h | 27 | ||||
-rw-r--r-- | src/objc/nntp/MCONNTPSession.mm | 12 |
13 files changed, 489 insertions, 0 deletions
diff --git a/build-mac/mailcore2.xcodeproj/project.pbxproj b/build-mac/mailcore2.xcodeproj/project.pbxproj index cc76c25f..64058b61 100755 --- a/build-mac/mailcore2.xcodeproj/project.pbxproj +++ b/build-mac/mailcore2.xcodeproj/project.pbxproj @@ -962,6 +962,14 @@ 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 */; }; + F382219F1C7A626700E00721 /* MCNNTPSendOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F382219E1C7A626700E00721 /* MCNNTPSendOperation.cpp */; }; + F38221A01C7A626700E00721 /* MCNNTPSendOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F382219E1C7A626700E00721 /* MCNNTPSendOperation.cpp */; }; + F38221A31C7AAD8100E00721 /* MCONNTPSendOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = F38221A21C7AAD8100E00721 /* MCONNTPSendOperation.mm */; }; + F38221A41C7AAD8100E00721 /* MCONNTPSendOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = F38221A21C7AAD8100E00721 /* MCONNTPSendOperation.mm */; }; + F38221A51C7B629B00E00721 /* MCNNTPSendOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = F382219D1C7A60A800E00721 /* MCNNTPSendOperation.h */; }; + F38221A61C7B62E900E00721 /* MCONNTPSendOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = F38221A11C7AAD8100E00721 /* MCONNTPSendOperation.h */; }; + F38221A71C7B638200E00721 /* MCNNTPSendOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = F382219D1C7A60A800E00721 /* MCNNTPSendOperation.h */; }; + F38221A81C7B63E500E00721 /* MCONNTPSendOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = F38221A11C7AAD8100E00721 /* MCONNTPSendOperation.h */; }; F87F190C16BB62B00012652F /* MCOIMAPFetchFoldersOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = F87F190B16BB62B00012652F /* MCOIMAPFetchFoldersOperation.mm */; }; F8EA941716BB1C9D0011AC6F /* MCOIMAPSession.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = F8EA941416BAED6E0011AC6F /* MCOIMAPSession.h */; }; /* End PBXBuildFile section */ @@ -1027,6 +1035,8 @@ dstPath = include/MailCore; dstSubfolderSpec = 16; files = ( + F38221A81C7B63E500E00721 /* MCONNTPSendOperation.h in CopyFiles */, + F38221A71C7B638200E00721 /* MCNNTPSendOperation.h in CopyFiles */, C6BEC1AB1B1256C100546519 /* MCHTMLCleaner.h in CopyFiles */, 27E91D601A80D3F4005A3244 /* MCMXRecordResolverOperation.h in CopyFiles */, 27478E861A76475F004AE621 /* MCOAccountValidator.h in CopyFiles */, @@ -1264,6 +1274,8 @@ dstPath = include/MailCore; dstSubfolderSpec = 16; files = ( + F38221A61C7B62E900E00721 /* MCONNTPSendOperation.h in CopyFiles */, + F38221A51C7B629B00E00721 /* MCNNTPSendOperation.h in CopyFiles */, C6BEC1AA1B1256BA00546519 /* MCHTMLCleaner.h in CopyFiles */, 276A65D01A7B7E7D008722C2 /* MCMXRecordResolverOperation.h in CopyFiles */, 27478E881A7647AC004AE621 /* MCOAccountValidator.h in CopyFiles */, @@ -2107,6 +2119,10 @@ DAACAD5017886807000B4517 /* MCHTMLRendererIMAPDataCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCHTMLRendererIMAPDataCallback.h; sourceTree = "<group>"; }; DAD28C891783CFFC00F2BB8F /* MCHTMLBodyRendererTemplateCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCHTMLBodyRendererTemplateCallback.cpp; sourceTree = "<group>"; }; DAD28C8A1783CFFC00F2BB8F /* MCHTMLBodyRendererTemplateCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCHTMLBodyRendererTemplateCallback.h; sourceTree = "<group>"; }; + F382219D1C7A60A800E00721 /* MCNNTPSendOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCNNTPSendOperation.h; sourceTree = "<group>"; }; + F382219E1C7A626700E00721 /* MCNNTPSendOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCNNTPSendOperation.cpp; sourceTree = "<group>"; }; + F38221A11C7AAD8100E00721 /* MCONNTPSendOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCONNTPSendOperation.h; sourceTree = "<group>"; }; + F38221A21C7AAD8100E00721 /* MCONNTPSendOperation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCONNTPSendOperation.mm; sourceTree = "<group>"; }; F87F190816BB62690012652F /* MCOIMAPFetchFoldersOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOIMAPFetchFoldersOperation.h; sourceTree = "<group>"; }; F87F190B16BB62B00012652F /* MCOIMAPFetchFoldersOperation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOIMAPFetchFoldersOperation.mm; sourceTree = "<group>"; }; F8EA941416BAED6E0011AC6F /* MCOIMAPSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOIMAPSession.h; sourceTree = "<group>"; }; @@ -2265,6 +2281,8 @@ 84D7372E199BF704005124E5 /* MCNNTPOperation.cpp */, 84D7372F199BF704005124E5 /* MCNNTPOperation.h */, 84D7373F199BF887005124E5 /* MCNNTPOperationCallback.h */, + F382219D1C7A60A800E00721 /* MCNNTPSendOperation.h */, + F382219E1C7A626700E00721 /* MCNNTPSendOperation.cpp */, ); path = nntp; sourceTree = "<group>"; @@ -2294,6 +2312,8 @@ 84D7378E199C02A8005124E5 /* MCONNTPDisconnectOperation.mm */, 84D73791199C0511005124E5 /* MCONNTPGroupInfo.h */, 84D73792199C0511005124E5 /* MCONNTPGroupInfo.mm */, + F38221A11C7AAD8100E00721 /* MCONNTPSendOperation.h */, + F38221A21C7AAD8100E00721 /* MCONNTPSendOperation.mm */, ); path = nntp; sourceTree = "<group>"; @@ -3664,6 +3684,7 @@ C6F61F9917016B460073032E /* MCOIMAPSearchExpression.mm in Sources */, C6F61F9F17016EA10073032E /* MCOIMAPFolderInfo.mm in Sources */, C6D4FD3F19FB7534001F7E01 /* MCMessageParserMac.mm in Sources */, + F38221A31C7AAD8100E00721 /* MCONNTPSendOperation.mm in Sources */, C6F61FB51702AB340073032E /* MCOIMAPBaseOperation.mm in Sources */, C608167517759967001F1018 /* MCSMTPDisconnectOperation.cpp in Sources */, C6A81BBF17068E5E00882C15 /* MCOSMTPSession.mm in Sources */, @@ -3707,6 +3728,7 @@ 9EF9AB09175F2EC60027FA3B /* MCOIMAPFolderStatus.mm in Sources */, 9EF9AB11175F319A0027FA3B /* MCIMAPFolderStatusOperation.cpp in Sources */, 9EF9AB19175F36600027FA3B /* MCOIMAPFolderStatusOperation.mm in Sources */, + F382219F1C7A626700E00721 /* MCNNTPSendOperation.cpp in Sources */, 9E774D891767C7F60065EB9B /* MCIMAPFolderStatus.cpp in Sources */, DAD28C8B1783CFFC00F2BB8F /* MCHTMLBodyRendererTemplateCallback.cpp in Sources */, BD63713B177DFF080094121B /* MCLibetpan.cpp in Sources */, @@ -3940,6 +3962,7 @@ C6E665BC1796500C0063F2CF /* unzip.c in Sources */, C6BA2C121705F4E6003F0E9E /* MCOIMAPSearchExpression.mm in Sources */, C6D4FD4019FB7786001F7E01 /* MCMessageParserMac.mm in Sources */, + F38221A41C7AAD8100E00721 /* MCONNTPSendOperation.mm in Sources */, C6BA2C131705F4E6003F0E9E /* MCOIMAPFolderInfo.mm in Sources */, C6BA2C141705F4E6003F0E9E /* MCOIMAPBaseOperation.mm in Sources */, C608167617759968001F1018 /* MCSMTPDisconnectOperation.cpp in Sources */, @@ -3983,6 +4006,7 @@ C6CF62CB175324F0006398B9 /* MCNetService.cpp in Sources */, 9EF9AB0A175F2EC60027FA3B /* MCOIMAPFolderStatus.mm in Sources */, 9EF9AB12175F319A0027FA3B /* MCIMAPFolderStatusOperation.cpp in Sources */, + F38221A01C7A626700E00721 /* MCNNTPSendOperation.cpp in Sources */, 9EF9AB1A175F36600027FA3B /* MCOIMAPFolderStatusOperation.mm in Sources */, 9E774D8A1767C7F60065EB9B /* MCIMAPFolderStatus.cpp in Sources */, DAD28C8C1783CFFC00F2BB8F /* MCHTMLBodyRendererTemplateCallback.cpp in Sources */, diff --git a/src/async/nntp/MCAsyncNNTP.h b/src/async/nntp/MCAsyncNNTP.h index 914cc754..57b80cb8 100644 --- a/src/async/nntp/MCAsyncNNTP.h +++ b/src/async/nntp/MCAsyncNNTP.h @@ -18,6 +18,7 @@ #include <MailCore/MCNNTPListNewsgroupsOperation.h> #include <MailCore/MCNNTPFetchOverviewOperation.h> #include <MailCore/MCNNTPFetchServerTimeOperation.h> +#include <MailCore/MCNNTPSendOperation.h> #include <MailCore/MCNNTPOperationCallback.h> #endif diff --git a/src/async/nntp/MCNNTPAsyncSession.cpp b/src/async/nntp/MCNNTPAsyncSession.cpp index ad74f7a9..ddd4c804 100644 --- a/src/async/nntp/MCNNTPAsyncSession.cpp +++ b/src/async/nntp/MCNNTPAsyncSession.cpp @@ -16,6 +16,7 @@ #include "MCNNTPFetchOverviewOperation.h" #include "MCNNTPCheckAccountOperation.h" #include "MCNNTPFetchServerTimeOperation.h" +#include "MCNNTPSendOperation.h" #include "MCNNTPDisconnectOperation.h" #include "MCOperationQueueCallback.h" #include "MCConnectionLogger.h" @@ -236,6 +237,24 @@ NNTPListNewsgroupsOperation * NNTPAsyncSession::listDefaultNewsgroupsOperation() return op; } +NNTPSendOperation * NNTPAsyncSession::sendMessageOperation(Data * messageData) +{ + NNTPSendOperation * op = new NNTPSendOperation(); + op->setSession(this); + op->setMessageData(messageData); + op->autorelease(); + return op; +} + +NNTPSendOperation * NNTPAsyncSession::sendMessageOperation(String * filename) +{ + NNTPSendOperation * op = new NNTPSendOperation(); + op->setSession(this); + op->setMessageFilepath(filename); + op->autorelease(); + return op; +} + NNTPOperation * NNTPAsyncSession::disconnectOperation() { NNTPDisconnectOperation * op = new NNTPDisconnectOperation(); diff --git a/src/async/nntp/MCNNTPAsyncSession.h b/src/async/nntp/MCNNTPAsyncSession.h index b3e40ea8..c41066ac 100644 --- a/src/async/nntp/MCNNTPAsyncSession.h +++ b/src/async/nntp/MCNNTPAsyncSession.h @@ -16,6 +16,7 @@ namespace mailcore { class NNTPFetchOverviewOperation; class NNTPListNewsgroupsOperation; class NNTPFetchServerTimeOperation; + class NNTPSendOperation; class NNTPOperationQueueCallback; class NNTPConnectionLogger; @@ -72,6 +73,9 @@ namespace mailcore { virtual NNTPListNewsgroupsOperation * listAllNewsgroupsOperation(); virtual NNTPListNewsgroupsOperation * listDefaultNewsgroupsOperation(); + virtual NNTPSendOperation * sendMessageOperation(Data * messageData); + virtual NNTPSendOperation * sendMessageOperation(String * filename); + virtual NNTPOperation * disconnectOperation(); virtual NNTPOperation * checkAccountOperation(); diff --git a/src/async/nntp/MCNNTPSendOperation.cpp b/src/async/nntp/MCNNTPSendOperation.cpp new file mode 100644 index 00000000..d5f27928 --- /dev/null +++ b/src/async/nntp/MCNNTPSendOperation.cpp @@ -0,0 +1,58 @@ +// +// MCNNTPSendOperation.cpp +// mailcore2 +// +// Created by Daryle Walker on 2/21/16. +// Copyright © 2016 MailCore. All rights reserved. +// + +#include "MCNNTPSendOperation.h" + +#include "MCNNTPAsyncSession.h" +#include "MCNNTPSession.h" + +using namespace mailcore; + +NNTPSendOperation::NNTPSendOperation() +{ + mMessageData = NULL; + mMessageFilepath = NULL; +} + +NNTPSendOperation::~NNTPSendOperation() +{ + MC_SAFE_RELEASE(mMessageFilepath); + MC_SAFE_RELEASE(mMessageData); +} + +void NNTPSendOperation::setMessageData(Data * data) +{ + MC_SAFE_REPLACE_RETAIN(Data, mMessageData, data); +} + +Data * NNTPSendOperation::messageData() +{ + return mMessageData; +} + +void NNTPSendOperation::setMessageFilepath(String * path) +{ + MC_SAFE_REPLACE_RETAIN(String, mMessageFilepath, path); +} + +String * NNTPSendOperation::messageFilepath() +{ + return mMessageFilepath; +} + +void NNTPSendOperation::main() +{ + ErrorCode error; + if (mMessageFilepath != NULL) { + session()->session()->sendMessage(mMessageFilepath, this, &error); + } + else { + session()->session()->sendMessage(mMessageData, this, &error); + } + setError(error); +} diff --git a/src/async/nntp/MCNNTPSendOperation.h b/src/async/nntp/MCNNTPSendOperation.h new file mode 100644 index 00000000..d859cd58 --- /dev/null +++ b/src/async/nntp/MCNNTPSendOperation.h @@ -0,0 +1,44 @@ +// +// MCNNTPSendOperation.h +// mailcore2 +// +// Created by Daryle Walker on 2/21/16. +// Copyright © 2016 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCNNTPSENDOPERATION_H + +#define MAILCORE_MCNNTPSENDOPERATION_H + +#include <MailCore/MCBaseTypes.h> +#include <MailCore/MCAbstract.h> +#include <MailCore/MCNNTPOperation.h> + +#ifdef __cplusplus + +namespace mailcore { + + class MAILCORE_EXPORT NNTPSendOperation : public NNTPOperation { + public: + NNTPSendOperation(); + virtual ~NNTPSendOperation(); + + virtual void setMessageData(Data * data); + virtual Data * messageData(); + + virtual void setMessageFilepath(String * path); + virtual String * messageFilepath(); + + public: // subclass behavior + virtual void main(); + + private: + Data * mMessageData; + String * mMessageFilepath; + }; + +} + +#endif + +#endif diff --git a/src/core/nntp/MCNNTPSession.cpp b/src/core/nntp/MCNNTPSession.cpp index 933f10f2..c40301a4 100644 --- a/src/core/nntp/MCNNTPSession.cpp +++ b/src/core/nntp/MCNNTPSession.cpp @@ -15,6 +15,7 @@ #include "MCNNTPGroupInfo.h" #include "MCMessageHeader.h" +#include "MCNNTPProgressCallback.h" #include "MCConnectionLoggerUtils.h" #include "MCCertificateUtils.h" #include "MCLibetpan.h" @@ -45,6 +46,7 @@ void NNTPSession::init() mTimeout = 30; mNNTP = NULL; + mProgressCallback = NULL; mState = STATE_DISCONNECTED; mConnectionLogger = NULL; } @@ -138,6 +140,21 @@ bool NNTPSession::checkCertificate() return mailcore::checkCertificate(mNNTP->nntp_stream, hostname()); } +void NNTPSession::body_progress(size_t current, size_t maximum, void * context) +{ + NNTPSession * session; + + session = (NNTPSession *) context; + session->bodyProgress((unsigned int) current, (unsigned int) maximum); +} + +void NNTPSession::bodyProgress(unsigned int current, unsigned int maximum) +{ + if (mProgressCallback != NULL) { + mProgressCallback->bodyProgress(this, current, maximum); + } +} + static void logger(newsnntp * nntp, int log_type, const char * buffer, size_t size, void * context) { NNTPSession * session = (NNTPSession *) context; @@ -605,6 +622,124 @@ Array * NNTPSession::fetchOverArticlesInRange(Range range, String * groupName, E return result; } +void NNTPSession::sendMessage(Data * messageData, NNTPProgressCallback * callback, ErrorCode * pError) +{ + int r; + + messageData = dataWithFilteredBcc(messageData); + + mProgressCallback = callback; + bodyProgress(0, messageData->length()); + + MCLog("setup"); + + MCLog("connect"); + loginIfNeeded(pError); + if (* pError != ErrorNone) { + goto err; + } + + MCLog("send"); + r = newsnntp_post(mNNTP, messageData->bytes(), messageData->length()); + + String * response; + + response = NULL; + if (mNNTP->nntp_response != NULL) { + response = String::stringWithUTF8Characters(mNNTP->nntp_response); + } + + if (r == NEWSNNTP_ERROR_STREAM) { + * pError = ErrorConnection; + goto err; + } + else if (r != NEWSNNTP_NO_ERROR) { + * pError = ErrorSendMessage; + goto err; + } + + bodyProgress(messageData->length(), messageData->length()); + * pError = ErrorNone; + +err: + mProgressCallback = NULL; +} + +void NNTPSession::sendMessage(String * messagePath, NNTPProgressCallback * callback, ErrorCode * pError) +{ + Data * messageData = Data::dataWithContentsOfFile(messagePath); + if (!messageData) { + * pError = ErrorFile; + return; + } + + return sendMessage(messageData, callback, pError); +} + +static void mmapStringDeallocator(char * bytes, unsigned int length) { + mmap_string_unref(bytes); +} + +Data * NNTPSession::dataWithFilteredBcc(Data * data) +{ + int r; + size_t idx; + struct mailimf_message * msg; + + 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; + + int hasRecipient = 0; + bool bccWasActuallyRemoved = false; + 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); + bccWasActuallyRemoved = true; + break; + } + else if ((field->fld_type == MAILIMF_FIELD_TO) || (field->fld_type == MAILIMF_FIELD_CC)) { + hasRecipient = 1; + } + } + if (!hasRecipient) { + struct mailimf_address_list * imfTo; + imfTo = mailimf_address_list_new_empty(); + mailimf_address_list_add_parse(imfTo, (char *) "Undisclosed recipients:;"); + struct mailimf_to * toField = mailimf_to_new(imfTo); + struct mailimf_field * field = mailimf_field_new(MAILIMF_FIELD_TO, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, toField, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + mailimf_fields_add(fields, field); + } + + Data * result; + if (!hasRecipient || bccWasActuallyRemoved) { + MMAPString * str = mmap_string_new(""); + 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); + + mmap_string_ref(str); + + result = Data::data(); + result->takeBytesOwnership(str->str, (unsigned int) str->len, mmapStringDeallocator); + } + else { + // filter Bcc and modify To: only if necessary. + result = data; + } + + mailimf_message_free(msg); + + return result; +} + void NNTPSession::selectGroup(String * folder, ErrorCode * pError) { int r; diff --git a/src/core/nntp/MCNNTPSession.h b/src/core/nntp/MCNNTPSession.h index ec0080ed..94669edd 100644 --- a/src/core/nntp/MCNNTPSession.h +++ b/src/core/nntp/MCNNTPSession.h @@ -57,6 +57,9 @@ namespace mailcore { virtual time_t fetchServerDate(ErrorCode * pError); + virtual void sendMessage(Data * messageData, NNTPProgressCallback * callback, ErrorCode * pError); + virtual void sendMessage(String * messagePath, NNTPProgressCallback * callback, ErrorCode * pError); + virtual void setConnectionLogger(ConnectionLogger * logger); virtual ConnectionLogger * connectionLogger(); @@ -70,11 +73,15 @@ namespace mailcore { time_t mTimeout; newsnntp * mNNTP; + NNTPProgressCallback * mProgressCallback; int mState; ConnectionLogger * mConnectionLogger; void init(); + Data * dataWithFilteredBcc(Data * data); + static void body_progress(size_t current, size_t maximum, void * context); + void bodyProgress(unsigned int current, unsigned int maximum); bool checkCertificate(); void setup(); void unsetup(); diff --git a/src/objc/nntp/MCONNTP.h b/src/objc/nntp/MCONNTP.h index 71979dfa..213384c4 100644 --- a/src/objc/nntp/MCONNTP.h +++ b/src/objc/nntp/MCONNTP.h @@ -18,6 +18,7 @@ #include <MailCore/MCONNTPListNewsgroupsOperation.h> #include <MailCore/MCONNTPFetchOverviewOperation.h> #include <MailCore/MCONNTPFetchServerTimeOperation.h> +#include <MailCore/MCONNTPSendOperation.h> #include <MailCore/MCONNTPGroupInfo.h> #endif diff --git a/src/objc/nntp/MCONNTPSendOperation.h b/src/objc/nntp/MCONNTPSendOperation.h new file mode 100644 index 00000000..b59c6e80 --- /dev/null +++ b/src/objc/nntp/MCONNTPSendOperation.h @@ -0,0 +1,41 @@ +// +// MCONNTPSendOperation.h +// mailcore2 +// +// Created by Daryle Walker on 2/21/16. +// Copyright © 2016 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCONNTPSENDOPERATION_H + +#define MAILCORE_MCONNTPSENDOPERATION_H + +#import <Foundation/Foundation.h> +#import <MailCore/MCONNTPOperation.h> + +/** Send a message from NNTP3 */ + +typedef void (^MCONNTPOperationProgressBlock)(unsigned int current, unsigned int maximum); + +NS_ASSUME_NONNULL_BEGIN +@interface MCONNTPSendOperation : MCONNTPOperation + +/** This block will be called as data is downloaded from the network */ +@property (nonatomic, copy) MCONNTPOperationProgressBlock progress; + +/** + Starts the asynchronous send operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in MCOConstants.h + */ +- (void) start:(void (^)(NSError * __nullable error))completionBlock; + +@end +NS_ASSUME_NONNULL_END + +#endif diff --git a/src/objc/nntp/MCONNTPSendOperation.mm b/src/objc/nntp/MCONNTPSendOperation.mm new file mode 100644 index 00000000..db1277af --- /dev/null +++ b/src/objc/nntp/MCONNTPSendOperation.mm @@ -0,0 +1,116 @@ +// +// MCONNTPSendOperation.mm +// mailcore2 +// +// Created by Daryle Walker on 2/21/16. +// Copyright © 2016 MailCore. All rights reserved. +// + +#import "MCONNTPSendOperation.h" + +#import "MCAsyncNNTP.h" + +#import "MCOUtils.h" +#import "MCOOperation+Private.h" + +#define nativeType mailcore::NNTPSendOperation + +typedef void (^CompletionType)(NSError *error); + +@interface MCONNTPSendOperation () + +- (void) bodyProgress:(unsigned int)current maximum:(unsigned int)maximum; + +@end + +class MCONNTPSendOperationCallback : public mailcore::NNTPOperationCallback { +public: + MCONNTPSendOperationCallback(MCONNTPSendOperation * op) + { + mOperation = op; + } + virtual ~MCONNTPSendOperationCallback() + { + } + + virtual void bodyProgress(mailcore::NNTPOperation * session, unsigned int current, unsigned int maximum) { + [mOperation bodyProgress:current maximum:maximum]; + } + +private: + MCONNTPSendOperation * mOperation; +}; + +@implementation MCONNTPSendOperation { + CompletionType _completionBlock; + MCONNTPSendOperationCallback * _popCallback; + MCONNTPOperationProgressBlock _progress; +} + +@synthesize progress = _progress; + ++ (void) load +{ + MCORegisterClass(self, &typeid(nativeType)); +} + ++ (NSObject *) mco_objectWithMCObject:(mailcore::Object *)object +{ + nativeType * op = (nativeType *) object; + return [[[self alloc] initWithMCOperation:op] autorelease]; +} + +- (instancetype) initWithMCOperation:(mailcore::Operation *)op +{ + self = [super initWithMCOperation:op]; + + _popCallback = new MCONNTPSendOperationCallback(self); + ((mailcore::NNTPOperation *) op)->setNNTPCallback(_popCallback); + + return self; +} + +- (void) dealloc +{ + [_progress release]; + [_completionBlock release]; + delete _popCallback; + [super dealloc]; +} + +- (void) start:(void (^)(NSError *error))completionBlock +{ + _completionBlock = [completionBlock copy]; + [self start]; +} + +- (void) cancel +{ + [_completionBlock release]; + _completionBlock = nil; + [super cancel]; +} + +- (void) operationCompleted +{ + if (_completionBlock == NULL) + return; + + nativeType *op = MCO_NATIVE_INSTANCE; + if (op->error() == mailcore::ErrorNone) { + _completionBlock(nil); + } else { + _completionBlock([NSError mco_errorWithErrorCode:op->error()]); + } + [_completionBlock release]; + _completionBlock = nil; +} + +- (void) bodyProgress:(unsigned int)current maximum:(unsigned int)maximum +{ + if (_progress != NULL) { + _progress(current, maximum); + } +} + +@end diff --git a/src/objc/nntp/MCONNTPSession.h b/src/objc/nntp/MCONNTPSession.h index 29fe18af..84b1c5e7 100644 --- a/src/objc/nntp/MCONNTPSession.h +++ b/src/objc/nntp/MCONNTPSession.h @@ -20,6 +20,7 @@ @class MCONNTPListNewsgroupsOperation; @class MCONNTPFetchOverviewOperation; @class MCONNTPFetchServerTimeOperation; +@class MCONNTPSendOperation; @class MCONNTPOperation; @class MCOIndexSet; @@ -182,6 +183,32 @@ NS_ASSUME_NONNULL_BEGIN - (MCONNTPListNewsgroupsOperation *) listDefaultNewsgroupsOperation; /** + Returns an operation that will send the given message through NNTP. + It will use the newsgroups set in the message data. + It will also filter out Bcc from the content of the message. + + Generate RFC 822 data using MCOMessageBuilder + + MCONNTPOperation * op = [session sendOperationWithData:rfc822Data]; + [op start:^(NSError * __nullable error) { + ... + }]; + */ +- (MCONNTPSendOperation *) sendOperationWithData:(NSData *)messageData; + +/** + Returns an operation that will send the message from the given file through NNTP. + It will use the newsgroups set in the message data. + It will also filter out Bcc from the content of the message. + + MCONNTPOperation * op = [session sendOperationWithContentsOfFile:rfc822DataFilename]; + [op start:^(NSError * __nullable error) { + ... + }]; + */ +- (MCONNTPSendOperation *) sendOperationWithContentsOfFile:(NSString *)path; + +/** Returns an operation that will disconnect the session. MCONNTPOperation * op = [session disconnectOperation]; diff --git a/src/objc/nntp/MCONNTPSession.mm b/src/objc/nntp/MCONNTPSession.mm index 8237145c..4a6e0c9a 100644 --- a/src/objc/nntp/MCONNTPSession.mm +++ b/src/objc/nntp/MCONNTPSession.mm @@ -14,6 +14,7 @@ #import "MCONNTPOperation.h" #import "MCOOperation+Private.h" #import "MCONNTPFetchAllArticlesOperation.h" +#import "MCONNTPSendOperation.h" #import "MCONNTPOperation+Private.h" #include "MCOperationQueueCallback.h" @@ -205,6 +206,17 @@ MCO_OBJC_SYNTHESIZE_SCALAR(dispatch_queue_t, dispatch_queue_t, setDispatchQueue, return MCO_TO_OBJC_OP(coreOp); } +- (MCONNTPSendOperation *) sendOperationWithData:(NSData *)messageData { + mailcore::NNTPSendOperation * coreOp = MCO_NATIVE_INSTANCE->sendMessageOperation(MCO_FROM_OBJC(mailcore::Data, messageData)); + return MCO_TO_OBJC_OP(coreOp); +} + +- (MCONNTPSendOperation *) sendOperationWithContentsOfFile:(NSString *)path +{ + mailcore::NNTPSendOperation * coreOp = MCO_NATIVE_INSTANCE->sendMessageOperation(MCO_FROM_OBJC(mailcore::String, path)); + return MCO_TO_OBJC_OP(coreOp); +} + - (MCONNTPOperation *) disconnectOperation { mailcore::NNTPOperation * coreOp = MCO_NATIVE_INSTANCE->disconnectOperation(); |