aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Yuk Lai Suen <yuklai@hothouselabs.com>2014-07-17 15:44:01 -0700
committerGravatar Yuk Lai Suen <yuklai@hothouselabs.com>2014-07-17 15:44:01 -0700
commit9b3928c4399d99f4c138688e8f26eda60dc33fb2 (patch)
treec30897fc16f2da6784b65baf5eafb4171183dc2c /src
parentb3214859c6c75d3930a0f8582fd1a1c85a96be76 (diff)
parent64f52dae67ba57d03e45ba35c626ddd6ea907367 (diff)
Merge from dev
Diffstat (limited to 'src')
-rw-r--r--src/async/imap/MCIMAPAppendMessageOperation.cc13
-rw-r--r--src/async/imap/MCIMAPAppendMessageOperation.h4
-rw-r--r--src/async/imap/MCIMAPQuotaOperation.cc6
-rw-r--r--src/core/abstract/MCMessageHeader.cc201
-rw-r--r--src/core/abstract/MCMessageHeader.h1
-rw-r--r--src/core/basetypes/MCArray.cc14
-rw-r--r--src/core/basetypes/MCData.cc3
-rw-r--r--src/core/basetypes/MCHTMLCleaner.cc2
-rw-r--r--src/core/basetypes/MCIndexSet.cc2
-rw-r--r--src/core/basetypes/MCLibetpan.cc202
-rw-r--r--src/core/basetypes/MCLibetpan.h12
-rwxr-xr-xsrc/core/imap/MCIMAPSession.cc20
-rwxr-xr-xsrc/core/imap/MCIMAPSession.h2
-rw-r--r--src/core/rfc822/MCMessageBuilder.cc6
-rw-r--r--src/core/rfc822/MCMessageParser.cc19
-rw-r--r--src/objc/imap/MCOIMAPAppendMessageOperation.h2
-rw-r--r--src/objc/imap/MCOIMAPAppendMessageOperation.mm2
-rwxr-xr-xsrc/objc/imap/MCOIMAPSession.h4
-rw-r--r--src/objc/pop/MCOPOPSession.h4
-rw-r--r--src/objc/smtp/MCOSMTPSession.h4
-rw-r--r--src/objc/utils/MCOOperation.h4
-rw-r--r--src/objc/utils/NSArray+MCO.mm3
22 files changed, 336 insertions, 194 deletions
diff --git a/src/async/imap/MCIMAPAppendMessageOperation.cc b/src/async/imap/MCIMAPAppendMessageOperation.cc
index 06a42b2d..23eaaea0 100644
--- a/src/async/imap/MCIMAPAppendMessageOperation.cc
+++ b/src/async/imap/MCIMAPAppendMessageOperation.cc
@@ -18,6 +18,7 @@ IMAPAppendMessageOperation::IMAPAppendMessageOperation()
mMessageData = NULL;
mFlags = MessageFlagNone;
mCustomFlags = NULL;
+ mDate = (time_t) -1;
mCreatedUID = 0;
}
@@ -57,6 +58,16 @@ Array * IMAPAppendMessageOperation::customFlags()
return customFlags();
}
+void IMAPAppendMessageOperation::setDate(time_t date)
+{
+ mDate = date;
+}
+
+time_t IMAPAppendMessageOperation::date()
+{
+ return mDate;
+}
+
uint32_t IMAPAppendMessageOperation::createdUID()
{
return mCreatedUID;
@@ -65,7 +76,7 @@ uint32_t IMAPAppendMessageOperation::createdUID()
void IMAPAppendMessageOperation::main()
{
ErrorCode error;
- session()->session()->appendMessageWithCustomFlags(folder(), mMessageData, mFlags, mCustomFlags, this, &mCreatedUID, &error);
+ session()->session()->appendMessageWithCustomFlagsAndDate(folder(), mMessageData, mFlags, mCustomFlags, mDate, this, &mCreatedUID, &error);
setError(error);
}
diff --git a/src/async/imap/MCIMAPAppendMessageOperation.h b/src/async/imap/MCIMAPAppendMessageOperation.h
index bca461d7..463d65d4 100644
--- a/src/async/imap/MCIMAPAppendMessageOperation.h
+++ b/src/async/imap/MCIMAPAppendMessageOperation.h
@@ -31,6 +31,9 @@ namespace mailcore {
virtual void setCustomFlags(Array * customFlags);
virtual Array * customFlags();
+ virtual void setDate(time_t date);
+ virtual time_t date();
+
virtual uint32_t createdUID();
public: // subclass behavior
@@ -40,6 +43,7 @@ namespace mailcore {
Data * mMessageData;
MessageFlag mFlags;
Array * mCustomFlags;
+ time_t mDate;
uint32_t mCreatedUID;
};
diff --git a/src/async/imap/MCIMAPQuotaOperation.cc b/src/async/imap/MCIMAPQuotaOperation.cc
index 6744ac4b..2268a384 100644
--- a/src/async/imap/MCIMAPQuotaOperation.cc
+++ b/src/async/imap/MCIMAPQuotaOperation.cc
@@ -36,6 +36,12 @@ uint32_t IMAPQuotaOperation::usage()
void IMAPQuotaOperation::main()
{
ErrorCode error;
+ session()->session()->loginIfNeeded(&error);
+ if (error != ErrorNone) {
+ setError(error);
+ return;
+ }
+
session()->session()->getQuota(&mUsage, &mLimit, &error);
setError(error);
}
diff --git a/src/core/abstract/MCMessageHeader.cc b/src/core/abstract/MCMessageHeader.cc
index 789da25e..6d2d8066 100644
--- a/src/core/abstract/MCMessageHeader.cc
+++ b/src/core/abstract/MCMessageHeader.cc
@@ -2,6 +2,7 @@
#include "MCAddress.h"
#include "MCIterator.h"
+#include "MCLibetpan.h"
#include <string.h>
#include <unistd.h>
@@ -9,12 +10,6 @@
using namespace mailcore;
-static time_t timestamp_from_date(struct mailimf_date_time * date_time);
-static struct mailimf_date_time * get_date_from_timestamp(time_t timeval);
-static time_t timestamp_from_imap_date(struct mailimap_date_time * date_time);
-static time_t mkgmtime(struct tm * tmp);
-static int tmcomp(struct tm * atmp, struct tm * btmp);
-
static struct mailimf_address_list * lep_address_list_from_array(Array * addresses);
static struct mailimf_mailbox_list * lep_mailbox_list_from_array(Array * addresses);
static Array * lep_address_list_from_lep_addr(struct mailimf_address_list * addr_list);
@@ -63,6 +58,7 @@ void MessageHeader::init(bool generateDate, bool generateMessageID)
mDate = (time_t) -1;
mReceivedDate = (time_t) -1;
mExtraHeaders = NULL;
+ mlcExtraHeaders = NULL;
if (generateDate) {
time_t date;
@@ -114,6 +110,7 @@ MessageHeader::~MessageHeader()
MC_SAFE_RELEASE(mReplyTo);
MC_SAFE_RELEASE(mSubject);
MC_SAFE_RELEASE(mExtraHeaders);
+ MC_SAFE_RELEASE(mlcExtraHeaders);
}
String * MessageHeader::description()
@@ -298,6 +295,13 @@ String * MessageHeader::userAgent()
void MessageHeader::setExtraHeaders(HashMap * headers)
{
MC_SAFE_REPLACE_COPY(HashMap, mExtraHeaders, headers);
+ MC_SAFE_RELEASE(mlcExtraHeaders);
+ if (mExtraHeaders != NULL) {
+ mlcExtraHeaders = new HashMap();
+ mc_foreachhashmapKeyAndValue(String, key, String, value, mExtraHeaders) {
+ mlcExtraHeaders->setObjectForKey(key->lowercaseString(), value);
+ }
+ }
}
Array * MessageHeader::allExtraHeadersNames()
@@ -309,13 +313,18 @@ Array * MessageHeader::allExtraHeadersNames()
void MessageHeader::setExtraHeader(String * name, String * object)
{
- if (mExtraHeaders == NULL)
+ if (mExtraHeaders == NULL) {
mExtraHeaders = new HashMap();
+ }
+ if (mlcExtraHeaders == NULL) {
+ mlcExtraHeaders = new HashMap();
+ }
if (object == NULL) {
removeExtraHeader(name);
return;
}
mExtraHeaders->setObjectForKey(name, object);
+ mlcExtraHeaders->setObjectForKey(name->lowercaseString(), object);
}
void MessageHeader::removeExtraHeader(String * name)
@@ -323,13 +332,14 @@ void MessageHeader::removeExtraHeader(String * name)
if (mExtraHeaders == NULL)
return;
mExtraHeaders->removeObjectForKey(name);
+ mlcExtraHeaders->removeObjectForKey(name);
}
String * MessageHeader::extraHeaderValueForName(String * name)
{
- if (mExtraHeaders == NULL)
+ if (mlcExtraHeaders == NULL)
return NULL;
- return (String *) mExtraHeaders->objectForKey(name);
+ return (String *) mlcExtraHeaders->objectForKey(name->lowercaseString());
}
String * MessageHeader::extractedSubject()
@@ -373,7 +383,7 @@ void MessageHeader::importIMFFields(struct mailimf_fields * fields)
if (single_fields.fld_orig_date != NULL) {
time_t timestamp;
- timestamp = timestamp_from_date(single_fields.fld_orig_date->dt_date_time);
+ timestamp = timestampFromDate(single_fields.fld_orig_date->dt_date_time);
setDate(timestamp);
setReceivedDate(timestamp);
//MCLog("%lu %lu", (unsigned long) timestamp, date());
@@ -508,169 +518,6 @@ void MessageHeader::importIMFFields(struct mailimf_fields * fields)
}
}
-static time_t timestamp_from_date(struct mailimf_date_time * date_time)
-{
- struct tm tmval;
- time_t timeval;
- int zone_min;
- int zone_hour;
-
- tmval.tm_sec = date_time->dt_sec;
- tmval.tm_min = date_time->dt_min;
- tmval.tm_hour = date_time->dt_hour;
- tmval.tm_mday = date_time->dt_day;
- tmval.tm_mon = date_time->dt_month - 1;
- if (date_time->dt_year < 1000) {
- // workaround when century is not given in year
- tmval.tm_year = date_time->dt_year + 2000 - 1900;
- }
- else {
- tmval.tm_year = date_time->dt_year - 1900;
- }
-
- timeval = mkgmtime(&tmval);
-
- if (date_time->dt_zone >= 0) {
- zone_hour = date_time->dt_zone / 100;
- zone_min = date_time->dt_zone % 100;
- }
- else {
- zone_hour = -((- date_time->dt_zone) / 100);
- zone_min = -((- date_time->dt_zone) % 100);
- }
- timeval -= zone_hour * 3600 + zone_min * 60;
-
- return timeval;
-}
-
-static struct mailimf_date_time * get_date_from_timestamp(time_t timeval)
-{
- struct tm gmt;
- struct tm lt;
- int off;
- struct mailimf_date_time * date_time;
- int sign;
- int hour;
- int min;
-
- gmtime_r(&timeval, &gmt);
- localtime_r(&timeval, &lt);
-
- off = (int) ((mkgmtime(&lt) - mkgmtime(&gmt)) / 60);
- if (off < 0) {
- sign = -1;
- }
- else {
- sign = 1;
- }
- off = off * sign;
- min = off % 60;
- hour = off / 60;
- off = hour * 100 + min;
- off = off * sign;
-
- date_time = mailimf_date_time_new(lt.tm_mday, lt.tm_mon + 1,
- lt.tm_year + 1900,
- lt.tm_hour, lt.tm_min, lt.tm_sec,
- off);
-
- return date_time;
-}
-
-static time_t timestamp_from_imap_date(struct mailimap_date_time * date_time)
-{
- struct tm tmval;
- time_t timeval;
- int zone_min;
- int zone_hour;
-
- tmval.tm_sec = date_time->dt_sec;
- tmval.tm_min = date_time->dt_min;
- tmval.tm_hour = date_time->dt_hour;
- tmval.tm_mday = date_time->dt_day;
- tmval.tm_mon = date_time->dt_month - 1;
- if (date_time->dt_year < 1000) {
- // workaround when century is not given in year
- tmval.tm_year = date_time->dt_year + 2000 - 1900;
- }
- else {
- tmval.tm_year = date_time->dt_year - 1900;
- }
-
- timeval = mkgmtime(&tmval);
-
- if (date_time->dt_zone >= 0) {
- zone_hour = date_time->dt_zone / 100;
- zone_min = date_time->dt_zone % 100;
- }
- else {
- zone_hour = -((- date_time->dt_zone) / 100);
- zone_min = -((- date_time->dt_zone) % 100);
- }
- timeval -= zone_hour * 3600 + zone_min * 60;
-
- return timeval;
-}
-
-#define INVALID_TIMESTAMP (-1)
-
-static int tmcomp(struct tm * atmp, struct tm * btmp)
-{
- int result;
-
- if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
- (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
- (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
- (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
- (result = (atmp->tm_min - btmp->tm_min)) == 0)
- result = atmp->tm_sec - btmp->tm_sec;
- return result;
-}
-
-static time_t mkgmtime(struct tm * tmp)
-{
- int dir;
- int bits;
- int saved_seconds;
- time_t t;
- struct tm yourtm, mytm;
-
- yourtm = *tmp;
- saved_seconds = yourtm.tm_sec;
- yourtm.tm_sec = 0;
- /*
- ** Calculate the number of magnitude bits in a time_t
- ** (this works regardless of whether time_t is
- ** signed or unsigned, though lint complains if unsigned).
- */
- for (bits = 0, t = 1; t > 0; ++bits, t <<= 1)
- ;
- /*
- ** If time_t is signed, then 0 is the median value,
- ** if time_t is unsigned, then 1 << bits is median.
- */
- if(bits > 40) bits = 40;
- t = (t < 0) ? 0 : ((time_t) 1 << bits);
- for ( ; ; ) {
- gmtime_r(&t, &mytm);
- dir = tmcomp(&mytm, &yourtm);
- if (dir != 0) {
- if (bits-- < 0) {
- return INVALID_TIMESTAMP;
- }
- if (bits < 0)
- --t;
- else if (dir > 0)
- t -= (time_t) 1 << bits;
- else t += (time_t) 1 << bits;
- continue;
- }
- break;
- }
- t += saved_seconds;
- return t;
-}
-
#pragma mark RFC 2822 mailbox conversion
static Array * lep_address_list_from_lep_mailbox(struct mailimf_mailbox_list * mb_list)
@@ -836,7 +683,7 @@ struct mailimf_fields * MessageHeader::createIMFFieldsAndFilterBcc(bool filterBc
imfDate = NULL;
if (date() != (time_t) -1) {
//MCLog("%lu", date());
- imfDate = get_date_from_timestamp(date());
+ imfDate = dateFromTimestamp(date());
}
imfFrom = NULL;
if (from() != NULL) {
@@ -937,7 +784,7 @@ void MessageHeader::importIMAPEnvelope(struct mailimap_envelope * env)
time_t timestamp;
// date
- timestamp = timestamp_from_date(date_time);
+ timestamp = timestampFromDate(date_time);
setDate(timestamp);
setReceivedDate(timestamp);
mailimf_date_time_free(date_time);
@@ -949,7 +796,7 @@ void MessageHeader::importIMAPEnvelope(struct mailimap_envelope * env)
if (r == MAILIMAP_NO_ERROR) {
time_t timestamp;
- timestamp = timestamp_from_imap_date(imap_date);
+ timestamp = timestampFromIMAPDate(imap_date);
setDate(timestamp);
setReceivedDate(timestamp);
mailimap_date_time_free(imap_date);
@@ -1117,7 +964,7 @@ void MessageHeader::importIMAPReferences(Data * data)
void MessageHeader::importIMAPInternalDate(struct mailimap_date_time * date)
{
- setReceivedDate(timestamp_from_imap_date(date));
+ setReceivedDate(timestampFromIMAPDate(date));
}
Array * MessageHeader::recipientWithReplyAll(bool replyAll, bool includeTo, bool includeCc, Array * senderEmails)
diff --git a/src/core/abstract/MCMessageHeader.h b/src/core/abstract/MCMessageHeader.h
index c6f1fbef..4fef0b7f 100644
--- a/src/core/abstract/MCMessageHeader.h
+++ b/src/core/abstract/MCMessageHeader.h
@@ -96,6 +96,7 @@ namespace mailcore {
time_t mDate;
time_t mReceivedDate;
HashMap * mExtraHeaders;
+ HashMap * mlcExtraHeaders;
void init(bool generateDate, bool generateMessageID);
void setExtraHeaders(HashMap *headers);
Array * recipientWithReplyAll(bool replyAll, bool includeTo, bool includeCc, Array * senderEmails);
diff --git a/src/core/basetypes/MCArray.cc b/src/core/basetypes/MCArray.cc
index 038ec022..43ee6bd4 100644
--- a/src/core/basetypes/MCArray.cc
+++ b/src/core/basetypes/MCArray.cc
@@ -212,20 +212,8 @@ static int sortCompare(Object ** pa, Object ** pb, struct sortData * data)
Array * Array::sortedArray(int (* compare)(void * a, void * b, void * context), void * context)
{
- struct sortData data;
Array * result = (Array *) this->copy()->autorelease();
- data.compare = compare;
- data.context = context;
-#ifdef __MACH__
- qsort_r(carray_data(result->mArray), carray_count(result->mArray),
- sizeof(* carray_data(result->mArray)), &data,
- (int (*)(void *, const void *, const void *)) sortCompare);
-#else
- qsort_r(carray_data(result->mArray), carray_count(result->mArray),
- sizeof(* carray_data(result->mArray)),
- (int (*)(const void *, const void *, void *)) sortCompare,
- &data);
-#endif
+ result->sortArray(compare, context);
return result;
}
diff --git a/src/core/basetypes/MCData.cc b/src/core/basetypes/MCData.cc
index 0a03316c..60b8ff8f 100644
--- a/src/core/basetypes/MCData.cc
+++ b/src/core/basetypes/MCData.cc
@@ -283,6 +283,9 @@ String * Data::stringWithDetectedCharset(String * hintCharset, bool isHTML)
if (result == NULL) {
result = data->stringWithCharset("iso-2022-jp");
}
+ if (result == NULL) {
+ result = MCSTR("");
+ }
return result;
}
diff --git a/src/core/basetypes/MCHTMLCleaner.cc b/src/core/basetypes/MCHTMLCleaner.cc
index 079163bf..81145c9e 100644
--- a/src/core/basetypes/MCHTMLCleaner.cc
+++ b/src/core/basetypes/MCHTMLCleaner.cc
@@ -43,6 +43,8 @@ String * HTMLCleaner::cleanHTML(String * input)
tidyOptSetBool(tdoc, TidyDropEmptyElems, no);
#endif
tidyOptSetBool(tdoc, TidyXhtmlOut, yes);
+ tidyOptSetInt(tdoc, TidyDoctypeMode, TidyDoctypeUser);
+
tidyOptSetBool(tdoc, TidyMark, no);
tidySetCharEncoding(tdoc, "utf8");
tidyOptSetBool(tdoc, TidyForceOutput, yes);
diff --git a/src/core/basetypes/MCIndexSet.cc b/src/core/basetypes/MCIndexSet.cc
index 6c883082..768cd601 100644
--- a/src/core/basetypes/MCIndexSet.cc
+++ b/src/core/basetypes/MCIndexSet.cc
@@ -372,7 +372,7 @@ void IndexSet::intersectsRange(Range range)
}
else {
removeRange(RangeMake(0, range.location - 1));
- removeRange(RangeMake(right, UINT64_MAX));
+ removeRange(RangeMake(right + 1, UINT64_MAX));
}
}
diff --git a/src/core/basetypes/MCLibetpan.cc b/src/core/basetypes/MCLibetpan.cc
index fcc1b772..1779d605 100644
--- a/src/core/basetypes/MCLibetpan.cc
+++ b/src/core/basetypes/MCLibetpan.cc
@@ -10,9 +10,211 @@
#include <libetpan/libetpan.h>
+using namespace mailcore;
+
+static time_t mkgmtime(struct tm * tmp);
+static int tmcomp(struct tm * atmp, struct tm * btmp);
+
__attribute__((constructor))
static void initialize()
{
// It will enable CFStream on platforms that supports it.
mailstream_cfstream_enabled = 1;
}
+
+time_t mailcore::timestampFromDate(struct mailimf_date_time * date_time)
+{
+ struct tm tmval;
+ time_t timeval;
+ int zone_min;
+ int zone_hour;
+
+ tmval.tm_sec = date_time->dt_sec;
+ tmval.tm_min = date_time->dt_min;
+ tmval.tm_hour = date_time->dt_hour;
+ tmval.tm_mday = date_time->dt_day;
+ tmval.tm_mon = date_time->dt_month - 1;
+ if (date_time->dt_year < 1000) {
+ // workaround when century is not given in year
+ tmval.tm_year = date_time->dt_year + 2000 - 1900;
+ }
+ else {
+ tmval.tm_year = date_time->dt_year - 1900;
+ }
+
+ timeval = mkgmtime(&tmval);
+
+ if (date_time->dt_zone >= 0) {
+ zone_hour = date_time->dt_zone / 100;
+ zone_min = date_time->dt_zone % 100;
+ }
+ else {
+ zone_hour = -((- date_time->dt_zone) / 100);
+ zone_min = -((- date_time->dt_zone) % 100);
+ }
+ timeval -= zone_hour * 3600 + zone_min * 60;
+
+ return timeval;
+}
+
+struct mailimf_date_time * mailcore::dateFromTimestamp(time_t timeval)
+{
+ struct tm gmt;
+ struct tm lt;
+ int off;
+ struct mailimf_date_time * date_time;
+ int sign;
+ int hour;
+ int min;
+
+ gmtime_r(&timeval, &gmt);
+ localtime_r(&timeval, &lt);
+
+ off = (int) ((mkgmtime(&lt) - mkgmtime(&gmt)) / 60);
+ if (off < 0) {
+ sign = -1;
+ }
+ else {
+ sign = 1;
+ }
+ off = off * sign;
+ min = off % 60;
+ hour = off / 60;
+ off = hour * 100 + min;
+ off = off * sign;
+
+ date_time = mailimf_date_time_new(lt.tm_mday, lt.tm_mon + 1,
+ lt.tm_year + 1900,
+ lt.tm_hour, lt.tm_min, lt.tm_sec,
+ off);
+
+ return date_time;
+}
+
+struct mailimap_date_time * mailcore::imapDateFromTimestamp(time_t timeval)
+{
+ struct tm gmt;
+ struct tm lt;
+ int off;
+ struct mailimap_date_time * date_time;
+ int sign;
+ int hour;
+ int min;
+
+ gmtime_r(&timeval, &gmt);
+ localtime_r(&timeval, &lt);
+
+ off = (int) ((mkgmtime(&lt) - mkgmtime(&gmt)) / 60);
+ if (off < 0) {
+ sign = -1;
+ }
+ else {
+ sign = 1;
+ }
+ off = off * sign;
+ min = off % 60;
+ hour = off / 60;
+ off = hour * 100 + min;
+ off = off * sign;
+
+ date_time = mailimap_date_time_new(lt.tm_mday, lt.tm_mon + 1,
+ lt.tm_year + 1900,
+ lt.tm_hour, lt.tm_min, lt.tm_sec,
+ off);
+
+ return date_time;
+}
+
+time_t mailcore::timestampFromIMAPDate(struct mailimap_date_time * date_time)
+{
+ struct tm tmval;
+ time_t timeval;
+ int zone_min;
+ int zone_hour;
+
+ tmval.tm_sec = date_time->dt_sec;
+ tmval.tm_min = date_time->dt_min;
+ tmval.tm_hour = date_time->dt_hour;
+ tmval.tm_mday = date_time->dt_day;
+ tmval.tm_mon = date_time->dt_month - 1;
+ if (date_time->dt_year < 1000) {
+ // workaround when century is not given in year
+ tmval.tm_year = date_time->dt_year + 2000 - 1900;
+ }
+ else {
+ tmval.tm_year = date_time->dt_year - 1900;
+ }
+
+ timeval = mkgmtime(&tmval);
+
+ if (date_time->dt_zone >= 0) {
+ zone_hour = date_time->dt_zone / 100;
+ zone_min = date_time->dt_zone % 100;
+ }
+ else {
+ zone_hour = -((- date_time->dt_zone) / 100);
+ zone_min = -((- date_time->dt_zone) % 100);
+ }
+ timeval -= zone_hour * 3600 + zone_min * 60;
+
+ return timeval;
+}
+
+#define INVALID_TIMESTAMP (-1)
+
+static int tmcomp(struct tm * atmp, struct tm * btmp)
+{
+ int result;
+
+ if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
+ (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
+ (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
+ (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
+ (result = (atmp->tm_min - btmp->tm_min)) == 0)
+ result = atmp->tm_sec - btmp->tm_sec;
+ return result;
+}
+
+static time_t mkgmtime(struct tm * tmp)
+{
+ int dir;
+ int bits;
+ int saved_seconds;
+ time_t t;
+ struct tm yourtm, mytm;
+
+ yourtm = *tmp;
+ saved_seconds = yourtm.tm_sec;
+ yourtm.tm_sec = 0;
+ /*
+ ** Calculate the number of magnitude bits in a time_t
+ ** (this works regardless of whether time_t is
+ ** signed or unsigned, though lint complains if unsigned).
+ */
+ for (bits = 0, t = 1; t > 0; ++bits, t <<= 1)
+ ;
+ /*
+ ** If time_t is signed, then 0 is the median value,
+ ** if time_t is unsigned, then 1 << bits is median.
+ */
+ if(bits > 40) bits = 40;
+ t = (t < 0) ? 0 : ((time_t) 1 << bits);
+ for ( ; ; ) {
+ gmtime_r(&t, &mytm);
+ dir = tmcomp(&mytm, &yourtm);
+ if (dir != 0) {
+ if (bits-- < 0) {
+ return INVALID_TIMESTAMP;
+ }
+ if (bits < 0)
+ --t;
+ else if (dir > 0)
+ t -= (time_t) 1 << bits;
+ else t += (time_t) 1 << bits;
+ continue;
+ }
+ break;
+ }
+ t += saved_seconds;
+ return t;
+}
diff --git a/src/core/basetypes/MCLibetpan.h b/src/core/basetypes/MCLibetpan.h
index 9670a47b..41024137 100644
--- a/src/core/basetypes/MCLibetpan.h
+++ b/src/core/basetypes/MCLibetpan.h
@@ -10,6 +10,16 @@
#define MAILCORE_MCLIBETPAN_H
-// No API in this file.
+#include <time.h>
+#include <libetpan/libetpan.h>
+
+namespace mailcore {
+
+ time_t timestampFromDate(struct mailimf_date_time * date_time);
+ time_t timestampFromIMAPDate(struct mailimap_date_time * date_time);
+ struct mailimf_date_time * dateFromTimestamp(time_t timeval);
+ struct mailimap_date_time * imapDateFromTimestamp(time_t timeval);
+
+}
#endif
diff --git a/src/core/imap/MCIMAPSession.cc b/src/core/imap/MCIMAPSession.cc
index 09ee841d..5efc5e12 100755
--- a/src/core/imap/MCIMAPSession.cc
+++ b/src/core/imap/MCIMAPSession.cc
@@ -23,6 +23,7 @@
#include "MCHTMLBodyRendererTemplateCallback.h"
#include "MCCertificateUtils.h"
#include "MCIMAPIdentity.h"
+#include "MCLibetpan.h"
using namespace mailcore;
@@ -1589,6 +1590,12 @@ void IMAPSession::appendMessage(String * folder, Data * messageData, MessageFlag
void IMAPSession::appendMessageWithCustomFlags(String * folder, Data * messageData, MessageFlag flags, Array * customFlags,
IMAPProgressCallback * progressCallback, uint32_t * createdUID, ErrorCode * pError)
{
+ this->appendMessageWithCustomFlagsAndDate(folder, messageData, flags, NULL, (time_t) -1, progressCallback, createdUID, pError);
+}
+
+void IMAPSession::appendMessageWithCustomFlagsAndDate(String * folder, Data * messageData, MessageFlag flags, Array * customFlags, time_t date,
+ IMAPProgressCallback * progressCallback, uint32_t * createdUID, ErrorCode * pError)
+{
int r;
struct mailimap_flag_list * flag_list;
uint32_t uidvalidity;
@@ -1612,8 +1619,15 @@ void IMAPSession::appendMessageWithCustomFlags(String * folder, Data * messageDa
mailimap_flag_list_add(flag_list, f);
}
}
- r = mailimap_uidplus_append(mImap, MCUTF8(folder), flag_list, NULL, messageData->bytes(), messageData->length(),
+ struct mailimap_date_time * imap_date = NULL;
+ if (date != (time_t) -1) {
+ imap_date = imapDateFromTimestamp(date);
+ }
+ r = mailimap_uidplus_append(mImap, MCUTF8(folder), flag_list, imap_date, messageData->bytes(), messageData->length(),
&uidvalidity, &uidresult);
+ if (imap_date != NULL) {
+ mailimap_date_time_free(imap_date);
+ }
mailimap_flag_list_free(flag_list);
bodyProgress(messageData->length(), messageData->length());
@@ -3607,6 +3621,10 @@ void IMAPSession::capabilitySetWithSessionState(IndexSet * capabilities)
if (mailimap_has_compress_deflate(mImap)) {
capabilities->addIndex(IMAPCapabilityCompressDeflate);
}
+ if (mailimap_has_extension(mImap, (char *)"CHILDREN")) {
+ capabilities->addIndex(IMAPCapabilityChildren);
+ }
+
applyCapabilities(capabilities);
}
diff --git a/src/core/imap/MCIMAPSession.h b/src/core/imap/MCIMAPSession.h
index 9ebe48d6..e52dc74f 100755
--- a/src/core/imap/MCIMAPSession.h
+++ b/src/core/imap/MCIMAPSession.h
@@ -83,6 +83,8 @@ namespace mailcore {
IMAPProgressCallback * progressCallback, uint32_t * createdUID, ErrorCode * pError);
virtual void appendMessageWithCustomFlags(String * folder, Data * messageData, MessageFlag flags, Array * customFlags,
IMAPProgressCallback * progressCallback, uint32_t * createdUID, ErrorCode * pError);
+ virtual void appendMessageWithCustomFlagsAndDate(String * folder, Data * messageData, MessageFlag flags, Array * customFlags, time_t date,
+ IMAPProgressCallback * progressCallback, uint32_t * createdUID, ErrorCode * pError);
void copyMessages(String * folder, IndexSet * uidSet, String * destFolder,
HashMap ** pUidMapping, ErrorCode * pError);
diff --git a/src/core/rfc822/MCMessageBuilder.cc b/src/core/rfc822/MCMessageBuilder.cc
index 384bb4e5..cd87009e 100644
--- a/src/core/rfc822/MCMessageBuilder.cc
+++ b/src/core/rfc822/MCMessageBuilder.cc
@@ -580,6 +580,9 @@ Array * MessageBuilder::attachments()
void MessageBuilder::addAttachment(Attachment * attachment)
{
+ if (attachment == NULL) {
+ return;
+ }
if (mAttachments == NULL) {
mAttachments = new Array();
}
@@ -598,6 +601,9 @@ Array * MessageBuilder::relatedAttachments()
void MessageBuilder::addRelatedAttachment(Attachment * attachment)
{
+ if (attachment == NULL) {
+ return;
+ }
if (mRelatedAttachments == NULL) {
mRelatedAttachments = new Array();
}
diff --git a/src/core/rfc822/MCMessageParser.cc b/src/core/rfc822/MCMessageParser.cc
index 0366d597..d5bf84e7 100644
--- a/src/core/rfc822/MCMessageParser.cc
+++ b/src/core/rfc822/MCMessageParser.cc
@@ -30,6 +30,25 @@ void MessageParser::init()
MessageParser::MessageParser(Data * data)
{
init();
+
+ const char * start = NULL;
+ unsigned int length = 0;
+ if (data->length() > 5) {
+ if (strncmp(data->bytes(), "From ", 5) == 0) {
+ start = data->bytes();
+ for(unsigned int i = 0 ; i < data->length() ; i ++) {
+ if (start[i] == '\n') {
+ start = start + i + 1;
+ length = data->length() - (i + 1);
+ break;
+ }
+ }
+ }
+ }
+ if (start != NULL) {
+ data = Data::dataWithBytes(start, length);
+ }
+
mData = (Data *) data->retain();
mailmessage * msg;
diff --git a/src/objc/imap/MCOIMAPAppendMessageOperation.h b/src/objc/imap/MCOIMAPAppendMessageOperation.h
index 04d64594..1e5fbd39 100644
--- a/src/objc/imap/MCOIMAPAppendMessageOperation.h
+++ b/src/objc/imap/MCOIMAPAppendMessageOperation.h
@@ -17,6 +17,8 @@
@interface MCOIMAPAppendMessageOperation : MCOIMAPBaseOperation
+@property (nonatomic, assign) time_t date;
+
/**
This block will be called as bytes are sent
*/
diff --git a/src/objc/imap/MCOIMAPAppendMessageOperation.mm b/src/objc/imap/MCOIMAPAppendMessageOperation.mm
index 042324b3..2dd16ced 100644
--- a/src/objc/imap/MCOIMAPAppendMessageOperation.mm
+++ b/src/objc/imap/MCOIMAPAppendMessageOperation.mm
@@ -78,4 +78,6 @@ typedef void (^CompletionType)(NSError *error, uint32_t createdUID);
}
}
+MCO_OBJC_SYNTHESIZE_SCALAR(time_t, time_t, setDate, date)
+
@end
diff --git a/src/objc/imap/MCOIMAPSession.h b/src/objc/imap/MCOIMAPSession.h
index 101f7953..7a35b7e3 100755
--- a/src/objc/imap/MCOIMAPSession.h
+++ b/src/objc/imap/MCOIMAPSession.h
@@ -117,7 +117,11 @@
It will make MCOIMAPSession safe. It will also set all the callbacks of operations to run on this given queue.
Defaults to the main queue.
This property should be used only if there's performance issue using MCOIMAPSession in the main thread. */
+#if OS_OBJECT_USE_OBJC
@property (nonatomic, retain) dispatch_queue_t dispatchQueue;
+#else
+@property (nonatomic, assign) dispatch_queue_t dispatchQueue;
+#endif
/**
The value will be YES when asynchronous operations are running, else it will return NO.
diff --git a/src/objc/pop/MCOPOPSession.h b/src/objc/pop/MCOPOPSession.h
index 74ed216b..719b65b7 100644
--- a/src/objc/pop/MCOPOPSession.h
+++ b/src/objc/pop/MCOPOPSession.h
@@ -66,7 +66,11 @@ See MCOConnectionType for more information.*/
It will make MCOPOPSession safe. It will also set all the callbacks of operations to run on this given queue.
Defaults to the main queue.
This property should be used only if there's performance issue using MCOPOPSession in the main thread. */
+#if OS_OBJECT_USE_OBJC
@property (nonatomic, retain) dispatch_queue_t dispatchQueue;
+#else
+@property (nonatomic, assign) dispatch_queue_t dispatchQueue;
+#endif
/** @name Operations */
diff --git a/src/objc/smtp/MCOSMTPSession.h b/src/objc/smtp/MCOSMTPSession.h
index 8e5deaa3..5c616244 100644
--- a/src/objc/smtp/MCOSMTPSession.h
+++ b/src/objc/smtp/MCOSMTPSession.h
@@ -80,7 +80,11 @@
It will make MCOSMTPSession safe. It will also set all the callbacks of operations to run on this given queue.
Defaults to the main queue.
This property should be used only if there's performance issue using MCOSMTPSession in the main thread. */
+#if OS_OBJECT_USE_OBJC
@property (nonatomic, retain) dispatch_queue_t dispatchQueue;
+#else
+@property (nonatomic, assign) dispatch_queue_t dispatchQueue;
+#endif
/** @name Operations */
diff --git a/src/objc/utils/MCOOperation.h b/src/objc/utils/MCOOperation.h
index b42dfbef..e3aa758a 100644
--- a/src/objc/utils/MCOOperation.h
+++ b/src/objc/utils/MCOOperation.h
@@ -23,7 +23,11 @@
/** The queue this operation dispatches the callback on. Defaults to the main queue.
This property should be used only if there's performance issue creating or calling the callback
in the main thread. */
+#if OS_OBJECT_USE_OBJC
@property (nonatomic, retain) dispatch_queue_t callbackDispatchQueue;
+#else
+@property (nonatomic, assign) dispatch_queue_t callbackDispatchQueue;
+#endif
/** This methods is called on the main thread when the asynchronous operation is finished.
Needs to be overriden by subclasses.*/
diff --git a/src/objc/utils/NSArray+MCO.mm b/src/objc/utils/NSArray+MCO.mm
index 022960f0..061f8429 100644
--- a/src/objc/utils/NSArray+MCO.mm
+++ b/src/objc/utils/NSArray+MCO.mm
@@ -21,6 +21,9 @@
+ (NSArray *) mco_arrayWithMCArray:(mailcore::Array *)array
{
+ if (array == NULL) {
+ return nil;
+ }
NSMutableArray * result = [NSMutableArray array];
for(unsigned int i = 0 ; i < array->count() ; i ++) {
[result addObject:[NSObject mco_objectWithMCObject:array->objectAtIndex(i)]];