aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Daryle Walker <dwalker07@yahoo.com>2016-02-22 18:47:45 -0500
committerGravatar Daryle Walker <dwalker07@yahoo.com>2016-02-22 18:47:45 -0500
commit79f2bebdb77914c44e8d92ebf0fe373971844e14 (patch)
tree51619ce4ded93aabbed152e2e13a482336878366
parentcb5963c42d0cb69df12ea9e2b19cb61298b2831d (diff)
Add upload functionality to NNTP sessions.
Add new methods to core, async, and objc NNTP sessions to upload message data. For the async and objc sessions, add classes to wrap upload operations.
-rwxr-xr-xbuild-mac/mailcore2.xcodeproj/project.pbxproj24
-rw-r--r--src/async/nntp/MCAsyncNNTP.h1
-rw-r--r--src/async/nntp/MCNNTPAsyncSession.cpp19
-rw-r--r--src/async/nntp/MCNNTPAsyncSession.h4
-rw-r--r--src/async/nntp/MCNNTPSendOperation.cpp58
-rw-r--r--src/async/nntp/MCNNTPSendOperation.h44
-rw-r--r--src/core/nntp/MCNNTPSession.cpp135
-rw-r--r--src/core/nntp/MCNNTPSession.h7
-rw-r--r--src/objc/nntp/MCONNTP.h1
-rw-r--r--src/objc/nntp/MCONNTPSendOperation.h41
-rw-r--r--src/objc/nntp/MCONNTPSendOperation.mm116
-rw-r--r--src/objc/nntp/MCONNTPSession.h27
-rw-r--r--src/objc/nntp/MCONNTPSession.mm12
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();