diff options
author | Dmitry Isaikin <isaikin-dmitry@yandex.ru> | 2016-06-06 04:28:53 +0400 |
---|---|---|
committer | Hoà V. DINH <dinh.viet.hoa@gmail.com> | 2016-06-05 17:28:53 -0700 |
commit | eeed76e48c830fe742eadd435682f3b1e6036f83 (patch) | |
tree | 36bad63fccde47e6cdecb7033f65a3d75e1bbb71 /src/core | |
parent | 6dbe79ccf3f085da9a195ee3f9a59cb4449f6505 (diff) |
Add possibility of fetching message attachment by chunks and store it to file. (#1438)
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/basetypes/MCData.cpp | 170 | ||||
-rw-r--r-- | src/core/basetypes/MCData.h | 4 | ||||
-rw-r--r-- | src/core/basetypes/MCDataDecoderUtils.cpp | 192 | ||||
-rw-r--r-- | src/core/basetypes/MCDataDecoderUtils.h | 25 | ||||
-rw-r--r-- | src/core/basetypes/MCDataStreamDecoder.cpp | 105 | ||||
-rw-r--r-- | src/core/basetypes/MCDataStreamDecoder.h | 51 | ||||
-rw-r--r-- | src/core/imap/MCIMAPSession.cpp | 162 | ||||
-rw-r--r-- | src/core/imap/MCIMAPSession.h | 13 | ||||
-rw-r--r-- | src/core/rfc822/MCAttachment.cpp | 4 |
9 files changed, 551 insertions, 175 deletions
diff --git a/src/core/basetypes/MCData.cpp b/src/core/basetypes/MCData.cpp index 796f580e..1fee18aa 100644 --- a/src/core/basetypes/MCData.cpp +++ b/src/core/basetypes/MCData.cpp @@ -28,6 +28,7 @@ #include "MCBase64.h" #include "MCSet.h" #include "MCLock.h" +#include "MCDataDecoderUtils.h" #define MCDATA_DEFAULT_CHARSET "iso-8859-1" @@ -565,170 +566,10 @@ Data * Data::dataWithContentsOfFile(String * filename) return data; } -static size_t uudecode(const char * text, size_t size, char * dst, size_t dst_buf_size) -{ - unsigned int count = 0; - const char *b = text; /* beg */ - const char *s = b; /* src */ - const char *e = b+size; /* end */ - char *d = dst; - int out = (*s++ & 0x7f) - 0x20; - - /* don't process lines without leading count character */ - if (out < 0) - return size; - - /* dummy check. user must allocate buffer with appropriate length */ - if (dst_buf_size < out) - return size; - - /* don't process begin and end lines */ - if ((strncasecmp((const char *)b, "begin ", 6) == 0) || - (strncasecmp((const char *)b, "end", 3) == 0)) - return size; - - //while (s < e - 4) - while (s < e && count < out) - { - int v = 0; - int i; - for (i = 0; i < 4; i += 1) { - char c = *s++; - v = v << 6 | ((c - 0x20) & 0x3F); - } - for (i = 2; i >= 0; i -= 1) { - char c = (char) (v & 0xFF); - d[i] = c; - v = v >> 8; - } - d += 3; - count += 3; - } - return count; -} - -static void decodedPartDeallocator(char * decoded, unsigned int decoded_length) { - mailmime_decoded_part_free(decoded); -}; - Data * Data::decodedDataUsingEncoding(Encoding encoding) { - const char * text; - size_t text_length; - - text = bytes(); - text_length = length(); - - switch (encoding) { - case Encoding7Bit: - case Encoding8Bit: - case EncodingBinary: - case EncodingOther: - default: - { - return this; - } - case EncodingBase64: - case EncodingQuotedPrintable: - { - char * decoded; - size_t decoded_length; - size_t cur_token; - int mime_encoding; - Data * data; - - switch (encoding) { - default: //disable warning - case EncodingBase64: - mime_encoding = MAILMIME_MECHANISM_BASE64; - break; - case EncodingQuotedPrintable: - mime_encoding = MAILMIME_MECHANISM_QUOTED_PRINTABLE; - break; - } - - cur_token = 0; - mailmime_part_parse(text, text_length, &cur_token, - mime_encoding, &decoded, &decoded_length); - - data = Data::data(); - data->takeBytesOwnership(decoded, (unsigned int) decoded_length, decodedPartDeallocator); - return data; - } - case EncodingUUEncode: - { - Data * data; - const char * current_p; - - data = Data::dataWithCapacity((unsigned int) text_length); - - current_p = text; - while (1) { - /* In uuencoded files each data line usually have 45 bytes of decoded data. - Maximum possible length is limited by (0x7f-0x20) bytes. - So 256-bytes buffer is enough. */ - char decoded_buf[256]; - size_t decoded_length; - size_t length; - const char * p; - const char * p1; - const char * p2; - const char * end_line; - - p1 = strchr(current_p, '\n'); - p2 = strchr(current_p, '\r'); - if (p1 == NULL) { - p = p2; - } - else if (p2 == NULL) { - p = p1; - } - else { - if (p1 - current_p < p2 - current_p) { - p = p1; - } - else { - p = p2; - } - } - end_line = p; - if (p != NULL) { - while ((size_t) (p - text) < text_length) { - if ((* p != '\r') && (* p != '\n')) { - break; - } - p ++; - } - } - if (p == NULL) { - length = text_length - (current_p - text); - } - else { - length = end_line - current_p; - } - if (length == 0) { - break; - } - decoded_length = uudecode(current_p, length, decoded_buf, sizeof(decoded_buf)); - if (decoded_length != 0 && decoded_length < length) { - data->appendBytes(decoded_buf, (unsigned int) decoded_length); - } - - if (p == NULL) - break; - - current_p = p; - while ((size_t) (current_p - text) < text_length) { - if ((* current_p != '\r') && (* current_p != '\n')) { - break; - } - current_p ++; - } - } - - return data; - } - } + Data * unused = NULL; + return MCDecodeData(this, encoding, false, &unused); } Data * Data::data() @@ -765,11 +606,14 @@ void Data::importSerializable(HashMap * serializable) ErrorCode Data::writeToFile(String * filename) { FILE * f = fopen(filename->fileSystemRepresentation(), "wb"); + if (f == NULL) { return ErrorFile; } size_t result = fwrite(bytes(), length(), 1, f); - fclose(f); + if (fclose(f) != 0) { + return ErrorFile; + } if (result == 0) { return ErrorFile; } diff --git a/src/core/basetypes/MCData.h b/src/core/basetypes/MCData.h index 11c0d6c2..ef7acda3 100644 --- a/src/core/basetypes/MCData.h +++ b/src/core/basetypes/MCData.h @@ -46,11 +46,11 @@ namespace mailcore { virtual String * stringWithDetectedCharset(String * charset, bool isHTML); virtual String * stringWithCharset(const char * charset); virtual Data * decodedDataUsingEncoding(Encoding encoding); - + virtual String * base64String(); virtual ErrorCode writeToFile(String * filename); - + public: // private virtual String * charsetWithFilteredHTML(bool filterHTML, String * hintCharset = NULL); diff --git a/src/core/basetypes/MCDataDecoderUtils.cpp b/src/core/basetypes/MCDataDecoderUtils.cpp new file mode 100644 index 00000000..4ea739ce --- /dev/null +++ b/src/core/basetypes/MCDataDecoderUtils.cpp @@ -0,0 +1,192 @@ +#include "MCDataDecoderUtils.h" + +#include <libetpan/libetpan.h> + +#include <string.h> +#include <strings.h> + +namespace mailcore { + +static size_t uudecode(const char * text, size_t size, char * dst, size_t dst_buf_size) +{ + unsigned int count = 0; + const char *b = text; /* beg */ + const char *s = b; /* src */ + const char *e = b+size; /* end */ + char *d = dst; + int out = (*s++ & 0x7f) - 0x20; + + /* don't process lines without leading count character */ + if (out < 0) + return size; + + /* dummy check. user must allocate buffer with appropriate length */ + if (dst_buf_size < out) + return size; + + /* don't process begin and end lines */ + if ((strncasecmp((const char *)b, "begin ", 6) == 0) || + (strncasecmp((const char *)b, "end", 3) == 0)) + return size; + + while (s < e && count < out) + { + int v = 0; + int i; + for (i = 0; i < 4; i += 1) { + char c = *s++; + v = v << 6 | ((c - 0x20) & 0x3F); + } + for (i = 2; i >= 0; i -= 1) { + char c = (char) (v & 0xFF); + d[i] = c; + v = v >> 8; + } + d += 3; + count += 3; + } + return count; +} + +static void decodedPartDeallocator(char * decoded, unsigned int decoded_length) { + mailmime_decoded_part_free(decoded); +} + +Data * MCDecodeData(Data * encodedData, Encoding encoding, bool partialContent, Data ** pRemainingData) +{ + const char * text; + size_t text_length; + + text = encodedData->bytes(); + text_length = encodedData->length(); + + * pRemainingData = NULL; + + switch (encoding) { + case Encoding7Bit: + case Encoding8Bit: + case EncodingBinary: + case EncodingOther: + default: + { + return encodedData; + } + case EncodingBase64: + case EncodingQuotedPrintable: + { + char * decoded; + size_t decoded_length; + size_t cur_token; + int mime_encoding; + + switch (encoding) { + default: //disable warning + case EncodingBase64: + mime_encoding = MAILMIME_MECHANISM_BASE64; + break; + case EncodingQuotedPrintable: + mime_encoding = MAILMIME_MECHANISM_QUOTED_PRINTABLE; + break; + } + + cur_token = 0; + if (partialContent) { + mailmime_part_parse_partial(text, text_length, &cur_token, + mime_encoding, &decoded, &decoded_length); + } + else { + mailmime_part_parse(text, text_length, &cur_token, + mime_encoding, &decoded, &decoded_length); + } + + if (cur_token < text_length) { + * pRemainingData = Data::dataWithBytes(text + cur_token, (unsigned int)(text_length - cur_token)); + } + + Data * data = Data::data(); + data->takeBytesOwnership(decoded, (unsigned int) decoded_length, decodedPartDeallocator); + return data; + } + case EncodingUUEncode: + { + Data * data; + const char * current_p; + + data = Data::dataWithCapacity((unsigned int) text_length); + + current_p = text; + while (1) { + /* In uuencoded files each data line usually have 45 bytes of decoded data. + Maximum possible length is limited by (0x7f-0x20) bytes. + So 256-bytes buffer is enough. */ + char decoded_buf[256]; + size_t decoded_length; + size_t length; + const char * p; + const char * p1; + const char * p2; + const char * end_line; + + p1 = strchr(current_p, '\n'); + p2 = strchr(current_p, '\r'); + if (p1 == NULL) { + p = p2; + } + else if (p2 == NULL) { + p = p1; + } + else { + if (p1 - current_p < p2 - current_p) { + p = p1; + } + else { + p = p2; + } + } + end_line = p; + if (partialContent && (p1 == NULL || p2 == NULL) && + ((end_line == NULL) || (end_line - text) == (text_length - 1))) { + // possibly partial content detected + * pRemainingData = Data::dataWithBytes(current_p, (unsigned int)(text_length - (current_p - text))); + break; + } + if (p != NULL) { + while ((size_t) (p - text) < text_length) { + if ((* p != '\r') && (* p != '\n')) { + break; + } + p ++; + } + } + if (p == NULL) { + length = text_length - (current_p - text); + } + else { + length = end_line - current_p; + } + if (length == 0) { + break; + } + decoded_length = uudecode(current_p, length, decoded_buf, sizeof(decoded_buf)); + if (decoded_length != 0 && decoded_length < length) { + data->appendBytes(decoded_buf, (unsigned int) decoded_length); + } + + if (p == NULL) + break; + + current_p = p; + while ((size_t) (current_p - text) < text_length) { + if ((* current_p != '\r') && (* current_p != '\n')) { + break; + } + current_p ++; + } + } + + return data; + } + } +} + +} diff --git a/src/core/basetypes/MCDataDecoderUtils.h b/src/core/basetypes/MCDataDecoderUtils.h new file mode 100644 index 00000000..1481a2b4 --- /dev/null +++ b/src/core/basetypes/MCDataDecoderUtils.h @@ -0,0 +1,25 @@ +// +// MCDataDecoderUtils.h +// mailcore2 +// +// Copyright © 2016 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCDATADECODERUTILS_H + +#define MAILCORE_MCDATADECODERUTILS_H + +#include <MailCore/MCData.h> +#include <MailCore/MCMessageConstants.h> + +#ifdef __cplusplus + +namespace mailcore { + + Data * MCDecodeData(Data * encodedData, Encoding encoding, bool partialContent, Data ** pRemainingData); + +} + +#endif + +#endif diff --git a/src/core/basetypes/MCDataStreamDecoder.cpp b/src/core/basetypes/MCDataStreamDecoder.cpp new file mode 100644 index 00000000..120cfb65 --- /dev/null +++ b/src/core/basetypes/MCDataStreamDecoder.cpp @@ -0,0 +1,105 @@ +#include "MCDataStreamDecoder.h" + +#include "MCString.h" +#include "MCUtils.h" +#include "MCDataDecoderUtils.h" + +using namespace mailcore; + +DataStreamDecoder::DataStreamDecoder() +{ + mFilename = NULL; + mEncoding = Encoding7Bit; + mRemainingData = NULL; + mFile = NULL; +} + +DataStreamDecoder::~DataStreamDecoder() +{ + MC_SAFE_RELEASE(mRemainingData); + MC_SAFE_RELEASE(mFilename); + if (mFile != NULL) { + fclose(mFile); + mFile = NULL; + } +} + +void DataStreamDecoder::setEncoding(Encoding encoding) +{ + mEncoding = encoding; +} + +void DataStreamDecoder::setFilename(String * filename) +{ + MC_SAFE_REPLACE_COPY(String, mFilename, filename); +} + +ErrorCode DataStreamDecoder::appendData(Data * data) +{ + Data * dataForDecode; + if (mRemainingData && mRemainingData->length()) { + // the data remains from previous append + dataForDecode = (Data *) MC_SAFE_COPY(mRemainingData); + dataForDecode->appendData(data); + } else { + dataForDecode = (Data *) MC_SAFE_RETAIN(data); + } + + Data * remainingData = NULL; + Data * decodedData = MCDecodeData(dataForDecode, mEncoding, true, &remainingData); + + ErrorCode errorCode = appendDecodedData(decodedData); + + if (errorCode == ErrorNone) { + MC_SAFE_REPLACE_RETAIN(Data, mRemainingData, remainingData); + } + + MC_SAFE_RELEASE(dataForDecode); + return errorCode; +} + +ErrorCode DataStreamDecoder::flushData() +{ + if (mRemainingData == NULL || mRemainingData->length() == 0) { + return ErrorNone; + } + + Data * unused = NULL; + Data * decodedData = MCDecodeData(mRemainingData, mEncoding, false, &unused); + + ErrorCode errorCode = appendDecodedData(decodedData); + + if (errorCode == ErrorNone) { + if (mFile != NULL) { + if (fclose(mFile) != 0) { + return ErrorFile; + } + } + + MC_SAFE_RELEASE(mRemainingData); + } + + return errorCode; +} + +ErrorCode DataStreamDecoder::appendDecodedData(Data * decodedData) +{ + if (mFilename == NULL) { + return ErrorFile; + } + + if (mFile == NULL) { + mFile = fopen(mFilename->fileSystemRepresentation(), "wb"); + + if (mFile == NULL) { + return ErrorFile; + } + } + + size_t result = fwrite(decodedData->bytes(), decodedData->length(), 1, mFile); + if (result == 0) { + return ErrorFile; + } + + return ErrorNone; +} diff --git a/src/core/basetypes/MCDataStreamDecoder.h b/src/core/basetypes/MCDataStreamDecoder.h new file mode 100644 index 00000000..9d04f361 --- /dev/null +++ b/src/core/basetypes/MCDataStreamDecoder.h @@ -0,0 +1,51 @@ +// +// DataStreamDecoder.hpp +// mailcore2 +// +// Copyright © 2016 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCDATASTREAMDECODER_H + +#define MAILCORE_MCDATASTREAMDECODER_H + +#include <stdlib.h> + +#include <MailCore/MCObject.h> +#include <MailCore/MCData.h> +#include <MailCore/MCMessageConstants.h> + +#ifdef __cplusplus + +namespace mailcore { + + class DataStreamDecoder : public Object { + public: + DataStreamDecoder(); + virtual ~DataStreamDecoder(); + + virtual void setEncoding(Encoding encoding); + // output filename + virtual void setFilename(String * filename); + + // when data are received, decode them and add them to the file. + virtual ErrorCode appendData(Data * data); + + // end of data received. + virtual ErrorCode flushData(); + + private: // impl + virtual ErrorCode appendDecodedData(Data * decodedData); + + private: + String * mFilename; + Encoding mEncoding; + Data * mRemainingData; + FILE * mFile; + }; + +} + +#endif + +#endif diff --git a/src/core/imap/MCIMAPSession.cpp b/src/core/imap/MCIMAPSession.cpp index 61be95c3..1357f47f 100644 --- a/src/core/imap/MCIMAPSession.cpp +++ b/src/core/imap/MCIMAPSession.cpp @@ -27,9 +27,63 @@ #include "MCCertificateUtils.h" #include "MCIMAPIdentity.h" #include "MCLibetpan.h" +#include "MCDataStreamDecoder.h" using namespace mailcore; +class LoadByChunkProgress : public Object, public IMAPProgressCallback { +public: + LoadByChunkProgress(); + virtual ~LoadByChunkProgress(); + + virtual void setOffset(uint32_t offset); + virtual void setEstimatedSize(uint32_t estimatedSize); + virtual void setProgressCallback(IMAPProgressCallback * progressCallback); + + virtual void bodyProgress(IMAPSession * session, unsigned int current, unsigned int maximum); + +private: + uint32_t mOffset; + uint32_t mEstimatedSize; + IMAPProgressCallback * mProgressCallback; // non retained +}; + +LoadByChunkProgress::LoadByChunkProgress() +{ + mOffset = 0; + mEstimatedSize = 0; + mProgressCallback = NULL; +} + +LoadByChunkProgress::~LoadByChunkProgress() +{ +} + +void LoadByChunkProgress::setOffset(uint32_t offset) +{ + mOffset = offset; +} + +void LoadByChunkProgress::setEstimatedSize(uint32_t estimatedSize) +{ + mEstimatedSize = estimatedSize; +} + +void LoadByChunkProgress::setProgressCallback(IMAPProgressCallback * progressCallback) +{ + mProgressCallback = progressCallback; +} + +void LoadByChunkProgress::bodyProgress(IMAPSession * session, unsigned int current, unsigned int maximum) +{ + // In case of loading attachment by chunks we need report overall progress + if (mEstimatedSize > 0 && mEstimatedSize > maximum) { + maximum = mEstimatedSize; + current += mOffset; + } + mProgressCallback->bodyProgress(session, current, maximum); +} + enum { STATE_DISCONNECTED, STATE_CONNECTED, @@ -2813,8 +2867,9 @@ static void nstringDeallocator(char * bytes, unsigned int length) { mailimap_nstring_free(bytes); }; -Data * IMAPSession::fetchMessageAttachment(String * folder, bool identifier_is_uid, +Data * IMAPSession::fetchNonDecodedMessageAttachment(String * folder, bool identifier_is_uid, uint32_t identifier, String * partID, + bool wholePart, uint32_t offset, uint32_t length, Encoding encoding, IMAPProgressCallback * progressCallback, ErrorCode * pError) { struct mailimap_fetch_type * fetch_type; @@ -2827,21 +2882,21 @@ Data * IMAPSession::fetchMessageAttachment(String * folder, bool identifier_is_u char * text = NULL; size_t text_length = 0; Data * data; - + selectIfNeeded(folder, pError); if (* pError != ErrorNone) return NULL; - + mProgressItemsCount = 0; mProgressCallback = progressCallback; bodyProgress(0, 0); - + partIDArray = partID->componentsSeparatedByString(MCSTR(".")); sec_list = clist_new(); for(unsigned int i = 0 ; i < partIDArray->count() ; i ++) { uint32_t * value; String * element; - + element = (String *) partIDArray->objectAtIndex(i); value = (uint32_t *) malloc(sizeof(* value)); * value = element->intValue(); @@ -2849,7 +2904,12 @@ Data * IMAPSession::fetchMessageAttachment(String * folder, bool identifier_is_u } section_part = mailimap_section_part_new(sec_list); section = mailimap_section_new_part(section_part); - fetch_att = mailimap_fetch_att_new_body_peek_section(section); + if (wholePart) { + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + } + else { + fetch_att = mailimap_fetch_att_new_body_peek_section_partial(section, offset, length); + } fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); #ifdef LIBETPAN_HAS_MAILIMAP_RAMBLER_WORKAROUND @@ -2885,13 +2945,23 @@ Data * IMAPSession::fetchMessageAttachment(String * folder, bool identifier_is_u data = Data::data(); data->takeBytesOwnership(text, (unsigned int) text_length, nstringDeallocator); - data = data->decodedDataUsingEncoding(encoding); * pError = ErrorNone; return data; } +Data * IMAPSession::fetchMessageAttachment(String * folder, bool identifier_is_uid, + uint32_t identifier, String * partID, + Encoding encoding, IMAPProgressCallback * progressCallback, ErrorCode * pError) +{ + Data * data = fetchNonDecodedMessageAttachment(folder, identifier_is_uid, identifier, partID, true, 0, 0, encoding, progressCallback, pError); + if (data) { + data = data->decodedDataUsingEncoding(encoding); + } + return data; +} + Data * IMAPSession::fetchMessageAttachmentByUID(String * folder, uint32_t uid, String * partID, Encoding encoding, IMAPProgressCallback * progressCallback, ErrorCode * pError) { @@ -2904,6 +2974,84 @@ 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, + uint32_t estimatedSize, Encoding encoding, + String * outputFile, uint32_t chunkSize, + IMAPProgressCallback * progressCallback, ErrorCode * pError) +{ + DataStreamDecoder * decoder = new DataStreamDecoder(); + decoder->setEncoding(encoding); + decoder->setFilename(outputFile); + + int nRetries = 0; + int const maxRetries = 3; + ErrorCode error = ErrorNone; + uint32_t offset = 0; + while (1) { + AutoreleasePool * pool = new AutoreleasePool(); + + LoadByChunkProgress * chunkProgressCallback = new LoadByChunkProgress(); + chunkProgressCallback->setOffset(offset); + chunkProgressCallback->setEstimatedSize(estimatedSize); + chunkProgressCallback->setProgressCallback(progressCallback); + + Data * data = fetchNonDecodedMessageAttachment(folder, true, uid, partID, false, offset, chunkSize, encoding, chunkProgressCallback, &error); + + MC_SAFE_RELEASE(chunkProgressCallback); + + if (error != ErrorNone) { + pool->release(); + if ((error == ErrorConnection || error == ErrorParse) && nRetries < maxRetries) { + error = ErrorNone; + nRetries++; + continue; + } + break; + } else { + nRetries = 0; + } + + if (data == NULL) { + break; + } + + uint32_t encodedSize = data->length(); + if (encodedSize == 0) { + pool->release(); + break; + } + + error = decoder->appendData(data); + + pool->release(); + + if (error != ErrorNone) { + break; + } + + offset += encodedSize; + + // Try detect is this chunk last. + // Estimated size (extracted from BODYSTRUCTURE info) may be incorrect. + // Also, server may return chunk with size less than requested. + // So this detection is some tricky. + bool endOfPart = ((encodedSize == 0) || + (estimatedSize > 0 && (estimatedSize <= offset) && (encodedSize != chunkSize)) || + (estimatedSize == 0 && encodedSize < chunkSize)); + if (endOfPart) { + break; + } + } + + if (error == ErrorNone) { + 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 adbecd43..55f47de0 100644 --- a/src/core/imap/MCIMAPSession.h +++ b/src/core/imap/MCIMAPSession.h @@ -121,6 +121,12 @@ namespace mailcore { IMAPProgressCallback * progressCallback, ErrorCode * pError); 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, + uint32_t estimatedSize, Encoding encoding, + String * outputFile, uint32_t chunkSize, + IMAPProgressCallback * progressCallback, ErrorCode * pError); + virtual Data * fetchMessageAttachmentByNumber(String * folder, uint32_t number, String * partID, Encoding encoding, IMAPProgressCallback * progressCallback, ErrorCode * pError); virtual HashMap * fetchMessageNumberUIDMapping(String * folder, uint32_t fromUID, uint32_t toUID, @@ -305,9 +311,14 @@ namespace mailcore { Data * fetchMessageAttachment(String * folder, bool identifier_is_uid, uint32_t identifier, String * partID, Encoding encoding, IMAPProgressCallback * progressCallback, ErrorCode * pError); + // in case of wholePart is false, receives range [offset, length] + Data * fetchNonDecodedMessageAttachment(String * folder, bool identifier_is_uid, + uint32_t identifier, String * partID, + bool wholePart, uint32_t offset, uint32_t length, + Encoding encoding, IMAPProgressCallback * progressCallback, ErrorCode * pError); void storeLabels(String * folder, bool identifier_is_uid, IndexSet * identifiers, IMAPStoreFlagsRequestKind kind, Array * labels, ErrorCode * pError); }; - + } #endif diff --git a/src/core/rfc822/MCAttachment.cpp b/src/core/rfc822/MCAttachment.cpp index e6ebc9c9..0881c9a8 100644 --- a/src/core/rfc822/MCAttachment.cpp +++ b/src/core/rfc822/MCAttachment.cpp @@ -548,12 +548,12 @@ Attachment * Attachment::attachmentWithSingleMIME(struct mailmime * mime) mailmime_single_fields_init(&single_fields, mime->mm_mime_fields, mime->mm_content_type); encoding = encodingForMIMEEncoding(single_fields.fld_encoding, data->dt_encoding); - + Data * mimeData; mimeData = Data::dataWithBytes(bytes, (unsigned int) length); mimeData = mimeData->decodedDataUsingEncoding(encoding); result->setData(mimeData); - + str = get_content_type_str(mime->mm_content_type); result->setMimeType(String::stringWithUTF8Characters(str)); free(str); |