aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/nntp
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 /src/core/nntp
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.
Diffstat (limited to 'src/core/nntp')
-rw-r--r--src/core/nntp/MCNNTPSession.cpp135
-rw-r--r--src/core/nntp/MCNNTPSession.h7
2 files changed, 142 insertions, 0 deletions
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();