From 1e77049bf421997de9d04a6d1e1dde4ce065affe Mon Sep 17 00:00:00 2001 From: Dmitry Isaikin Date: Wed, 6 Jul 2016 10:17:28 +0300 Subject: Use libetpan API for fetching whole IMAP attachment to file (#1461) --- .../imap/MCIMAPFetchContentToFileOperation.cpp | 16 +++++--- src/core/basetypes/MCDataStreamDecoder.cpp | 4 ++ src/core/imap/MCIMAPSession.cpp | 47 +++++++++++++++++++++- src/core/imap/MCIMAPSession.h | 5 ++- 4 files changed, 65 insertions(+), 7 deletions(-) diff --git a/src/async/imap/MCIMAPFetchContentToFileOperation.cpp b/src/async/imap/MCIMAPFetchContentToFileOperation.cpp index 82a1fa23..e6bf7740 100644 --- a/src/async/imap/MCIMAPFetchContentToFileOperation.cpp +++ b/src/async/imap/MCIMAPFetchContentToFileOperation.cpp @@ -19,7 +19,7 @@ IMAPFetchContentToFileOperation::IMAPFetchContentToFileOperation() mPartID = NULL; mEncoding = Encoding7Bit; mFilename = NULL; - mLoadingByChunksEnabled = true; + mLoadingByChunksEnabled = false; mChunksSize = 2*1024*1024; mEstimatedSize = 0; } @@ -83,9 +83,15 @@ uint32_t IMAPFetchContentToFileOperation::estimatedSize() void IMAPFetchContentToFileOperation::main() { ErrorCode error = ErrorNone; - session()->session()->fetchMessageAttachmentToFileByUID(folder(), mUid, mPartID, - mEstimatedSize, mEncoding, - mFilename, mChunksSize, - this, &error); + if (mLoadingByChunksEnabled) { + session()->session()->fetchMessageAttachmentToFileByChunksByUID(folder(), mUid, mPartID, + mEstimatedSize, mEncoding, + mFilename, mChunksSize, + this, &error); + } else { + session()->session()->fetchMessageAttachmentToFileByUID(folder(), mUid, mPartID, + mEncoding, mFilename, + this, &error); + } setError(error); } diff --git a/src/core/basetypes/MCDataStreamDecoder.cpp b/src/core/basetypes/MCDataStreamDecoder.cpp index 120cfb65..3b24c56e 100644 --- a/src/core/basetypes/MCDataStreamDecoder.cpp +++ b/src/core/basetypes/MCDataStreamDecoder.cpp @@ -88,6 +88,10 @@ ErrorCode DataStreamDecoder::appendDecodedData(Data * decodedData) return ErrorFile; } + if (decodedData->length() == 0) { + return ErrorNone; + } + if (mFile == NULL) { mFile = fopen(mFilename->fileSystemRepresentation(), "wb"); diff --git a/src/core/imap/MCIMAPSession.cpp b/src/core/imap/MCIMAPSession.cpp index e58b8cba..a5a5e06c 100644 --- a/src/core/imap/MCIMAPSession.cpp +++ b/src/core/imap/MCIMAPSession.cpp @@ -2973,7 +2973,7 @@ Data * IMAPSession::fetchMessageAttachmentByNumber(String * folder, uint32_t num return fetchMessageAttachment(folder, false, number, partID, encoding, progressCallback, pError); } -void IMAPSession::fetchMessageAttachmentToFileByUID(String * folder, uint32_t uid, String * partID, +void IMAPSession::fetchMessageAttachmentToFileByChunksByUID(String * folder, uint32_t uid, String * partID, uint32_t estimatedSize, Encoding encoding, String * outputFile, uint32_t chunkSize, IMAPProgressCallback * progressCallback, ErrorCode * pError) @@ -3051,6 +3051,51 @@ void IMAPSession::fetchMessageAttachmentToFileByUID(String * folder, uint32_t ui * pError = error; } +static bool msg_body_handler(int msg_att_type, struct mailimap_msg_att_body_section * section, + const char * bytes, size_t len, void * context) +{ + DataStreamDecoder * decoder = (DataStreamDecoder *)context; + + AutoreleasePool * pool = new AutoreleasePool(); + + Data * data = Data::dataWithBytes(bytes, (unsigned int) len); + ErrorCode error = decoder->appendData(data); + + pool->release(); + + return error == ErrorNone; +} + +void IMAPSession::fetchMessageAttachmentToFileByUID(String * folder, uint32_t uid, String * partID, + Encoding encoding, String * outputFile, + IMAPProgressCallback * progressCallback, ErrorCode * pError) +{ + DataStreamDecoder * decoder = new DataStreamDecoder(); + decoder->setEncoding(encoding); + decoder->setFilename(outputFile); + + ErrorCode error = ErrorNone; + selectIfNeeded(folder, &error); + if (error != ErrorNone) { + * pError = error; + return; + } + + mailimap_set_msg_body_handler(mImap, msg_body_handler, decoder); + + fetchNonDecodedMessageAttachment(folder, true, uid, partID, true, 0, 0, encoding, progressCallback, &error); + + mailimap_set_msg_body_handler(mImap, NULL, NULL); + + if (error == ErrorNone) { + error = decoder->flushData(); + } + + MC_SAFE_RELEASE(decoder); + + * pError = error; +} + IndexSet * IMAPSession::search(String * folder, IMAPSearchKind kind, String * searchString, ErrorCode * pError) { IMAPSearchExpression * expr; diff --git a/src/core/imap/MCIMAPSession.h b/src/core/imap/MCIMAPSession.h index 55f47de0..4d1f3894 100644 --- a/src/core/imap/MCIMAPSession.h +++ b/src/core/imap/MCIMAPSession.h @@ -122,10 +122,13 @@ namespace mailcore { virtual Data * fetchMessageAttachmentByUID(String * folder, uint32_t uid, String * partID, Encoding encoding, IMAPProgressCallback * progressCallback, ErrorCode * pError); - virtual void fetchMessageAttachmentToFileByUID(String * folder, uint32_t uid, String * partID, + virtual void fetchMessageAttachmentToFileByChunksByUID(String * folder, uint32_t uid, String * partID, uint32_t estimatedSize, Encoding encoding, String * outputFile, uint32_t chunkSize, IMAPProgressCallback * progressCallback, ErrorCode * pError); + virtual void fetchMessageAttachmentToFileByUID(String * folder, uint32_t uid, String * partID, + Encoding encoding, String * outputFile, + IMAPProgressCallback * progressCallback, ErrorCode * pError); virtual Data * fetchMessageAttachmentByNumber(String * folder, uint32_t number, String * partID, Encoding encoding, IMAPProgressCallback * progressCallback, ErrorCode * pError); -- cgit v1.2.3