diff options
author | Hoà V. DINH <dinh.viet.hoa@gmail.com> | 2016-02-26 07:43:33 -0800 |
---|---|---|
committer | Hoà V. DINH <dinh.viet.hoa@gmail.com> | 2016-02-26 07:43:33 -0800 |
commit | eac836a9858e765e0fb07f1b1f4b325893666fe6 (patch) | |
tree | 42b328e5b80752776658de78cea84a38afec4c3e /src/core | |
parent | dbd4f63735beab5f2014597d3b1e0d67af03fe97 (diff) | |
parent | 38cae4a0a329da2618c212f545d3d8e10417af72 (diff) |
Merge pull request #1367 from CTMacUser/NNTPSendOperation
Add upload functionality to NNTP sessions.
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/nntp/MCNNTPSession.cpp | 135 | ||||
-rw-r--r-- | src/core/nntp/MCNNTPSession.h | 7 |
2 files changed, 142 insertions, 0 deletions
diff --git a/src/core/nntp/MCNNTPSession.cpp b/src/core/nntp/MCNNTPSession.cpp index 933f10f2..e5004432 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::postMessage(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::postMessage(String * messagePath, NNTPProgressCallback * callback, ErrorCode * pError) +{ + Data * messageData = Data::dataWithContentsOfFile(messagePath); + if (!messageData) { + * pError = ErrorFile; + return; + } + + return postMessage(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..22734f2d 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 postMessage(Data * messageData, NNTPProgressCallback * callback, ErrorCode * pError); + virtual void postMessage(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(); |