aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Robert Widmann <devteam.codafi@gmail.com>2016-01-18 23:41:02 -0500
committerGravatar Robert Widmann <devteam.codafi@gmail.com>2016-01-18 23:41:02 -0500
commit63e1f0471769d8a72edeafbd4e65b9d0c2763e9e (patch)
treebd602a8610c680548761a8fac3fd48025b3f9df5 /src/core
parente1fddae3b6edbbd33a22408f30a36704906cd30f (diff)
parentab62ae2cdddc2fda8ad667260db22617839b3593 (diff)
Merge branch 'master' of https://github.com/MailCore/mailcore2
Diffstat (limited to 'src/core')
-rw-r--r--src/core/abstract/MCAbstractPart.cpp33
-rw-r--r--src/core/abstract/MCAbstractPart.h4
-rw-r--r--src/core/abstract/MCAddress.cpp6
-rw-r--r--src/core/abstract/MCErrorMessage.cpp36
-rw-r--r--src/core/abstract/MCMessageConstants.h3
-rw-r--r--src/core/abstract/MCMessageHeader.cpp53
-rw-r--r--src/core/basetypes/MCAssert.c2
-rw-r--r--src/core/basetypes/MCBaseTypes.h1
-rw-r--r--src/core/basetypes/MCData.cpp14
-rw-r--r--src/core/basetypes/MCData.h2
-rw-r--r--src/core/basetypes/MCHTMLCleaner.h4
-rw-r--r--src/core/basetypes/MCHashMap.cpp4
-rw-r--r--src/core/basetypes/MCIndexSet.cpp64
-rw-r--r--src/core/basetypes/MCIndexSet.h3
-rw-r--r--src/core/basetypes/MCJSONParser.cpp6
-rw-r--r--src/core/basetypes/MCLog.cpp8
-rw-r--r--src/core/basetypes/MCObject.cpp7
-rw-r--r--src/core/basetypes/MCString.cpp212
-rw-r--r--src/core/basetypes/MCString.h3
-rw-r--r--src/core/basetypes/MCUtils.h18
-rw-r--r--src/core/basetypes/icu-ucsdet/cstring.c2
-rw-r--r--src/core/basetypes/icu-ucsdet/uinvchar.c4
-rw-r--r--src/core/basetypes/icu-ucsdet/ustring.cpp2
-rw-r--r--src/core/imap/MCIMAPMessage.cpp5
-rw-r--r--src/core/imap/MCIMAPNamespace.cpp13
-rw-r--r--src/core/imap/MCIMAPNamespace.h4
-rw-r--r--src/core/imap/MCIMAPNamespaceItem.cpp20
-rw-r--r--src/core/imap/MCIMAPNamespaceItem.h4
-rw-r--r--src/core/imap/MCIMAPSearchExpression.cpp18
-rw-r--r--src/core/imap/MCIMAPSearchExpression.h3
-rwxr-xr-xsrc/core/imap/MCIMAPSession.cpp48
-rwxr-xr-xsrc/core/imap/MCIMAPSession.h3
-rw-r--r--src/core/nntp/MCNNTPGroupInfo.cpp2
-rw-r--r--src/core/nntp/MCNNTPSession.cpp7
-rw-r--r--src/core/nntp/MCNNTPSession.h2
-rw-r--r--src/core/pop/MCPOPSession.cpp1
-rw-r--r--src/core/provider/MCAccountValidator.cpp497
-rw-r--r--src/core/provider/MCAccountValidator.h119
-rw-r--r--src/core/provider/MCMXRecordResolverOperation.cpp75
-rw-r--r--src/core/provider/MCMXRecordResolverOperation.h41
-rw-r--r--src/core/provider/MCMailProvider.cpp35
-rw-r--r--src/core/provider/MCMailProvidersManager.cpp20
-rw-r--r--src/core/provider/MCMailProvidersManager.h2
-rw-r--r--src/core/provider/MCNetService.h2
-rw-r--r--src/core/provider/MCProvider.h1
-rw-r--r--src/core/renderer/MCHTMLRenderer.cpp31
-rw-r--r--src/core/renderer/MCHTMLRendererCallback.cpp4
-rw-r--r--src/core/renderer/MCHTMLRendererCallback.h2
-rw-r--r--src/core/rfc822/MCAttachment.cpp22
-rw-r--r--src/core/rfc822/MCMessageParser.cpp20
-rw-r--r--src/core/rfc822/MCMessageParser.h3
-rw-r--r--src/core/rfc822/MCMessagePart.cpp12
-rw-r--r--src/core/rfc822/MCMultipart.cpp11
-rw-r--r--src/core/smtp/MCSMTPSession.cpp44
-rw-r--r--src/core/zip/MCZip.cpp19
-rw-r--r--src/core/zip/MCZipMac.mm30
-rw-r--r--src/core/zip/MCZipPrivate.h20
57 files changed, 1498 insertions, 133 deletions
diff --git a/src/core/abstract/MCAbstractPart.cpp b/src/core/abstract/MCAbstractPart.cpp
index e88a5a36..0956368c 100644
--- a/src/core/abstract/MCAbstractPart.cpp
+++ b/src/core/abstract/MCAbstractPart.cpp
@@ -28,6 +28,7 @@ AbstractPart::AbstractPart(AbstractPart * other)
setContentLocation(other->mContentLocation);
setContentDescription(other->mContentDescription);
setInlineAttachment(other->mInlineAttachment);
+ setAttachment(other->mAttachment);
setPartType(other->mPartType);
setContentTypeParameters(other->mContentTypeParameters);
}
@@ -42,6 +43,7 @@ void AbstractPart::init()
mContentLocation = NULL;
mContentDescription = NULL;
mInlineAttachment = false;
+ mAttachment = false;
mPartType = PartTypeSingle;
mContentTypeParameters = NULL;
}
@@ -81,6 +83,7 @@ String * AbstractPart::description()
result->appendUTF8Format("content-description: %s\n", mContentDescription->UTF8Characters());
}
result->appendUTF8Format("inline: %i\n", mInlineAttachment);
+ result->appendUTF8Format("attachment: %i\n", mAttachment);
if (mContentTypeParameters != NULL) {
mc_foreachhashmapKeyAndValue(String, key, String, value, mContentTypeParameters) {
result->appendUTF8Format("%s: %s\n", key->UTF8Characters(), value->UTF8Characters());
@@ -186,6 +189,16 @@ void AbstractPart::setInlineAttachment(bool inlineAttachment)
mInlineAttachment = inlineAttachment;
}
+bool AbstractPart::isAttachment()
+{
+ return mAttachment;
+}
+
+void AbstractPart::setAttachment(bool attachment)
+{
+ mAttachment = attachment;
+}
+
void AbstractPart::importIMAPFields(struct mailimap_body_fields * fields,
struct mailimap_body_ext_1part * extension)
{
@@ -233,7 +246,10 @@ void AbstractPart::importIMAPFields(struct mailimap_body_fields * fields,
if (strcasecmp(extension->bd_disposition->dsp_type, "inline") == 0) {
setInlineAttachment(true);
}
-
+ else if (strcasecmp(extension->bd_disposition->dsp_type, "attachment") == 0) {
+ setAttachment(true);
+ }
+
if (extension->bd_disposition->dsp_attributes != NULL) {
clistiter * cur;
@@ -345,6 +361,9 @@ HashMap * AbstractPart::serializable()
if (mInlineAttachment) {
result->setObjectForKey(MCSTR("inlineAttachment"), MCSTR("1"));
}
+ if (mAttachment) {
+ result->setObjectForKey(MCSTR("attachment"), MCSTR("1"));
+ }
String * partTypeStr;
switch (mPartType) {
default:
@@ -387,6 +406,12 @@ void AbstractPart::importSerializable(HashMap * serializable)
setInlineAttachment(true);
}
}
+ value = (String *) serializable->objectForKey(MCSTR("attachment"));
+ if (value != NULL) {
+ if (value->intValue()) {
+ setAttachment(true);
+ }
+ }
value = (String *) serializable->objectForKey(MCSTR("partType"));
if (value != NULL) {
if (value->isEqual(MCSTR("single"))) {
@@ -417,8 +442,9 @@ void AbstractPart::setContentTypeParameters(HashMap * parameters)
Array * AbstractPart::allContentTypeParametersNames()
{
- if (mContentTypeParameters == NULL)
+ if (mContentTypeParameters == NULL) {
return Array::array();
+ }
return mContentTypeParameters->allKeys();
}
@@ -433,8 +459,9 @@ void AbstractPart::setContentTypeParameter(String * name, String * object)
void AbstractPart::removeContentTypeParameter(String * name)
{
- if (mContentTypeParameters == NULL)
+ if (mContentTypeParameters == NULL) {
return;
+ }
mc_foreachhashmapKey(String, key, mContentTypeParameters) {
if (key->isEqualCaseInsensitive(name)) {
mContentTypeParameters->removeObjectForKey(key);
diff --git a/src/core/abstract/MCAbstractPart.h b/src/core/abstract/MCAbstractPart.h
index 7a743e1d..88b5b331 100644
--- a/src/core/abstract/MCAbstractPart.h
+++ b/src/core/abstract/MCAbstractPart.h
@@ -43,6 +43,9 @@ namespace mailcore {
virtual bool isInlineAttachment();
virtual void setInlineAttachment(bool inlineAttachment);
+ virtual bool isAttachment();
+ virtual void setAttachment(bool attachment);
+
virtual AbstractPart * partForContentID(String * contentID);
virtual AbstractPart * partForUniqueID(String * uniqueID);
@@ -75,6 +78,7 @@ namespace mailcore {
String * mContentLocation;
String * mContentDescription;
bool mInlineAttachment;
+ bool mAttachment;
PartType mPartType;
HashMap * mContentTypeParameters;
void init();
diff --git a/src/core/abstract/MCAddress.cpp b/src/core/abstract/MCAddress.cpp
index 98b4d8ec..335bc68b 100644
--- a/src/core/abstract/MCAddress.cpp
+++ b/src/core/abstract/MCAddress.cpp
@@ -213,6 +213,9 @@ Array * Address::addressesWithNonEncodedRFC822String(String * string)
String * Address::RFC822StringForAddresses(Array * addresses)
{
String * result = String::string();
+ if (addresses == NULL) {
+ return result;
+ }
for(unsigned int i = 0 ; i < addresses->count() ; i ++) {
Address * address = (Address *) addresses->objectAtIndex(i);
if (i != 0) {
@@ -226,6 +229,9 @@ String * Address::RFC822StringForAddresses(Array * addresses)
String * Address::nonEncodedRFC822StringForAddresses(Array * addresses)
{
String * result = String::string();
+ if (addresses == NULL) {
+ return result;
+ }
for(unsigned int i = 0 ; i < addresses->count() ; i ++) {
Address * address = (Address *) addresses->objectAtIndex(i);
if (i != 0) {
diff --git a/src/core/abstract/MCErrorMessage.cpp b/src/core/abstract/MCErrorMessage.cpp
index c7205d42..bbe65eb1 100644
--- a/src/core/abstract/MCErrorMessage.cpp
+++ b/src/core/abstract/MCErrorMessage.cpp
@@ -15,35 +15,37 @@ static const char * localizedDescriptionTable[] = {
"MobileMe is no longer an active mail service.", /** MCOErrorMobileMeMoved */
"Yahoo!'s servers are currently unavailable.", /** MCOErrorYahooUnavailable */
"The requested folder does not exist. Folder selection failed", /** MCOErrorNonExistantFolder */
- "An error occured while renaming the requested folder.", /** MCOErrorRename */
- "An error occured while deleting the requested folder.", /** MCOErrorDelete */
- "An error occured while creating the requested folder.", /** MCOErrorCreate */
- "An error occured while (un)subscribing to the requested folder.", /** MCOErrorSubscribe */
- "An error occured while appending a message to the requested folder.", /** MCOErrorAppend */
- "An error occured while copying a message to the requested folder.", /** MCOErrorCopy */
- "An error occured while expunging a message in the requested folder.", /** MCOErrorExpunge */
- "An error occured while fetching messages in the requested folder.", /** MCOErrorFetch */
- "An error occured during an IDLE operation.", /** MCOErrorIdle */
- "An error occured while requesting the server's identity.", /** MCOErrorIdentity */
- "An error occured while requesting the server's namespace.", /** MCOErrorNamespace */
- "An error occured while storing flags.", /** MCOErrorStore */
- "An error occured while requesting the server's capabilities.", /** MCOErrorCapability */
+ "An error occurred while renaming the requested folder.", /** MCOErrorRename */
+ "An error occurred while deleting the requested folder.", /** MCOErrorDelete */
+ "An error occurred while creating the requested folder.", /** MCOErrorCreate */
+ "An error occurred while (un)subscribing to the requested folder.", /** MCOErrorSubscribe */
+ "An error occurred while appending a message to the requested folder.", /** MCOErrorAppend */
+ "An error occurred while copying a message to the requested folder.", /** MCOErrorCopy */
+ "An error occurred while expunging a message in the requested folder.", /** MCOErrorExpunge */
+ "An error occurred while fetching messages in the requested folder.", /** MCOErrorFetch */
+ "An error occurred during an IDLE operation.", /** MCOErrorIdle */
+ "An error occurred while requesting the server's identity.", /** MCOErrorIdentity */
+ "An error occurred while requesting the server's namespace.", /** MCOErrorNamespace */
+ "An error occurred while storing flags.", /** MCOErrorStore */
+ "An error occurred while requesting the server's capabilities.", /** MCOErrorCapability */
"The server does not support STARTTLS connections.", /** MCOErrorStartTLSNotAvailable */
"Attempted to send a message with an illegal attachment.", /** MCOErrorSendMessageIllegalAttachment */
"The SMTP storage limit was hit while trying to send a large message.", /** MCOErrorStorageLimit */
"Sending messages is not allowed on this server.", /** MCOErrorSendMessageNotAllowed */
"The current HotMail account cannot connect to WebMail.", /** MCOErrorNeedsConnectToWebmail */
- "An error occured while sending the message.", /** MCOErrorSendMessage */
+ "An error occurred while sending the message.", /** MCOErrorSendMessage */
"Authentication is required for this SMTP server.", /** MCOErrorAuthenticationRequired */
- "An error occured while fetching a message list on the POP server.", /** MCOErrorFetchMessageList */
- "An error occured while deleting a message on the POP server.", /** MCOErrorDeleteMessage */
+ "An error occurred while fetching a message list on the POP server.", /** MCOErrorFetchMessageList */
+ "An error occurred while deleting a message on the POP server.", /** MCOErrorDeleteMessage */
"Account check failed because the account is invalid.", /** MCOErrorInvalidAccount */
"File access error", /** MCOErrorFile */
"Compression is not available", /** MCOErrorCompression */
"A sender is required to send message", /** MCOErrorNoSender */
"A recipient is required to send message", /** MCOErrorNoRecipient */
- "An error occured while performing a No-Op operation.", /** MCOErrorNoop */
+ "An error occurred while performing a No-Op operation.", /** MCOErrorNoop */
"An application specific password is required", /** MCOErrorGmailApplicationSpecificPasswordRequired */
+ "An error when requesting date", /** MCOErrorServerDate */
+ "No valid server found", /** MCOErrorNoValidServerFound */
};
String * mailcore::errorMessageWithErrorCode(ErrorCode errorCode)
diff --git a/src/core/abstract/MCMessageConstants.h b/src/core/abstract/MCMessageConstants.h
index 1c489583..7d7403da 100644
--- a/src/core/abstract/MCMessageConstants.h
+++ b/src/core/abstract/MCMessageConstants.h
@@ -180,6 +180,7 @@ namespace mailcore {
IMAPSearchKindContent,
IMAPSearchKindBody,
IMAPSearchKindUIDs,
+ IMAPSearchKindNumbers,
IMAPSearchKindHeader,
IMAPSearchKindRead,
IMAPSearchKindUnread,
@@ -250,6 +251,8 @@ namespace mailcore {
ErrorNoop,
ErrorGmailApplicationSpecificPasswordRequired, // 40
ErrorServerDate,
+ ErrorNoValidServerFound,
+ ErrorCustomCommand,
};
enum PartType {
diff --git a/src/core/abstract/MCMessageHeader.cpp b/src/core/abstract/MCMessageHeader.cpp
index e65695ca..63675be5 100644
--- a/src/core/abstract/MCMessageHeader.cpp
+++ b/src/core/abstract/MCMessageHeader.cpp
@@ -721,12 +721,7 @@ struct mailimf_fields * MessageHeader::createIMFFieldsAndFilterBcc(bool filterBc
imfSubject = strdup(data->bytes());
}
}
-
- if ((imfTo == NULL) && (imfCc == NULL) && (imfBcc == NULL)) {
- imfTo = mailimf_address_list_new_empty();
- mailimf_address_list_add_parse(imfTo, (char *) "Undisclosed recipients:;");
- }
-
+
fields = mailimf_fields_new_with_data_all(imfDate,
imfFrom,
NULL /* sender */,
@@ -985,6 +980,7 @@ Array * MessageHeader::recipientWithReplyAll(bool replyAll, bool includeTo, bool
Array * toField;
Array * ccField;
bool containsSender;
+ Array * senderEmailsMailboxes;
toField = NULL;
ccField = NULL;
@@ -992,19 +988,23 @@ Array * MessageHeader::recipientWithReplyAll(bool replyAll, bool includeTo, bool
hasTo = false;
hasCc = false;
addedAddresses = new Set();
-
+ senderEmailsMailboxes = Array::array();
+
containsSender = false;
if (senderEmails != NULL) {
- if (from() != NULL) {
- if (senderEmails->containsObject(from()->mailbox()->lowercaseString())) {
- containsSender = true;
+ mc_foreacharray(Address, address, senderEmails) {
+ senderEmailsMailboxes->addObject(address->mailbox()->lowercaseString());
}
- }
- if (sender() != NULL) {
- if (senderEmails->containsObject(sender()->mailbox()->lowercaseString())) {
- containsSender = true;
+ if (from() != NULL) {
+ if (senderEmailsMailboxes->containsObject(from()->mailbox()->lowercaseString())) {
+ containsSender = true;
+ }
+ }
+ if (sender() != NULL) {
+ if (senderEmailsMailboxes->containsObject(sender()->mailbox()->lowercaseString())) {
+ containsSender = true;
+ }
}
- }
}
if (containsSender) {
@@ -1019,12 +1019,14 @@ Array * MessageHeader::recipientWithReplyAll(bool replyAll, bool includeTo, bool
}
if ((from() != NULL) && address->mailbox()->isEqualCaseInsensitive(from()->mailbox())) {
recipient->addObjectsFromArray(replyTo());
- for(unsigned int j = 0 ; j < replyTo()->count() ; j ++) {
- Address * rtAddress = (Address *) replyTo()->objectAtIndex(j);
- if (addedAddresses->containsObject(rtAddress->mailbox()->lowercaseString())) {
- continue;
+ if (replyTo() != NULL) {
+ for(unsigned int j = 0 ; j < replyTo()->count() ; j ++) {
+ Address * rtAddress = (Address *) replyTo()->objectAtIndex(j);
+ if (addedAddresses->containsObject(rtAddress->mailbox()->lowercaseString())) {
+ continue;
+ }
+ addedAddresses->addObject(rtAddress->mailbox()->lowercaseString());
}
- addedAddresses->addObject(rtAddress->mailbox()->lowercaseString());
}
}
else {
@@ -1066,7 +1068,7 @@ Array * MessageHeader::recipientWithReplyAll(bool replyAll, bool includeTo, bool
}
}
else {
- addedAddresses->addObjectsFromArray(senderEmails);
+ addedAddresses->addObjectsFromArray(senderEmailsMailboxes);
if (replyTo() != NULL && replyTo()->count() > 0) {
hasTo = true;
@@ -1152,7 +1154,12 @@ MessageHeader * MessageHeader::replyHeader(bool replyAll, Array * addressesExclu
subjectValue = MCSTR("Re: ");
}
else {
- subjectValue = MCSTR("Re: ")->stringByAppendingString(subject());
+ if (!subject()->lowercaseString()->hasPrefix(MCSTR("re:"))) {
+ subjectValue = MCSTR("Re: ")->stringByAppendingString(subject());
+ }
+ else {
+ subjectValue = (String *) subject()->copy()->autorelease();
+ }
}
if (references() != NULL) {
referencesValue = (Array *) (references()->copy());
@@ -1193,7 +1200,7 @@ MessageHeader * MessageHeader::forwardHeader()
subjectValue = MCSTR("Fw: ");
}
else {
- subjectValue = MCSTR("Fw: ")->stringByAppendingString(subject());
+ subjectValue = MCSTR("Fw: ")->stringByAppendingString(subject()->extractedSubjectAndKeepBracket(true));
}
if (references() != NULL) {
referencesValue = (Array *) (references()->copy());
diff --git a/src/core/basetypes/MCAssert.c b/src/core/basetypes/MCAssert.c
index ce9b5703..564f1648 100644
--- a/src/core/basetypes/MCAssert.c
+++ b/src/core/basetypes/MCAssert.c
@@ -9,6 +9,6 @@ void MCAssertInternal(const char * filename, unsigned int line, int cond, const
return;
}
- fprintf(stderr, "%s:%i: assert %s\n", filename, line, condString);
+ fprintf(stderr, "%s:%u: assert %s\n", filename, line, condString);
abort();
}
diff --git a/src/core/basetypes/MCBaseTypes.h b/src/core/basetypes/MCBaseTypes.h
index ce3e1153..3088d4c2 100644
--- a/src/core/basetypes/MCBaseTypes.h
+++ b/src/core/basetypes/MCBaseTypes.h
@@ -26,5 +26,6 @@
#include <MailCore/MCICUTypes.h>
#include <MailCore/MCIterator.h>
#include <MailCore/MCConnectionLogger.h>
+#include <MailCore/MCHTMLCleaner.h>
#endif
diff --git a/src/core/basetypes/MCData.cpp b/src/core/basetypes/MCData.cpp
index 8b689036..079344da 100644
--- a/src/core/basetypes/MCData.cpp
+++ b/src/core/basetypes/MCData.cpp
@@ -718,6 +718,20 @@ void Data::importSerializable(HashMap * serializable)
setData(((String *) (serializable->objectForKey(MCSTR("data"))))->decodedBase64Data());
}
+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 (result == 0) {
+ return ErrorFile;
+ }
+ return ErrorNone;
+}
+
#if __APPLE__
static CFStringEncoding encodingFromCString(const char * charset)
{
diff --git a/src/core/basetypes/MCData.h b/src/core/basetypes/MCData.h
index bec75008..0bb1bc07 100644
--- a/src/core/basetypes/MCData.h
+++ b/src/core/basetypes/MCData.h
@@ -44,6 +44,8 @@ namespace mailcore {
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/MCHTMLCleaner.h b/src/core/basetypes/MCHTMLCleaner.h
index 33e65767..eccf88c9 100644
--- a/src/core/basetypes/MCHTMLCleaner.h
+++ b/src/core/basetypes/MCHTMLCleaner.h
@@ -13,6 +13,8 @@
#include <MailCore/MCString.h>
#include <MailCore/MCUtils.h>
+#ifdef __cplusplus
+
namespace mailcore {
class MAILCORE_EXPORT HTMLCleaner {
@@ -23,3 +25,5 @@ namespace mailcore {
}
#endif
+
+#endif
diff --git a/src/core/basetypes/MCHashMap.cpp b/src/core/basetypes/MCHashMap.cpp
index c56277fc..9958c502 100644
--- a/src/core/basetypes/MCHashMap.cpp
+++ b/src/core/basetypes/MCHashMap.cpp
@@ -169,6 +169,10 @@ void HashMap::removeObjectForKey(Object * key)
{
unsigned int func, indx;
HashMapIter * iter, * old;
+
+ if (key == NULL) {
+ return;
+ }
func = key->hash();;
indx = func % mAllocated;
diff --git a/src/core/basetypes/MCIndexSet.cpp b/src/core/basetypes/MCIndexSet.cpp
index 7f7e1db3..191a1588 100644
--- a/src/core/basetypes/MCIndexSet.cpp
+++ b/src/core/basetypes/MCIndexSet.cpp
@@ -398,6 +398,21 @@ void IndexSet::importSerializable(HashMap * serializable)
}
}
+bool IndexSet::isEqual(Object * otherObject)
+{
+ IndexSet * otherIndexSet = (IndexSet *) otherObject;
+ if (mCount != otherIndexSet->mCount) {
+ return false;
+ }
+ for(unsigned int i = 0 ; i < mCount ; i ++) {
+ if ((mRanges[i].location != otherIndexSet->mRanges[i].location) ||
+ (mRanges[i].length != otherIndexSet->mRanges[i].length)) {
+ return false;
+ }
+ }
+ return true;
+}
+
void IndexSet::addIndexSet(IndexSet * indexSet)
{
for(unsigned int i = 0 ; i < indexSet->rangesCount() ; i ++) {
@@ -435,3 +450,52 @@ INITIALIZE(IndexSet)
{
Object::registerObjectConstructor("mailcore::IndexSet", &createObject);
}
+
+/*
+
+Unit test:
+
+String * uidsStr = MCSTR("129597-129662,129664,129667-129671,129673-129674,129678-129694,129696-129804");
+String * cachedUidsStr = MCSTR("129755-129804");
+IndexSet * uids = NULL;
+IndexSet * cachedUids = NULL;
+
+{
+ IndexSet * result = new IndexSet();
+ Array * array = uidsStr->componentsSeparatedByString(MCSTR(","));
+ mc_foreacharray(String, rangeStr, array) {
+ Array * rangeArray = rangeStr->componentsSeparatedByString(MCSTR("-"));
+ if (rangeArray->count() == 2) {
+ int left = ((String *) rangeArray->objectAtIndex(0))->intValue();
+ int right = ((String *) rangeArray->objectAtIndex(1))->intValue();
+ int length = right - left;
+ result->addRange(RangeMake(left, length));
+ }
+ else {
+ result->addIndex(rangeStr->intValue());
+ }
+ }
+ //fprintf(stderr, "%s\n", MCUTF8DESC(result));
+ uids = result;
+}
+{
+ IndexSet * result = new IndexSet();
+ Array * array = cachedUidsStr->componentsSeparatedByString(MCSTR(","));
+ mc_foreacharray(String, rangeStr, array) {
+ Array * rangeArray = rangeStr->componentsSeparatedByString(MCSTR("-"));
+ if (rangeArray->count() == 2) {
+ int left = ((String *) rangeArray->objectAtIndex(0))->intValue();
+ int right = ((String *) rangeArray->objectAtIndex(1))->intValue();
+ int length = right - left;
+ result->addRange(RangeMake(left, length));
+ }
+ else {
+ result->addIndex(rangeStr->intValue());
+ }
+ }
+ cachedUids = result;
+}
+fprintf(stderr, "|%s|\n", MCUTF8DESC(uids));
+uids->removeIndexSet(cachedUids);
+fprintf(stderr, "|%s|\n", MCUTF8DESC(uids));
+*/
diff --git a/src/core/basetypes/MCIndexSet.h b/src/core/basetypes/MCIndexSet.h
index 2e2f4892..2cf67b07 100644
--- a/src/core/basetypes/MCIndexSet.h
+++ b/src/core/basetypes/MCIndexSet.h
@@ -50,7 +50,8 @@ namespace mailcore {
virtual Object * copy();
virtual HashMap * serializable();
virtual void importSerializable(HashMap * serializable);
-
+ virtual bool isEqual(Object * otherObject);
+
private:
Range * mRanges;
unsigned int mCount;
diff --git a/src/core/basetypes/MCJSONParser.cpp b/src/core/basetypes/MCJSONParser.cpp
index d9f68204..cfddbf9e 100644
--- a/src/core/basetypes/MCJSONParser.cpp
+++ b/src/core/basetypes/MCJSONParser.cpp
@@ -587,7 +587,7 @@ bool JSONParser::parseFloat()
}
else {
mPosition += endptr - str;
- mResult = Value::valueWithDoubleValue(value);
+ mResult = Value::valueWithDoubleValue(value)->retain();
}
pool->release();
@@ -617,7 +617,9 @@ Object * JSONParser::objectFromString(String * str)
parser->setContent(str);
parser->parse();
result = parser->result();
- result->retain()->autorelease();
+ if (result != NULL) {
+ result->retain()->autorelease();
+ }
parser->release();
return result;
diff --git a/src/core/basetypes/MCLog.cpp b/src/core/basetypes/MCLog.cpp
index 952229ec..386ac422 100644
--- a/src/core/basetypes/MCLog.cpp
+++ b/src/core/basetypes/MCLog.cpp
@@ -53,9 +53,7 @@ static void logInternalv(FILE * file,
return;
while (1) {
- const char * p = filename;
-
- p = strchr(filename, '/');
+ const char * p = strchr(filename, '/');
if (p == NULL) {
break;
}
@@ -80,7 +78,7 @@ static void logInternalv(FILE * file,
#else
if (0) {
#endif
- fprintf(file, "[%i:main] %s:%i: ", sPid, filename, line);
+ fprintf(file, "[%i:main] %s:%u: ", sPid, filename, line);
}
else {
unsigned long threadValue;
@@ -91,7 +89,7 @@ static void logInternalv(FILE * file,
#else
threadValue = (unsigned long) thread_id;
#endif
- fprintf(file, "[%i:%lx] %s:%i: ", sPid, threadValue, filename, line);
+ fprintf(file, "[%i:%lx] %s:%u: ", sPid, threadValue, filename, line);
}
vfprintf(file, format, argp);
fprintf(file, "\n");
diff --git a/src/core/basetypes/MCObject.cpp b/src/core/basetypes/MCObject.cpp
index bbcddb2f..6f776ef6 100644
--- a/src/core/basetypes/MCObject.cpp
+++ b/src/core/basetypes/MCObject.cpp
@@ -181,7 +181,7 @@ static void removeFromPerformHash(Object * obj, Object::Method method, void * co
keyData.method = method;
key.data = &keyData;
key.len = sizeof(keyData);
-
+
pthread_mutex_lock(&delayedPerformLock);
chash_delete(delayedPerformHash, (chashdatum *) &key, NULL);
pthread_mutex_unlock(&delayedPerformLock);
@@ -360,7 +360,9 @@ void Object::performMethodOnDispatchQueueAfterDelay(Method method, void * contex
}
dupCancelableBlock(false);
Block_release(dupCancelableBlock);
- release();
+ if (!cancelled) {
+ release();
+ }
});
}
@@ -373,6 +375,7 @@ void Object::cancelDelayedPerformMethodOnDispatchQueue(Method method, void * con
}
removeFromPerformHash(this, method, context, targetDispatchQueue);
dupCancelableBlock(true);
+ release();
}
#endif
diff --git a/src/core/basetypes/MCString.cpp b/src/core/basetypes/MCString.cpp
index 213d5e5f..9c024067 100644
--- a/src/core/basetypes/MCString.cpp
+++ b/src/core/basetypes/MCString.cpp
@@ -823,7 +823,9 @@ String::String(const char * UTF8Characters)
{
mUnicodeChars = NULL;
reset();
- allocate((unsigned int) strlen(UTF8Characters), true);
+ if (UTF8Characters != NULL) {
+ allocate((unsigned int) strlen(UTF8Characters), true);
+ }
appendUTF8Characters(UTF8Characters);
}
@@ -890,7 +892,7 @@ void String::allocate(unsigned int length, bool force)
String * String::string()
{
- return stringWithCharacters(NULL);
+ return stringWithCharacters(NULL, 0);
}
String * String::stringWithData(Data * data, const char * charset)
@@ -926,12 +928,18 @@ String * String::stringWithVUTF8Format(const char * format, va_list ap)
String * String::stringWithUTF8Characters(const char * UTF8Characters)
{
+ if (UTF8Characters == NULL) {
+ return NULL;
+ }
String * result = new String(UTF8Characters);
return (String *) result->autorelease();
}
String * String::stringWithCharacters(const UChar * characters)
{
+ if (characters == NULL) {
+ return NULL;
+ }
String * result = new String(characters);
return (String *) result->autorelease();
}
@@ -1194,6 +1202,9 @@ Data * String::encodedMIMEHeaderValueForSubject()
int String::compareWithCaseSensitive(String * otherString, bool caseSensitive)
{
+ if (otherString == NULL) {
+ return 1;
+ }
if ((length() == 0) && (otherString->length() == 0)) {
return 0;
}
@@ -1206,7 +1217,7 @@ int String::compareWithCaseSensitive(String * otherString, bool caseSensitive)
}
if (otherString->unicodeCharacters() == NULL) {
- return -1;
+ return 1;
}
#if DISABLE_ICU
@@ -2034,25 +2045,69 @@ String * String::flattenHTML()
String * String::stripWhitespace()
{
- String *str = (String *)copy();
-
- str->replaceOccurrencesOfString(MCSTR("\t"), MCSTR(" "));
- str->replaceOccurrencesOfString(MCSTR("\n"), MCSTR(" "));
- str->replaceOccurrencesOfString(MCSTR("\v"), MCSTR(" "));
- str->replaceOccurrencesOfString(MCSTR("\f"), MCSTR(" "));
- str->replaceOccurrencesOfString(MCSTR("\r"), MCSTR(" "));
- str->replaceOccurrencesOfString(s_unicode160, MCSTR(" "));
- str->replaceOccurrencesOfString(s_unicode133, MCSTR(" "));
- str->replaceOccurrencesOfString(s_unicode2028, MCSTR(" "));
+ String * str = (String *)copy();
- while (str->replaceOccurrencesOfString(MCSTR(" "), MCSTR(" ")) > 0) {
- /* do nothing */
+ // replace space-like characters with space.
+ const UChar * source = str->unicodeCharacters();
+ UChar * dest = str->mUnicodeChars;
+ while (* source != 0) {
+ if (* source == '\t') {
+ * dest = ' ';
+ }
+ else if (* source == '\n') {
+ * dest = ' ';
+ }
+ else if (* source == '\t') {
+ * dest = ' ';
+ }
+ else if (* source == '\f') {
+ * dest = ' ';
+ }
+ else if (* source == '\r') {
+ * dest = ' ';
+ }
+ else if (* source == 160) {
+ * dest = ' ';
+ }
+ else if (* source == 133) {
+ * dest = ' ';
+ }
+ else if (* source == 0x2028) {
+ * dest = ' ';
+ }
+ else {
+ * dest = * source;
+ }
+ dest ++;
+ source ++;
}
- while (str->hasPrefix(MCSTR(" "))) {
- str->deleteCharactersInRange(RangeMake(0, 1));
+
+ // skip spaces at the beginning.
+ source = str->unicodeCharacters();
+ dest = str->mUnicodeChars;
+ while (* source == ' ') {
+ source ++;
}
- while (str->hasSuffix(MCSTR(" "))) {
- str->deleteCharactersInRange(RangeMake(str->length() - 1, 1));
+
+ // copy content
+ while (* source != 0) {
+ if ((* source == ' ') && (* (source + 1) == ' ')) {
+ source ++;
+ }
+ * dest = * source;
+ source ++;
+ dest ++;
+ }
+ * dest = 0;
+ str->mLength = (unsigned int) (dest - str->mUnicodeChars);
+
+ // skip spaces at the end.
+ if (str->mLength > 0) {
+ while (* (dest - 1) == ' ') {
+ dest --;
+ }
+ * dest = 0;
+ str->mLength = (unsigned int) (dest - str->mUnicodeChars);
}
str->autorelease();
@@ -2241,10 +2296,29 @@ Array * String::componentsSeparatedByString(String * separator)
p = mUnicodeChars;
while (1) {
UChar * location;
+#if 0
location = u_strstr(p, separator->unicodeCharacters());
if (location == NULL) {
break;
}
+#else
+ int remaining = length() - (int) (p - mUnicodeChars);
+ location = NULL;
+ while (location == NULL) {
+ location = (UChar *) memmem(p, remaining * sizeof(UChar), separator->unicodeCharacters(), separator->length() * sizeof(UChar));
+ if (location == NULL) {
+ break;
+ }
+ // If it's odd, it's an invalid location. Keep looking for the pattern.
+ if (((char *) location - (char *) p) % sizeof(UChar) != 0) {
+ p = (UChar *) (((char *) location) + 1);
+ location = NULL;
+ }
+ }
+ if (location == NULL) {
+ break;
+ }
+#endif
unsigned int length = (unsigned int) (location - p);
String * value = new String(p, length);
@@ -2357,6 +2431,10 @@ String * String::uniquedStringWithUTF8Characters(const char * UTF8Characters)
static pthread_once_t once = PTHREAD_ONCE_INIT;
int r;
+ if (UTF8Characters == NULL) {
+ return NULL;
+ }
+
pthread_once(&once, initUniquedStringHash);
key.data = (void *) UTF8Characters;
key.len = (unsigned int) strlen(UTF8Characters);
@@ -2512,6 +2590,102 @@ Data * String::decodedBase64Data()
return result;
}
+static int hexValue(const char * code) {
+ int value = 0;
+ const char * pch = code;
+ for (;;) {
+ int digit = *pch++;
+ if (digit >= '0' && digit <= '9') {
+ value += digit - '0';
+ }
+ else if (digit >= 'A' && digit <= 'F') {
+ value += digit - 'A' + 10;
+ }
+ else if (digit >= 'a' && digit <= 'f') {
+ value += digit - 'a' + 10;
+ }
+ else {
+ return -1;
+ }
+ if (pch == code + 2) {
+ return value;
+ }
+ value <<= 4;
+ }
+}
+
+String * String::urlDecodedString()
+{
+ Data * sourceData = dataUsingEncoding();
+ const char * source = sourceData->bytes();
+ char * start = (char *) malloc(sourceData->length() + 1);
+ char * dest = start;
+ unsigned int i = 0;
+ while (i < sourceData->length()) {
+ switch (source[i]) {
+ case '%':
+ {
+ if (i + 2 < sourceData->length()) {
+ int value = hexValue(&source[i + 1]);
+ if (value >= 0) {
+ *(dest++) = value;
+ i += 3;
+ }
+ else {
+ *dest++ = '?';
+ i ++;
+ }
+ }
+ else {
+ *dest++ = '?';
+ i ++;
+ }
+ break;
+ }
+ default:
+ {
+ *dest++ = source[i];
+ i ++;
+ break;
+ }
+ }
+ }
+ * dest = 0;
+ String * result = String::stringWithUTF8Characters(start);
+ free(start);
+ return result;
+}
+
+static inline bool isValidUrlChar(char ch) {
+ return strchr("$&+,/:;=?@[]#!'()* ", ch) == NULL;
+}
+
+String * String::urlEncodedString()
+{
+ const char * digits = "0123456789ABCDEF";
+ Data * sourceData = dataUsingEncoding();
+ const char * source = sourceData->bytes();
+ char * start = (char *) malloc(sourceData->length() * 3 + 1);
+ char * dest = start;
+ unsigned int i = 0;
+ while (i < sourceData->length()) {
+ unsigned char ch = (unsigned char) source[i];
+ if (isValidUrlChar(ch)) {
+ *dest++ = ch;
+ } else {
+ *dest++ = '%';
+ *dest++ = digits[(ch >> 4) & 0x0F];
+ *dest++ = digits[ ch & 0x0F];
+ }
+ i ++;
+ }
+ *dest = 0;
+ String * result = String::stringWithUTF8Characters(dest);
+ free(start);
+
+ return result;
+}
+
HashMap * String::serializable()
{
HashMap * result = Object::serializable();
diff --git a/src/core/basetypes/MCString.h b/src/core/basetypes/MCString.h
index cbe5538b..5ee2ad65 100644
--- a/src/core/basetypes/MCString.h
+++ b/src/core/basetypes/MCString.h
@@ -117,6 +117,9 @@ namespace mailcore {
virtual Data * decodedBase64Data();
+ virtual String * urlDecodedString();
+ virtual String * urlEncodedString();
+
public: // private
static String * uniquedStringWithUTF8Characters(const char * UTF8Characters);
diff --git a/src/core/basetypes/MCUtils.h b/src/core/basetypes/MCUtils.h
index eb4ef290..ef8f3cd3 100644
--- a/src/core/basetypes/MCUtils.h
+++ b/src/core/basetypes/MCUtils.h
@@ -48,6 +48,20 @@
# define MAILCORE_EXPORT
#endif
+#ifdef __ANDROID_API__
+#if __ANDROID_API__ < 21
+#include <wchar.h>
+extern int iswblank(wint_t);
+extern int vfwscanf(FILE*, const wchar_t*, va_list);
+extern int vswscanf(const wchar_t*, const wchar_t*, va_list);
+extern int vwscanf(const wchar_t*, va_list);
+extern float wcstof(const wchar_t*, wchar_t**);
+extern long double wcstold(const wchar_t*, wchar_t**);
+extern long long wcstoll(const wchar_t*, wchar_t**, int);
+extern unsigned long long wcstoull(const wchar_t*, wchar_t**, int);
+#endif
+#endif
+
#ifdef __clang__
#if __has_feature(attribute_analyzer_noreturn)
@@ -65,4 +79,8 @@
#endif
+#ifndef DEPRECATED_ATTRIBUTE
+#define DEPRECATED_ATTRIBUTE __attribute__((deprecated))
+#endif
+
#endif
diff --git a/src/core/basetypes/icu-ucsdet/cstring.c b/src/core/basetypes/icu-ucsdet/cstring.c
index 3af959eb..868ee5c0 100644
--- a/src/core/basetypes/icu-ucsdet/cstring.c
+++ b/src/core/basetypes/icu-ucsdet/cstring.c
@@ -225,7 +225,7 @@ U_CAPI int32_t U_EXPORT2
T_CString_stringToInteger(const char *integerString, int32_t radix)
{
char *end;
- return uprv_strtoul(integerString, &end, radix);
+ return (int32_t)uprv_strtoul(integerString, &end, radix);
}
diff --git a/src/core/basetypes/icu-ucsdet/uinvchar.c b/src/core/basetypes/icu-ucsdet/uinvchar.c
index f874edd9..81f73d80 100644
--- a/src/core/basetypes/icu-ucsdet/uinvchar.c
+++ b/src/core/basetypes/icu-ucsdet/uinvchar.c
@@ -569,7 +569,7 @@ uprv_aestrncpy(uint8_t *dst, const uint8_t *src, int32_t n)
uint8_t *orig_dst = dst;
if(n==-1) {
- n = uprv_strlen((const char*)src)+1; /* copy NUL */
+ n = (int32_t)uprv_strlen((const char*)src)+1; /* copy NUL */
}
/* copy non-null */
while(*src && n>0) {
@@ -590,7 +590,7 @@ uprv_eastrncpy(uint8_t *dst, const uint8_t *src, int32_t n)
uint8_t *orig_dst = dst;
if(n==-1) {
- n = uprv_strlen((const char*)src)+1; /* copy NUL */
+ n = (int32_t)uprv_strlen((const char*)src)+1; /* copy NUL */
}
/* copy non-null */
while(*src && n>0) {
diff --git a/src/core/basetypes/icu-ucsdet/ustring.cpp b/src/core/basetypes/icu-ucsdet/ustring.cpp
index 40d23c06..d5d748fc 100644
--- a/src/core/basetypes/icu-ucsdet/ustring.cpp
+++ b/src/core/basetypes/icu-ucsdet/ustring.cpp
@@ -997,7 +997,7 @@ u_strlen(const UChar *s)
while(*t != 0) {
++t;
}
- return t - s;
+ return (int32_t)(t - s);
#endif
}
diff --git a/src/core/imap/MCIMAPMessage.cpp b/src/core/imap/MCIMAPMessage.cpp
index 48139633..530d9075 100644
--- a/src/core/imap/MCIMAPMessage.cpp
+++ b/src/core/imap/MCIMAPMessage.cpp
@@ -26,6 +26,7 @@ void IMAPMessage::init()
mModSeqValue = 0;
mGmailThreadID = 0;
mGmailMessageID = 0;
+ mSize = 0;
}
IMAPMessage::IMAPMessage()
@@ -257,7 +258,7 @@ HashMap * IMAPMessage::serializable()
HashMap * result = AbstractMessage::serializable();
result->setObjectForKey(MCSTR("modSeqValue"), String::stringWithUTF8Format("%llu", (long long unsigned) modSeqValue()));
result->setObjectForKey(MCSTR("uid"), String::stringWithUTF8Format("%lu", (long unsigned) uid()));
- result->setObjectForKey(MCSTR("size"), String::stringWithUTF8Format("%lu", (long unsigned) uid()));
+ result->setObjectForKey(MCSTR("size"), String::stringWithUTF8Format("%lu", (long unsigned) size()));
result->setObjectForKey(MCSTR("flags"), String::stringWithUTF8Format("%u", (unsigned) flags()));
result->setObjectForKey(MCSTR("originalFlags"), String::stringWithUTF8Format("%u", (unsigned) originalFlags()));
if (customFlags() != NULL) {
@@ -300,7 +301,7 @@ void IMAPMessage::importSerializable(HashMap * serializable)
}
String * originalFlags = (String *) serializable->objectForKey(MCSTR("originalFlags"));
if (originalFlags != NULL) {
- setFlags((MessageFlag) originalFlags->unsignedIntValue());
+ setOriginalFlags((MessageFlag) originalFlags->unsignedIntValue());
}
String * customFlags = (String *) serializable->objectForKey(MCSTR("customFlags"));
if (customFlags != NULL) {
diff --git a/src/core/imap/MCIMAPNamespace.cpp b/src/core/imap/MCIMAPNamespace.cpp
index 09037877..d5c618a0 100644
--- a/src/core/imap/MCIMAPNamespace.cpp
+++ b/src/core/imap/MCIMAPNamespace.cpp
@@ -142,3 +142,16 @@ void IMAPNamespace::importIMAPNamespace(struct mailimap_namespace_item * item)
item->release();
}
}
+
+HashMap * IMAPNamespace::serializable()
+{
+ HashMap * result = Object::serializable();
+ result->setObjectForKey(MCSTR("items"), mItems->serializable());
+ return result;
+}
+
+void IMAPNamespace::importSerializable(HashMap * serializable)
+{
+ Array * items = (Array *) Object::objectWithSerializable((HashMap *) serializable->objectForKey(MCSTR("items")));
+ MC_SAFE_REPLACE_RETAIN(Array, mItems, items);
+}
diff --git a/src/core/imap/MCIMAPNamespace.h b/src/core/imap/MCIMAPNamespace.h
index e57cecba..711fb7e5 100644
--- a/src/core/imap/MCIMAPNamespace.h
+++ b/src/core/imap/MCIMAPNamespace.h
@@ -33,7 +33,9 @@ namespace mailcore {
IMAPNamespace(IMAPNamespace * other);
virtual String * description();
virtual Object * copy();
-
+ virtual HashMap * serializable();
+ virtual void importSerializable(HashMap * serializable);
+
private:
Array * /* String */ mItems;
void init();
diff --git a/src/core/imap/MCIMAPNamespaceItem.cpp b/src/core/imap/MCIMAPNamespaceItem.cpp
index c985e915..c8561c50 100644
--- a/src/core/imap/MCIMAPNamespaceItem.cpp
+++ b/src/core/imap/MCIMAPNamespaceItem.cpp
@@ -150,3 +150,23 @@ static Array * decodedComponents(Array * components)
return result;
}
+
+HashMap * IMAPNamespaceItem::serializable()
+{
+ HashMap * result = Object::serializable();
+ result->setObjectForKey(MCSTR("delimiter"), String::stringWithUTF8Format("%c", mDelimiter));
+ if (mPrefix != NULL) {
+ result->setObjectForKey(MCSTR("prefix"), mPrefix);
+ }
+ return result;
+}
+
+void IMAPNamespaceItem::importSerializable(HashMap * serializable)
+{
+ String * aPrefix = (String *) serializable->objectForKey(MCSTR("prefix"));
+ setPrefix(aPrefix);
+ String * delimiterString = (String *) serializable->objectForKey(MCSTR("delimiter"));
+ if ((delimiterString != NULL) && (delimiterString->length() > 0)) {
+ setDelimiter((char) delimiterString->characterAtIndex(0));
+ }
+}
diff --git a/src/core/imap/MCIMAPNamespaceItem.h b/src/core/imap/MCIMAPNamespaceItem.h
index 3ca8e485..0fffed98 100644
--- a/src/core/imap/MCIMAPNamespaceItem.h
+++ b/src/core/imap/MCIMAPNamespaceItem.h
@@ -28,7 +28,9 @@ namespace mailcore {
IMAPNamespaceItem(IMAPNamespaceItem * other);
virtual String * description();
virtual Object * copy();
-
+ virtual HashMap * serializable();
+ virtual void importSerializable(HashMap * serializable);
+
private:
char mDelimiter;
String * mPrefix;
diff --git a/src/core/imap/MCIMAPSearchExpression.cpp b/src/core/imap/MCIMAPSearchExpression.cpp
index b3467e59..8d6b1f0b 100644
--- a/src/core/imap/MCIMAPSearchExpression.cpp
+++ b/src/core/imap/MCIMAPSearchExpression.cpp
@@ -9,6 +9,7 @@ void IMAPSearchExpression::init()
mValue = NULL;
mLongNumber = 0;
mUids = NULL;
+ mNumbers = NULL;
mLeftExpression = NULL;
mRightExpression = NULL;
}
@@ -26,6 +27,7 @@ IMAPSearchExpression::IMAPSearchExpression(IMAPSearchExpression * other)
MC_SAFE_REPLACE_COPY(String, mHeader, other->mHeader);
MC_SAFE_REPLACE_COPY(String, mValue, other->mValue);
MC_SAFE_REPLACE_COPY(IndexSet, mUids, other->mUids);
+ MC_SAFE_REPLACE_COPY(IndexSet, mNumbers, other->mNumbers);
MC_SAFE_REPLACE_COPY(IMAPSearchExpression, mLeftExpression, other->mLeftExpression);
MC_SAFE_REPLACE_COPY(IMAPSearchExpression, mRightExpression, other->mRightExpression);
}
@@ -35,6 +37,7 @@ IMAPSearchExpression::~IMAPSearchExpression()
MC_SAFE_RELEASE(mHeader);
MC_SAFE_RELEASE(mValue);
MC_SAFE_RELEASE(mUids);
+ MC_SAFE_RELEASE(mNumbers);
MC_SAFE_RELEASE(mLeftExpression);
MC_SAFE_RELEASE(mRightExpression);
}
@@ -68,6 +71,9 @@ String * IMAPSearchExpression::description()
case IMAPSearchKindUIDs:
return String::stringWithUTF8Format("<%s:%p UIDs %s>", MCUTF8(className()), this,
MCUTF8(mUids->description()));
+ case IMAPSearchKindNumbers:
+ return String::stringWithUTF8Format("<%s:%p Numbers %s>", MCUTF8(className()), this,
+ MCUTF8(mNumbers->description()));
case IMAPSearchKindContent:
return String::stringWithUTF8Format("<%s:%p Content %s>", MCUTF8(className()), this,
MCUTF8(mValue->description()));
@@ -170,6 +176,13 @@ IMAPSearchExpression * IMAPSearchExpression::searchUIDs(IndexSet * uids)
return (IMAPSearchExpression *) expr->autorelease();
}
+IMAPSearchExpression * IMAPSearchExpression::searchNumbers(IndexSet * numbers)
+{
+ IMAPSearchExpression * expr = new IMAPSearchExpression();
+ expr->mKind = IMAPSearchKindNumbers;
+ MC_SAFE_REPLACE_COPY(IndexSet, expr->mNumbers, numbers);
+ return (IMAPSearchExpression *) expr->autorelease();
+}
IMAPSearchExpression * IMAPSearchExpression::searchHeader(String * header, String * value)
{
@@ -393,6 +406,11 @@ IndexSet * IMAPSearchExpression::uids()
return mUids;
}
+IndexSet * IMAPSearchExpression::numbers()
+{
+ return mNumbers;
+}
+
IMAPSearchExpression * IMAPSearchExpression::leftExpression()
{
return mLeftExpression;
diff --git a/src/core/imap/MCIMAPSearchExpression.h b/src/core/imap/MCIMAPSearchExpression.h
index 6f1f4ea0..182f3013 100644
--- a/src/core/imap/MCIMAPSearchExpression.h
+++ b/src/core/imap/MCIMAPSearchExpression.h
@@ -20,6 +20,7 @@ namespace mailcore {
virtual uint64_t longNumber();
virtual time_t date();
virtual IndexSet * uids();
+ virtual IndexSet * numbers();
virtual IMAPSearchExpression * leftExpression();
@@ -36,6 +37,7 @@ namespace mailcore {
static IMAPSearchExpression * searchBody(String * value);
static IMAPSearchExpression * searchHeader(String * header, String * value);
static IMAPSearchExpression * searchUIDs(IndexSet * uids);
+ static IMAPSearchExpression * searchNumbers(IndexSet * numbers);
static IMAPSearchExpression * searchRead();
static IMAPSearchExpression * searchUnread();
static IMAPSearchExpression * searchFlagged();
@@ -73,6 +75,7 @@ namespace mailcore {
String * mValue;
uint64_t mLongNumber;
IndexSet * mUids;
+ IndexSet * mNumbers;
IMAPSearchExpression * mLeftExpression;
IMAPSearchExpression * mRightExpression;
void init();
diff --git a/src/core/imap/MCIMAPSession.cpp b/src/core/imap/MCIMAPSession.cpp
index 854bddec..93427d8d 100755
--- a/src/core/imap/MCIMAPSession.cpp
+++ b/src/core/imap/MCIMAPSession.cpp
@@ -627,6 +627,10 @@ void IMAPSession::connect(ErrorCode * pError)
if (mImap->imap_response != NULL) {
MC_SAFE_REPLACE_RETAIN(String, mWelcomeString, String::stringWithUTF8Characters(mImap->imap_response));
mYahooServer = (mWelcomeString->locationOfString(MCSTR("yahoo.com")) != -1);
+#ifdef LIBETPAN_HAS_MAILIMAP_163_WORKAROUND
+ if(mWelcomeString->locationOfString(MCSTR("Coremail System IMap Server Ready")) != -1)
+ mailimap_set_163_workaround_enabled(mImap, 1);
+#endif
}
mState = STATE_CONNECTED;
@@ -789,7 +793,12 @@ void IMAPSession::login(ErrorCode * pError)
case AuthTypeXOAuth2:
case AuthTypeXOAuth2Outlook:
- r = mailimap_oauth2_authenticate(mImap, utf8username, MCUTF8(mOAuth2Token));
+ if (mOAuth2Token == NULL) {
+ r = MAILIMAP_ERROR_STREAM;
+ }
+ else {
+ r = mailimap_oauth2_authenticate(mImap, utf8username, MCUTF8(mOAuth2Token));
+ }
break;
}
if (r == MAILIMAP_ERROR_STREAM) {
@@ -987,6 +996,33 @@ static uint64_t get_mod_sequence_value(mailimap * session)
return mod_sequence_value;
}
+String * IMAPSession::customCommand(String * command, ErrorCode * pError)
+{
+ int r;
+
+ loginIfNeeded(pError);
+ if (* pError != ErrorNone)
+ return NULL;
+
+ r = mailimap_custom_command(mImap, MCUTF8(command));
+ if (r == MAILIMAP_ERROR_STREAM) {
+ mShouldDisconnect = true;
+ * pError = ErrorConnection;
+ return NULL;
+ }
+ else if (r == MAILIMAP_ERROR_PARSE) {
+ * pError = ErrorParse;
+ return NULL;
+ }
+ else if (hasError(r)) {
+ * pError = ErrorCustomCommand;
+ return NULL;
+ }
+
+ String *response = String::stringWithUTF8Characters(mImap->imap_response);
+ return response;
+}
+
void IMAPSession::select(String * folder, ErrorCode * pError)
{
int r;
@@ -1088,14 +1124,17 @@ IMAPFolderStatus * IMAPSession::folderStatus(String * folder, ErrorCode * pError
mShouldDisconnect = true;
* pError = ErrorConnection;
MCLog("status error : %s %i", MCUTF8DESC(this), * pError);
+ mailimap_status_att_list_free(status_att_list);
return fs;
}
else if (r == MAILIMAP_ERROR_PARSE) {
* pError = ErrorParse;
+ mailimap_status_att_list_free(status_att_list);
return fs;
}
else if (hasError(r)) {
* pError = ErrorNonExistantFolder;
+ mailimap_status_att_list_free(status_att_list);
return fs;
}
@@ -1141,7 +1180,7 @@ IMAPFolderStatus * IMAPSession::folderStatus(String * folder, ErrorCode * pError
}
mailimap_status_att_list_free(status_att_list);
-
+ mailimap_mailbox_data_status_free(status);
return fs;
}
@@ -1574,7 +1613,6 @@ void IMAPSession::appendMessageWithCustomFlagsAndDate(String * folder, Data * me
mProgressCallback = progressCallback;
bodyProgress(0, messageData->length());
- flag_list = NULL;
flag_list = flags_to_lep(flags);
if (customFlags != NULL) {
for (unsigned int i = 0 ; i < customFlags->count() ; i ++) {
@@ -2791,6 +2829,10 @@ static struct mailimap_search_key * searchKeyFromSearchExpression(IMAPSearchExpr
{
return mailimap_search_key_new_uid(setFromIndexSet(expression->uids()));
}
+ case IMAPSearchKindNumbers:
+ {
+ return mailimap_search_key_new_set(setFromIndexSet(expression->numbers()));
+ }
case IMAPSearchKindHeader:
{
return mailimap_search_key_new_header(strdup(expression->header()->UTF8Characters()), strdup(expression->value()->UTF8Characters()));
diff --git a/src/core/imap/MCIMAPSession.h b/src/core/imap/MCIMAPSession.h
index d0a310b7..5ee6bc1c 100755
--- a/src/core/imap/MCIMAPSession.h
+++ b/src/core/imap/MCIMAPSession.h
@@ -107,6 +107,7 @@ namespace mailcore {
IndexSet * numbers,
IMAPProgressCallback * progressCallback,
Array * extraHeaders, ErrorCode * pError);
+ virtual String * customCommand(String * command, ErrorCode * pError);
virtual Data * fetchMessageByUID(String * folder, uint32_t uid,
IMAPProgressCallback * progressCallback, ErrorCode * pError);
@@ -177,7 +178,7 @@ namespace mailcore {
virtual bool isCompressionEnabled();
virtual bool allowsNewPermanentFlags();
- virtual String * gmailUserDisplayName();
+ virtual String * gmailUserDisplayName() DEPRECATED_ATTRIBUTE;
virtual void setConnectionLogger(ConnectionLogger * logger);
virtual ConnectionLogger * connectionLogger();
diff --git a/src/core/nntp/MCNNTPGroupInfo.cpp b/src/core/nntp/MCNNTPGroupInfo.cpp
index 787967f3..8ebe08bc 100644
--- a/src/core/nntp/MCNNTPGroupInfo.cpp
+++ b/src/core/nntp/MCNNTPGroupInfo.cpp
@@ -13,10 +13,12 @@ using namespace mailcore;
void NNTPGroupInfo::init()
{
mMessageCount = 0;
+ mName = NULL;
}
NNTPGroupInfo::NNTPGroupInfo()
{
+ MC_SAFE_RELEASE(mName);
init();
}
diff --git a/src/core/nntp/MCNNTPSession.cpp b/src/core/nntp/MCNNTPSession.cpp
index f6427006..933f10f2 100644
--- a/src/core/nntp/MCNNTPSession.cpp
+++ b/src/core/nntp/MCNNTPSession.cpp
@@ -464,7 +464,7 @@ Data * NNTPSession::fetchArticle(String *groupName, unsigned int index, NNTPProg
return result;
}
-Data * NNTPSession::fetchArticleByMessageID(String * groupName, String * messageID, ErrorCode * pError)
+Data * NNTPSession::fetchArticleByMessageID(String * messageID, ErrorCode * pError)
{
int r;
char * msgID;
@@ -473,11 +473,6 @@ Data * NNTPSession::fetchArticleByMessageID(String * groupName, String * message
MCLog("fetch article at message-id %s", messageID->UTF8Characters());
- selectGroup(groupName, pError);
- if (* pError != ErrorNone) {
- return NULL;
- }
-
msgID = strdup(messageID->UTF8Characters());
r = newsnntp_article_by_message_id(mNNTP, msgID, &content, &content_len);
diff --git a/src/core/nntp/MCNNTPSession.h b/src/core/nntp/MCNNTPSession.h
index dc2316ff..ec0080ed 100644
--- a/src/core/nntp/MCNNTPSession.h
+++ b/src/core/nntp/MCNNTPSession.h
@@ -53,7 +53,7 @@ namespace mailcore {
virtual IndexSet * fetchAllArticles(String * groupname, ErrorCode * pError);
virtual Data * fetchArticle(String *groupName, unsigned int index, NNTPProgressCallback * callback, ErrorCode * pError);
- virtual Data * fetchArticleByMessageID(String * groupname, String * messageID, ErrorCode * pError);
+ virtual Data * fetchArticleByMessageID(String * messageID, ErrorCode * pError);
virtual time_t fetchServerDate(ErrorCode * pError);
diff --git a/src/core/pop/MCPOPSession.cpp b/src/core/pop/MCPOPSession.cpp
index 8415a081..ab8975a6 100644
--- a/src/core/pop/MCPOPSession.cpp
+++ b/src/core/pop/MCPOPSession.cpp
@@ -174,6 +174,7 @@ static void logger(mailpop3 * pop3, int log_type, const char * buffer, size_t si
void POPSession::setup()
{
mPop = mailpop3_new(0, NULL);
+ mailpop3_set_timeout(mPop, timeout());
mailpop3_set_progress_callback(mPop, POPSession::body_progress, this);
mailpop3_set_logger(mPop, logger, this);
}
diff --git a/src/core/provider/MCAccountValidator.cpp b/src/core/provider/MCAccountValidator.cpp
new file mode 100644
index 00000000..59538c72
--- /dev/null
+++ b/src/core/provider/MCAccountValidator.cpp
@@ -0,0 +1,497 @@
+//
+// MCAccountValidator.cpp
+// mailcore2
+//
+// Created by Christopher Hockley on 22/01/15.
+// Copyright (c) 2015 MailCore. All rights reserved.
+//
+
+#include "MCAccountValidator.h"
+#include "MCMailProvider.h"
+#include "MCMailProvidersManager.h"
+#include "MCIMAPAsyncSession.h"
+#include "MCPOPAsyncSession.h"
+#include "MCSMTPAsyncSession.h"
+#include "MCNetService.h"
+#include "MCAddress.h"
+#include "MCIMAPOperation.h"
+#include "MCPOPOperation.h"
+#include "MCSMTPOperation.h"
+#include "MCMXRecordResolverOperation.h"
+
+using namespace mailcore;
+
+/* this is the service being tested */
+
+enum {
+ SERVICE_IMAP, /* IMAP service */
+ SERVICE_POP, /* POP service */
+ SERVICE_SMTP, /* SMTP service */
+};
+
+void AccountValidator::init()
+{
+ mEmail = NULL;
+ mUsername = NULL;
+ mPassword = NULL;
+ mOAuth2Token = NULL;
+
+ mImapServices = new Array();
+ mSmtpServices = new Array();
+ mPopServices = new Array();
+
+ mIdentifier = NULL;
+ mImapServer = NULL;
+ mPopServer = NULL;
+ mSmtpServer = NULL;
+ mImapError = ErrorNone;
+ mPopError = ErrorNone;
+ mSmtpError = ErrorNone;
+
+ mCurrentServiceIndex = 0;
+ mCurrentServiceTested = 0;
+
+ mProvider = NULL;
+
+ mOperation = NULL;
+ mQueue = NULL;
+ mResolveMX = NULL;
+
+ mImapSession = NULL;
+ mPopSession = NULL;
+ mSmtpSession = NULL;
+
+ mImapEnabled = false;
+ mPopEnabled = false;
+ mSmtpEnabled = false;
+}
+
+AccountValidator::AccountValidator()
+{
+ init();
+}
+
+AccountValidator::~AccountValidator()
+{
+ MC_SAFE_RELEASE(mEmail);
+ MC_SAFE_RELEASE(mUsername);
+ MC_SAFE_RELEASE(mPassword);
+ MC_SAFE_RELEASE(mOAuth2Token);
+ MC_SAFE_RELEASE(mImapServices);
+ MC_SAFE_RELEASE(mSmtpServices);
+ MC_SAFE_RELEASE(mPopServices);
+ MC_SAFE_RELEASE(mIdentifier);
+ MC_SAFE_RELEASE(mProvider);
+ MC_SAFE_RELEASE(mOperation);
+ MC_SAFE_RELEASE(mQueue);
+ MC_SAFE_RELEASE(mResolveMX);
+ MC_SAFE_RELEASE(mImapSession);
+ MC_SAFE_RELEASE(mPopSession);
+ MC_SAFE_RELEASE(mSmtpSession);
+}
+
+void AccountValidator::start()
+{
+ if (mEmail == NULL) {
+ if (mUsername == NULL) {
+ return;
+ }
+ else {
+ mEmail = mUsername;
+ MC_SAFE_RETAIN(mEmail);
+ }
+ }
+ else if (mUsername == NULL){
+ mUsername = mEmail;
+ MC_SAFE_RETAIN(mUsername);
+ }
+
+ MC_SAFE_RELEASE(mProvider);
+ mProvider = MailProvidersManager::sharedManager()->providerForEmail(mEmail);
+ if (mProvider != NULL) {
+ MC_SAFE_REPLACE_COPY(String, mIdentifier, mProvider->identifier());
+ }
+ MC_SAFE_RETAIN(mProvider);
+
+ if (mProvider == NULL) {
+ resolveMX();
+ }
+ else{
+ startCheckingHosts();
+ }
+}
+
+void AccountValidator::cancel()
+{
+ if(mOperation != NULL)
+ mOperation->cancel();
+
+ if(mResolveMX != NULL)
+ mResolveMX->cancel();
+
+ if (mQueue != NULL)
+ mQueue->cancelAllOperations();
+
+ MC_SAFE_RELEASE(mOperation);
+ MC_SAFE_RELEASE(mResolveMX);
+ MC_SAFE_RELEASE(mQueue);
+ MC_SAFE_RELEASE(mImapSession);
+ MC_SAFE_RELEASE(mPopSession);
+ MC_SAFE_RELEASE(mSmtpSession);
+
+ Operation::cancel();
+}
+
+void AccountValidator::operationFinished(Operation * op)
+{
+ if (op == mResolveMX) {
+ resolveMXDone();
+ }
+ else {
+ checkNextHostDone();
+ }
+}
+
+void AccountValidator::resolveMX()
+{
+ Array * components;
+ String * domain;
+
+ components = mUsername->componentsSeparatedByString(MCSTR("@"));
+ if (components->count() >= 2) {
+ domain = (String *) components->lastObject();
+ mResolveMX = new MXRecordResolverOperation();
+ mResolveMX->setHostname(domain);
+ mResolveMX->setCallback((OperationCallback *)this);
+
+ mQueue = new OperationQueue();
+ mQueue->addOperation(mResolveMX);
+ }
+ else {
+ mImapError = ErrorNoValidServerFound;
+ mPopError = ErrorNoValidServerFound;
+ mSmtpError = ErrorNoValidServerFound;
+
+ callback()->operationFinished(this);
+ }
+}
+
+void AccountValidator::resolveMXDone()
+{
+ Array * mxRecords = mResolveMX->mxRecords();
+
+ mc_foreacharray(String, mxRecord, mxRecords) {
+ MailProvider * provider = MailProvidersManager::sharedManager()->providerForMX(mxRecord);
+ if (provider != NULL){
+ MC_SAFE_REPLACE_RETAIN(MailProvider, mProvider, provider);
+ if (mProvider != NULL) {
+ MC_SAFE_REPLACE_COPY(String, mIdentifier, mProvider->identifier());
+ }
+ break;
+ }
+ }
+
+ startCheckingHosts();
+}
+
+void AccountValidator::setupServices()
+{
+ MC_SAFE_RELEASE(mImapServices);
+ mImapServices = mProvider->imapServices();
+ MC_SAFE_RETAIN(mImapServices);
+
+ MC_SAFE_RELEASE(mPopServices);
+ mPopServices = mProvider->popServices();
+ MC_SAFE_RETAIN(mPopServices);
+
+ MC_SAFE_RELEASE(mSmtpServices);
+ mSmtpServices = mProvider->smtpServices();
+ MC_SAFE_RETAIN(mSmtpServices);
+}
+
+void AccountValidator::startCheckingHosts()
+{
+ if (mProvider != NULL) {
+ setupServices();
+ }
+
+ if (mImapServices->count() == 0)
+ mImapError = ErrorNoValidServerFound;
+
+ if (mPopServices->count() == 0)
+ mPopError = ErrorNoValidServerFound;
+
+ if (mSmtpServices->count() == 0)
+ mSmtpError = ErrorNoValidServerFound;
+
+ checkNextHost();
+}
+
+/**
+ Each service(IMAP/POP/SMTP) is tested one after the other.
+ For each service we test each server details (NetService),
+ Until either:
+ we find on that works and returns ErrorNone in checkNextHostDone().
+ we have gone trough the Array of NetService for that service and checkNextHost() is then called for the next service.
+ */
+void AccountValidator::checkNextHost()
+{
+ if (mCurrentServiceTested == SERVICE_IMAP) {
+ if (mImapEnabled && (mCurrentServiceIndex < mImapServices->count())) {
+ mImapSession = new IMAPAsyncSession();
+ mImapSession->setUsername(mUsername);
+ mImapSession->setPassword(mPassword);
+ if (mOAuth2Token != NULL) {
+ mImapSession->setOAuth2Token(mOAuth2Token);
+ mImapSession->setAuthType(AuthTypeXOAuth2);
+ }
+
+ mImapServer = (NetService *) mImapServices->objectAtIndex(mCurrentServiceIndex);
+ mImapSession->setHostname(mImapServer->hostname());
+ mImapSession->setPort(mImapServer->port());
+ mImapSession->setConnectionType(mImapServer->connectionType());
+
+ mOperation = (IMAPOperation *)mImapSession->checkAccountOperation();
+ mOperation->retain();
+ mOperation->setCallback(this);
+ mOperation->start();
+ }
+ else if (mImapEnabled && (mImapServices->count() > 0)) {
+ mImapServer = NULL;
+ callback()->operationFinished(this);
+ }
+ else {
+ mCurrentServiceTested ++;
+ mCurrentServiceIndex = 0;
+ checkNextHost();
+ }
+ }
+ else if (mCurrentServiceTested == SERVICE_POP){
+ if (mPopEnabled && (mCurrentServiceIndex < mPopServices->count())) {
+ mPopSession = new POPAsyncSession();
+ mPopSession->setUsername(mUsername);
+ mPopSession->setPassword(mPassword);
+
+ mPopServer = (NetService *) mPopServices->objectAtIndex(mCurrentServiceIndex);
+ mPopSession->setHostname(mPopServer->hostname());
+ mPopSession->setPort(mPopServer->port());
+ mPopSession->setConnectionType(mPopServer->connectionType());
+
+ mOperation = mPopSession->checkAccountOperation();
+ mOperation->retain();
+ mOperation->setCallback(this);
+ mOperation->start();
+ }
+ else if (mPopEnabled && (mPopServices->count() > 0)) {
+ mPopServer = NULL;
+ callback()->operationFinished(this);
+ }
+ else {
+ mCurrentServiceTested ++;
+ mCurrentServiceIndex = 0;
+ checkNextHost();
+ }
+ }
+ else if (mCurrentServiceTested == SERVICE_SMTP){
+ if (mSmtpEnabled && (mCurrentServiceIndex < mSmtpServices->count())) {
+ mSmtpSession = new SMTPAsyncSession();
+ mSmtpSession->setUsername(mUsername);
+ mSmtpSession->setPassword(mPassword);
+ if (mOAuth2Token != NULL) {
+ mSmtpSession->setOAuth2Token(mOAuth2Token);
+ mSmtpSession->setAuthType(AuthTypeXOAuth2);
+ }
+
+ mSmtpServer = (NetService *) mSmtpServices->objectAtIndex(mCurrentServiceIndex);
+ mSmtpSession->setHostname(mSmtpServer->hostname());
+ mSmtpSession->setPort(mSmtpServer->port());
+ mSmtpSession->setConnectionType(mSmtpServer->connectionType());
+
+ mOperation = mSmtpSession->checkAccountOperation(Address::addressWithMailbox(mEmail));
+ mOperation->retain();
+ mOperation->setCallback(this);
+ mOperation->start();
+ }
+ else if (mSmtpEnabled && (mSmtpServices->count() > 0)) {
+ mSmtpServer = NULL;
+ callback()->operationFinished(this);
+ }
+ else {
+ mCurrentServiceTested ++;
+ mCurrentServiceIndex = 0;
+ checkNextHost();
+ }
+ }
+ else {
+ callback()->operationFinished(this);
+ }
+}
+
+void AccountValidator::checkNextHostDone()
+{
+ ErrorCode error = ErrorNone;
+
+ if (mCurrentServiceTested == SERVICE_IMAP) {
+ mImapError = ((IMAPOperation *)mOperation)->error();
+ error = mImapError;
+ MC_SAFE_RELEASE(mImapSession);
+ }
+ else if (mCurrentServiceTested == SERVICE_POP) {
+ mPopError = ((POPOperation *)mOperation)->error();
+ error = mPopError;
+ MC_SAFE_RELEASE(mPopSession);
+ }
+ else if (mCurrentServiceTested == SERVICE_SMTP) {
+ mSmtpError = ((SMTPOperation *)mOperation)->error();
+ error = mSmtpError;
+ MC_SAFE_RELEASE(mSmtpSession);
+ }
+
+ MC_SAFE_RELEASE(mOperation);
+
+ if (error == ErrorNone) {
+ mCurrentServiceIndex = 0;
+ mCurrentServiceTested ++;
+ }
+ else {
+ mCurrentServiceIndex ++;
+ }
+
+ checkNextHost();
+}
+
+void AccountValidator::setEmail(String * email)
+{
+ MC_SAFE_REPLACE_COPY(String, mEmail, email);
+}
+
+String * AccountValidator::email()
+{
+ return mEmail;
+}
+
+void AccountValidator::setUsername(String * username)
+{
+ MC_SAFE_REPLACE_COPY(String, mUsername, username);
+}
+
+String * AccountValidator::username()
+{
+ return mUsername;
+}
+
+void AccountValidator::setPassword(String * password)
+{
+ MC_SAFE_REPLACE_COPY(String, mPassword, password);
+}
+
+String * AccountValidator::password()
+{
+ return mPassword;
+}
+
+void AccountValidator::setOAuth2Token(String * OAuth2Token)
+{
+ MC_SAFE_REPLACE_COPY(String, mOAuth2Token, OAuth2Token);
+}
+
+String * AccountValidator::OAuth2Token()
+{
+ return mOAuth2Token;
+}
+
+void AccountValidator::setImapEnabled(bool enabled)
+{
+ mImapEnabled = enabled;
+}
+
+bool AccountValidator::isImapEnabled()
+{
+ return mImapEnabled;
+}
+
+void AccountValidator::setPopEnabled(bool enabled)
+{
+ mPopEnabled = enabled;
+}
+
+bool AccountValidator::isPopEnabled()
+{
+ return mPopEnabled;
+}
+
+
+void AccountValidator::setSmtpEnabled(bool enabled)
+{
+ mSmtpEnabled = enabled;
+}
+
+bool AccountValidator::isSmtpEnabled()
+{
+ return mSmtpEnabled;
+}
+
+void AccountValidator::setImapServices(Array * imapServices)
+{
+ MC_SAFE_REPLACE_COPY(Array, mImapServices, imapServices);
+}
+
+Array * AccountValidator::imapServices()
+{
+ return mImapServices;
+}
+
+void AccountValidator::setSmtpServices(Array * smtpServices)
+{
+ MC_SAFE_REPLACE_COPY(Array, mSmtpServices, smtpServices);
+}
+
+Array * AccountValidator::smtpServices()
+{
+ return mSmtpServices;
+}
+
+void AccountValidator::setPopServices(Array * popServices)
+{
+ MC_SAFE_REPLACE_COPY(Array, mPopServices, popServices);
+}
+
+Array * AccountValidator::popServices()
+{
+ return mPopServices;
+}
+
+String * AccountValidator::identifier()
+{
+ return mIdentifier;
+}
+
+NetService * AccountValidator::imapServer()
+{
+ return mImapServer;
+}
+
+NetService * AccountValidator::smtpServer()
+{
+ return mSmtpServer;
+}
+
+NetService * AccountValidator::popServer()
+{
+ return mPopServer;
+}
+
+ErrorCode AccountValidator::imapError()
+{
+ return mImapError;
+}
+
+ErrorCode AccountValidator::popError()
+{
+ return mPopError;
+}
+
+ErrorCode AccountValidator::smtpError()
+{
+ return mSmtpError;
+}
diff --git a/src/core/provider/MCAccountValidator.h b/src/core/provider/MCAccountValidator.h
new file mode 100644
index 00000000..436317cf
--- /dev/null
+++ b/src/core/provider/MCAccountValidator.h
@@ -0,0 +1,119 @@
+//
+// MCAccountValidator.h
+// mailcore2
+//
+// Created by Christopher Hockley on 22/01/15.
+// Copyright (c) 2015 MailCore. All rights reserved.
+//
+
+#ifndef MAILCORE_MCACCOUNTVALIDATOR_H
+
+#define MAILCORE_MCACCOUNTVALIDATOR_H
+
+#include <MailCore/MCBaseTypes.h>
+
+#ifdef __cplusplus
+
+namespace mailcore {
+
+ class NetService;
+ class MailProvider;
+ class MXRecordResolverOperation;
+ class IMAPAsyncSession;
+ class POPAsyncSession;
+ class SMTPAsyncSession;
+
+ class MAILCORE_EXPORT AccountValidator : public Operation, public OperationCallback {
+ public:
+ AccountValidator();
+ virtual ~AccountValidator();
+
+ virtual void setEmail(String * email);
+ virtual String * email(); /* for SMTP */
+ virtual void setUsername(String * username);
+ virtual String * username();
+ virtual void setPassword(String * password);
+ virtual String * password();
+ virtual void setOAuth2Token(String * OAuth2Token);
+ virtual String * OAuth2Token();
+
+ virtual void setImapEnabled(bool enabled);
+ virtual bool isImapEnabled();
+
+ virtual void setPopEnabled(bool enabled);
+ virtual bool isPopEnabled();
+
+ virtual void setSmtpEnabled(bool enabled);
+ virtual bool isSmtpEnabled();
+
+ virtual void setImapServices(Array * imapServices);
+ virtual Array * /* NetService */ imapServices();
+ virtual void setSmtpServices(Array * smtpServices);
+ virtual Array * /* NetService */ smtpServices();
+ virtual void setPopServices(Array * popServices);
+ virtual Array * /* NetService */ popServices();
+
+ // result
+ virtual String * identifier();
+ virtual NetService * imapServer();
+ virtual NetService * popServer();
+ virtual NetService * smtpServer();
+ virtual ErrorCode imapError();
+ virtual ErrorCode popError();
+ virtual ErrorCode smtpError();
+
+ virtual void start();
+ virtual void cancel();
+
+ private:
+ String * mEmail; /* for SMTP */
+ String * mUsername;
+ String * mPassword;
+ String * mOAuth2Token;
+
+ Array * /* NetService */ mImapServices;
+ Array * /* NetService */ mSmtpServices;
+ Array * /* NetService */ mPopServices;
+
+ // result
+ String * mIdentifier;
+ NetService * mImapServer;
+ NetService * mPopServer;
+ NetService * mSmtpServer;
+ ErrorCode mImapError;
+ ErrorCode mPopError;
+ ErrorCode mSmtpError;
+
+ MailProvider * mProvider;
+
+ //indexs for services being tested
+ int mCurrentServiceIndex;
+ int mCurrentServiceTested;
+
+ Operation * mOperation;
+ virtual void operationFinished(Operation * op);
+
+ OperationQueue * mQueue;
+ MXRecordResolverOperation * mResolveMX;
+
+ IMAPAsyncSession * mImapSession;
+ POPAsyncSession * mPopSession;
+ SMTPAsyncSession * mSmtpSession;
+
+ bool mImapEnabled;
+ bool mPopEnabled;
+ bool mSmtpEnabled;
+
+ void init();
+ void setupServices();
+ void resolveMX();
+ void resolveMXDone();
+ void startCheckingHosts();
+ void checkNextHost();
+ void checkNextHostDone();
+ };
+}
+
+#endif
+
+#endif
diff --git a/src/core/provider/MCMXRecordResolverOperation.cpp b/src/core/provider/MCMXRecordResolverOperation.cpp
new file mode 100644
index 00000000..ac6c8219
--- /dev/null
+++ b/src/core/provider/MCMXRecordResolverOperation.cpp
@@ -0,0 +1,75 @@
+//
+// MCFetchAsyncMXRecord.cpp
+// mailcore2
+//
+// Created by Christopher Hockley on 29/01/15.
+// Copyright (c) 2015 MailCore. All rights reserved.
+//
+
+#include "MCMXRecordResolverOperation.h"
+
+#if !defined(ANDROID) && !defined(__ANDROID__)
+#include <arpa/inet.h>
+#include <resolv.h>
+#endif
+
+using namespace mailcore;
+
+MXRecordResolverOperation::MXRecordResolverOperation()
+{
+ mHostname = NULL;
+ mMXRecords = NULL;
+}
+
+MXRecordResolverOperation::~MXRecordResolverOperation()
+{
+ MC_SAFE_RELEASE(mMXRecords);
+ MC_SAFE_RELEASE(mHostname);
+}
+
+void MXRecordResolverOperation::setHostname(String * hostname)
+{
+ MC_SAFE_REPLACE_COPY(String, mHostname, hostname);
+}
+
+String * MXRecordResolverOperation::hostname()
+{
+ return mHostname;
+}
+
+Array * MXRecordResolverOperation::mxRecords()
+{
+ return mMXRecords;
+}
+
+void MXRecordResolverOperation::main()
+{
+ mMXRecords = new Array();
+#if !defined(ANDROID) && !defined(__ANDROID__)
+ unsigned char response[NS_PACKETSZ];
+ ns_msg handle;
+ ns_rr rr;
+ int len;
+ char dispbuf[4096];
+
+ if (((len = res_search(MCUTF8(mHostname), ns_c_in, ns_t_mx, response, sizeof(response))) >= 0) and
+ (ns_initparse(response, len, &handle) >= 0) and
+ (ns_msg_count(handle, ns_s_an) >= 0)) {
+
+ for (int ns_index = 0; ns_index < len; ns_index++) {
+ if (ns_parserr(&handle, ns_s_an, ns_index, &rr)) {
+ /* WARN: ns_parserr failed */
+ continue;
+ }
+ ns_sprintrr (&handle, &rr, NULL, NULL, dispbuf, sizeof (dispbuf));
+ if (ns_rr_class(rr) == ns_c_in and ns_rr_type(rr) == ns_t_mx) {
+ char mxname[4096];
+ dn_expand(ns_msg_base(handle), ns_msg_base(handle) + ns_msg_size(handle), ns_rr_rdata(rr) + NS_INT16SZ, mxname, sizeof(mxname));
+ String * str = String::stringWithUTF8Characters(mxname);
+ mMXRecords->addObject(str);
+ }
+ }
+ }
+#endif
+}
+
diff --git a/src/core/provider/MCMXRecordResolverOperation.h b/src/core/provider/MCMXRecordResolverOperation.h
new file mode 100644
index 00000000..7d8a6fc8
--- /dev/null
+++ b/src/core/provider/MCMXRecordResolverOperation.h
@@ -0,0 +1,41 @@
+//
+// ResolveProviderUsingMXRecordAsync.h
+// mailcore2
+//
+// Created by Christopher Hockley on 29/01/15.
+// Copyright (c) 2015 MailCore. All rights reserved.
+//
+
+#ifndef MAILCORE_MCFETCHASYNCMXRECORD_H
+
+#define MAILCORE_MCFETCHASYNCMXRECORD_H
+
+#include <MailCore/MCBaseTypes.h>
+#include <MailCore/MCMessageConstants.h>
+
+#ifdef __cplusplus
+
+namespace mailcore {
+
+ class MAILCORE_EXPORT MXRecordResolverOperation : public Operation {
+ public:
+ MXRecordResolverOperation();
+ virtual ~MXRecordResolverOperation();
+
+ virtual void setHostname(String * hostname);
+ virtual String * hostname();
+
+ virtual Array * mxRecords();
+
+ public: // subclass behavior
+ virtual void main();
+
+ private:
+ Array * mMXRecords;
+ String * mHostname;
+ };
+}
+
+#endif
+
+#endif
diff --git a/src/core/provider/MCMailProvider.cpp b/src/core/provider/MCMailProvider.cpp
index 1055d4fa..99fc4deb 100644
--- a/src/core/provider/MCMailProvider.cpp
+++ b/src/core/provider/MCMailProvider.cpp
@@ -161,30 +161,42 @@ bool MailProvider::matchEmail(String * email)
domain = (String *) components->lastObject();
+ bool matchExcludeDomain = false;
mc_foreacharray(String, exclude, mDomainExclude) {
if (matchDomain(exclude, domain)){
- return false;
+ matchExcludeDomain = true;;
+ break;
}
}
-
+ if (matchExcludeDomain) {
+ return false;
+ }
+
+ bool matchValidDomain = false;
mc_foreacharray(String, match, mDomainMatch) {
if (matchDomain(match, domain)){
- return true;
+ matchValidDomain = true;
+ break;
}
}
-
+ if (matchValidDomain) {
+ return true;
+ }
+
return false;
}
bool MailProvider::matchMX(String * hostname)
{
+ bool result = false;
mc_foreacharray(String, match, mMxMatch) {
if (matchDomain(match, hostname)){
- return true;
+ result = true;
+ break;
}
}
-
- return false;
+
+ return result;
}
bool MailProvider::matchDomain(String * match, String * domain)
@@ -272,6 +284,7 @@ String * MailProvider::importantFolderPath()
bool MailProvider::isMainFolder(String * folderPath, String * prefix)
{
+ bool result = false;
mc_foreachhashmapValue(String, path, mMailboxPaths) {
String * fullPath;
@@ -282,11 +295,13 @@ bool MailProvider::isMainFolder(String * folderPath, String * prefix)
fullPath = path;
}
- if (fullPath->isEqual(folderPath))
- return true;
+ if (fullPath->isEqual(folderPath)) {
+ result = true;
+ break;
+ }
}
- return false;
+ return result;
}
String * MailProvider::description()
diff --git a/src/core/provider/MCMailProvidersManager.cpp b/src/core/provider/MCMailProvidersManager.cpp
index 0d7938e4..a5f7891a 100644
--- a/src/core/provider/MCMailProvidersManager.cpp
+++ b/src/core/provider/MCMailProvidersManager.cpp
@@ -30,22 +30,28 @@ MailProvidersManager * MailProvidersManager::sharedManager()
MailProvider * MailProvidersManager::providerForEmail(String * email)
{
+ MailProvider * result = NULL;
mc_foreachhashmapValue(MailProvider, provider, mProviders) {
- if (provider->matchEmail(email))
- return provider;
+ if (provider->matchEmail(email)) {
+ result = provider;
+ break;
+ }
}
- return NULL;
+ return result;
}
MailProvider * MailProvidersManager::providerForMX(String * hostname)
{
+ MailProvider * result = NULL;
mc_foreachhashmapValue(MailProvider, provider, mProviders) {
- if (provider->matchMX(hostname))
- return provider;
+ if (provider->matchMX(hostname)) {
+ result = provider;
+ break;
+ }
}
-
- return NULL;
+
+ return result;
}
MailProvider * MailProvidersManager::providerForIdentifier(String * identifier)
diff --git a/src/core/provider/MCMailProvidersManager.h b/src/core/provider/MCMailProvidersManager.h
index 42d1d3bc..774c2d30 100644
--- a/src/core/provider/MCMailProvidersManager.h
+++ b/src/core/provider/MCMailProvidersManager.h
@@ -40,4 +40,4 @@ namespace mailcore {
#endif
-#endif \ No newline at end of file
+#endif
diff --git a/src/core/provider/MCNetService.h b/src/core/provider/MCNetService.h
index bc1edf81..00a618ad 100644
--- a/src/core/provider/MCNetService.h
+++ b/src/core/provider/MCNetService.h
@@ -56,4 +56,4 @@ namespace mailcore {
#endif
-#endif \ No newline at end of file
+#endif
diff --git a/src/core/provider/MCProvider.h b/src/core/provider/MCProvider.h
index b13bb263..ad8189b2 100644
--- a/src/core/provider/MCProvider.h
+++ b/src/core/provider/MCProvider.h
@@ -13,5 +13,6 @@
#include <MailCore/MCMailProvidersManager.h>
#include <MailCore/MCMailProvider.h>
#include <MailCore/MCNetService.h>
+#include <MailCore/MCAccountValidator.h>
#endif
diff --git a/src/core/renderer/MCHTMLRenderer.cpp b/src/core/renderer/MCHTMLRenderer.cpp
index 568c939e..c42bcb45 100644
--- a/src/core/renderer/MCHTMLRenderer.cpp
+++ b/src/core/renderer/MCHTMLRenderer.cpp
@@ -92,7 +92,7 @@ static bool isTextPart(AbstractPart * part, htmlRendererContext * context)
MCAssert(mimeType != NULL);
if (!part->isInlineAttachment()) {
- if ((part->filename() != NULL) && context->firstRendered) {
+ if (part->isAttachment() || ((part->filename() != NULL) && context->firstRendered)) {
return false;
}
}
@@ -218,6 +218,9 @@ static String * htmlForAbstractMessage(String * folder, AbstractMessage * messag
context.pass = 1;
context.firstAttachment = false;
context.hasTextPart = false;
+
+ htmlCallback->setMixedTextAndAttachmentsModeEnabled(context.hasMixedTextAndAttachments);
+
String * content = htmlForAbstractPart(mainPart, &context);
if (content == NULL)
return NULL;
@@ -274,6 +277,28 @@ static String * htmlForAbstractSinglePart(AbstractPart * part, htmlRendererConte
if (isTextPart(part, context)) {
if (context->pass == 0) {
if (context->state == RENDER_STATE_HAD_ATTACHMENT) {
+#if 0
+ if (part->className()->isEqual(MCSTR("mailcore::IMAPPart"))) {
+ if (mimeType->isEqual(MCSTR("text/plain"))) {
+ Data * data = context->dataCallback->dataForIMAPPart(context->folder, (IMAPPart *) part);
+ if (data != NULL) {
+ if (data->length() == 0) {
+ return NULL;
+ }
+ else if (data->length() == 2) {
+ if (strncmp(data->bytes(), "\r\n", 2) == 0) {
+ return NULL;
+ }
+ }
+ else if (data->length() == 1) {
+ if (strncmp(data->bytes(), "\n", 1) == 0) {
+ return NULL;
+ }
+ }
+ }
+ }
+ }
+#endif
context->state = RENDER_STATE_HAD_ATTACHMENT_THEN_TEXT;
}
return NULL;
@@ -296,6 +321,7 @@ static String * htmlForAbstractSinglePart(AbstractPart * part, htmlRendererConte
String * str = data->stringWithDetectedCharset(charset, false);
str = str->htmlMessageContent();
+ str = context->htmlCallback->filterHTMLForPart(str);
context->firstRendered = true;
return str;
}
@@ -307,7 +333,8 @@ static String * htmlForAbstractSinglePart(AbstractPart * part, htmlRendererConte
}
else if (part->className()->isEqual(MCSTR("mailcore::Attachment"))) {
data = ((Attachment *) part)->data();
- MCAssert(data != NULL);
+ // It may be NULL when mailcore::MessageParser::attachments() is invoked when
+ // when mailcore::MessageParser has been serialized/unserialized.
}
if (data == NULL)
return NULL;
diff --git a/src/core/renderer/MCHTMLRendererCallback.cpp b/src/core/renderer/MCHTMLRendererCallback.cpp
index fb492c9e..a3b14341 100644
--- a/src/core/renderer/MCHTMLRendererCallback.cpp
+++ b/src/core/renderer/MCHTMLRendererCallback.cpp
@@ -289,3 +289,7 @@ bool HTMLRendererTemplateCallback::shouldShowPart(AbstractPart * part)
{
return true;
}
+
+void HTMLRendererTemplateCallback::setMixedTextAndAttachmentsModeEnabled(bool enabled)
+{
+}
diff --git a/src/core/renderer/MCHTMLRendererCallback.h b/src/core/renderer/MCHTMLRendererCallback.h
index a12a3e45..4a4fc40f 100644
--- a/src/core/renderer/MCHTMLRendererCallback.h
+++ b/src/core/renderer/MCHTMLRendererCallback.h
@@ -35,6 +35,8 @@ namespace mailcore {
HTMLRendererTemplateCallback();
virtual ~HTMLRendererTemplateCallback();
+ virtual void setMixedTextAndAttachmentsModeEnabled(bool enabled);
+
virtual bool canPreviewPart(AbstractPart * part);
virtual bool shouldShowPart(AbstractPart * part);
diff --git a/src/core/rfc822/MCAttachment.cpp b/src/core/rfc822/MCAttachment.cpp
index 99f3caa0..cdee201b 100644
--- a/src/core/rfc822/MCAttachment.cpp
+++ b/src/core/rfc822/MCAttachment.cpp
@@ -2,6 +2,7 @@
#include "MCAttachment.h"
+#include "MCDefines.h"
#include "MCMultipart.h"
#include "MCMessagePart.h"
#include "MCMessageHeader.h"
@@ -111,10 +112,7 @@ String * Attachment::mimeTypeForFilename(String * filename)
if (result != NULL)
return result;
- if (ext->isEqual(MCSTR("jpg"))) {
- return MCSTR("image/jpeg");
- }
- else if (ext->isEqual(MCSTR("jpeg"))) {
+ if (ext->isEqual(MCSTR("jpeg")) || ext->isEqual(MCSTR("jpg"))) {
return MCSTR("image/jpeg");
}
else if (ext->isEqual(MCSTR("png"))) {
@@ -129,6 +127,9 @@ String * Attachment::mimeTypeForFilename(String * filename)
else if (ext->isEqual(MCSTR("txt"))) {
return MCSTR("text/plain");
}
+ else if (ext->isEqual(MCSTR("tiff")) || ext->isEqual(MCSTR("tif"))) {
+ return MCSTR("image/tiff");
+ }
return NULL;
}
@@ -589,6 +590,9 @@ Attachment * Attachment::attachmentWithSingleMIME(struct mailmime * mime)
if (single_fields.fld_disposition->dsp_type->dsp_type == MAILMIME_DISPOSITION_TYPE_INLINE) {
result->setInlineAttachment(true);
}
+ else if (single_fields.fld_disposition->dsp_type->dsp_type == MAILMIME_DISPOSITION_TYPE_ATTACHMENT) {
+ result->setAttachment(true);
+ }
}
}
@@ -607,3 +611,13 @@ MessagePart * Attachment::attachmentWithMessageMIME(struct mailmime * mime)
return (MessagePart *) attachment->autorelease();
}
+
+static void * createObject()
+{
+ return new Attachment();
+}
+
+INITIALIZE(Attachment)
+{
+ Object::registerObjectConstructor("mailcore::Attachment", &createObject);
+}
diff --git a/src/core/rfc822/MCMessageParser.cpp b/src/core/rfc822/MCMessageParser.cpp
index 71071c02..beddeebc 100644
--- a/src/core/rfc822/MCMessageParser.cpp
+++ b/src/core/rfc822/MCMessageParser.cpp
@@ -5,6 +5,7 @@
#include <CoreFoundation/CoreFoundation.h>
#endif
+#include "MCDefines.h"
#include "MCAttachment.h"
#include "MCMessageHeader.h"
#include "MCHTMLRenderer.h"
@@ -140,6 +141,15 @@ HashMap * MessageParser::serializable()
return result;
}
+void MessageParser::importSerializable(HashMap * serializable)
+{
+ AbstractMessage::importSerializable(serializable);
+ MC_SAFE_REPLACE_RETAIN(AbstractPart, mMainPart, Object::objectWithSerializable((HashMap *) serializable->objectForKey(MCSTR("mainPart"))));
+ if (mMainPart != NULL) {
+ mMainPart->applyUniquePartID();
+ }
+}
+
Object * MessageParser::copy()
{
return new MessageParser(this);
@@ -190,3 +200,13 @@ String * MessageParser::plainTextBodyRendering(bool stripWhitespace)
}
return plainTextBodyString;
}
+
+static void * createObject()
+{
+ return new MessageParser();
+}
+
+INITIALIZE(MessageParser)
+{
+ Object::registerObjectConstructor("mailcore::MessageParser", &createObject);
+}
diff --git a/src/core/rfc822/MCMessageParser.h b/src/core/rfc822/MCMessageParser.h
index 048cee60..9682bfce 100644
--- a/src/core/rfc822/MCMessageParser.h
+++ b/src/core/rfc822/MCMessageParser.h
@@ -42,7 +42,8 @@ namespace mailcore {
virtual AbstractPart * partForUniqueID(String * uniqueID);
virtual HashMap * serializable();
-
+ virtual void importSerializable(HashMap * serializable);
+
#ifdef __APPLE__
public:
static MessageParser * messageParserWithData(CFDataRef data);
diff --git a/src/core/rfc822/MCMessagePart.cpp b/src/core/rfc822/MCMessagePart.cpp
index 21d61181..abd98ac2 100644
--- a/src/core/rfc822/MCMessagePart.cpp
+++ b/src/core/rfc822/MCMessagePart.cpp
@@ -1,5 +1,7 @@
#include "MCMessagePart.h"
+#include "MCDefines.h"
+
using namespace mailcore;
MessagePart::MessagePart()
@@ -18,3 +20,13 @@ Object * MessagePart::copy()
{
return new MessagePart(this);
}
+
+static void * createObject()
+{
+ return new MessagePart();
+}
+
+INITIALIZE(MessagePart)
+{
+ Object::registerObjectConstructor("mailcore::MessagePart", &createObject);
+}
diff --git a/src/core/rfc822/MCMultipart.cpp b/src/core/rfc822/MCMultipart.cpp
index e048669e..0be76430 100644
--- a/src/core/rfc822/MCMultipart.cpp
+++ b/src/core/rfc822/MCMultipart.cpp
@@ -1,5 +1,7 @@
#include "MCMultipart.h"
+#include "MCDefines.h"
+
using namespace mailcore;
Multipart::Multipart()
@@ -19,3 +21,12 @@ Object * Multipart::copy()
return new Multipart(this);
}
+static void * createObject()
+{
+ return new Multipart();
+}
+
+INITIALIZE(Multipart)
+{
+ Object::registerObjectConstructor("mailcore::Multipart", &createObject);
+}
diff --git a/src/core/smtp/MCSMTPSession.cpp b/src/core/smtp/MCSMTPSession.cpp
index eab05730..0c2016fd 100644
--- a/src/core/smtp/MCSMTPSession.cpp
+++ b/src/core/smtp/MCSMTPSession.cpp
@@ -189,6 +189,10 @@ static void logger(mailsmtp * smtp, int log_type, const char * buffer, size_t si
return;
ConnectionLogType type = getConnectionType(log_type);
+ if ((int) type == -1) {
+ // in case of MAILSTREAM_LOG_TYPE_INFO_RECEIVED or MAILSTREAM_LOG_TYPE_INFO_SENT.
+ return;
+ }
bool isBuffer = isBufferFromLogType(log_type);
if (isBuffer) {
@@ -626,6 +630,7 @@ void SMTPSession::sendMessage(Address * from, Array * recipients, Data * message
r = mailesmtp_send_quit(mSmtp, MCUTF8(from->mailbox()), 0, NULL,
address_list,
messageData->bytes(), messageData->length());
+ mShouldDisconnect = true;
}
else {
r = mailesmtp_send(mSmtp, MCUTF8(from->mailbox()), 0, NULL,
@@ -667,17 +672,22 @@ void SMTPSession::sendMessage(Address * from, Array * recipients, Data * message
goto err;
}
else if (r != MAILSMTP_NO_ERROR) {
- if ((responseCode == 550) && (response != NULL) && (response->hasPrefix(MCSTR("5.3.4")))) {
- * pError = ErrorNeedsConnectToWebmail;
- goto err;
- }
- else {
- * pError = ErrorSendMessage;
- MC_SAFE_REPLACE_COPY(String, mLastSMTPResponse, response);
- mLastLibetpanError = r;
- mLastSMTPResponseCode = responseCode;
- goto err;
+ if ((responseCode == 550) && (response != NULL)) {
+ if (response->hasPrefix(MCSTR("5.3.4 "))) {
+ * pError = ErrorNeedsConnectToWebmail;
+ goto err;
+ }
+ else if (response->hasPrefix(MCSTR("5.7.1 "))) {
+ * pError = ErrorSendMessageNotAllowed;
+ goto err;
+ }
}
+
+ * pError = ErrorSendMessage;
+ MC_SAFE_REPLACE_COPY(String, mLastSMTPResponse, response);
+ mLastLibetpanError = r;
+ mLastSMTPResponseCode = responseCode;
+ goto err;
}
bodyProgress(messageData->length(), messageData->length());
@@ -702,7 +712,8 @@ Data * SMTPSession::dataWithFilteredBcc(Data * data)
struct mailimf_fields * fields = msg->msg_fields;
int col = 0;
-
+
+ int hasRecipient = 0;
str = mmap_string_new("");
for(clistiter * cur = clist_begin(fields->fld_list) ; cur != NULL ; cur = clist_next(cur)) {
struct mailimf_field * field = (struct mailimf_field *) clist_content(cur);
@@ -711,6 +722,17 @@ Data * SMTPSession::dataWithFilteredBcc(Data * data)
clist_delete(fields->fld_list, cur);
break;
}
+ else if ((field->fld_type == MAILIMF_FIELD_TO) || (field->fld_type == MAILIMF_FIELD_CC) || (field->fld_type == MAILIMF_FIELD_BCC)) {
+ 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);
}
mailimf_fields_write_mem(str, &col, fields);
mmap_string_append(str, "\n");
diff --git a/src/core/zip/MCZip.cpp b/src/core/zip/MCZip.cpp
index a9879c9f..69e7fc6e 100644
--- a/src/core/zip/MCZip.cpp
+++ b/src/core/zip/MCZip.cpp
@@ -1,6 +1,7 @@
#include "MCWin32.h" // Should be included first.
#include "MCZip.h"
+#include "MCZipPrivate.h"
#include "zip.h"
#include "unzip.h"
@@ -166,23 +167,33 @@ static ErrorCode addFile(zipFile file, String * path)
return ErrorNone;
}
-String * mailcore::CreateTemporaryZipFileFromFolder(String * folder)
+#ifndef __APPLE__
+String * mailcore::TemporaryDirectoryForZip()
{
char tempdir[] = "/tmp/mailcore2-XXXXXX";
char * result = mkdtemp(tempdir);
if (result == NULL) {
return NULL;
}
+ return String::stringWithFileSystemRepresentation(tempdir);
+}
+#endif
+
+String * mailcore::CreateTemporaryZipFileFromFolder(String * folder)
+{
+ String * tempDirectoryString = TemporaryDirectoryForZip();
+
+ if (tempDirectoryString == NULL) {
+ return NULL;
+ }
- String * tempDirectoryString = String::stringWithFileSystemRepresentation(tempdir);
String * path = tempDirectoryString->stringByAppendingPathComponent(folder->lastPathComponent())->stringByAppendingUTF8Format(".zip");
ErrorCode err = CreateZipFileFromFolder(path, folder);
if (err != ErrorNone) {
- unlink(path->fileSystemRepresentation());
- unlink(tempdir);
return NULL;
}
+ unlink(tempDirectoryString->fileSystemRepresentation());
return path;
}
diff --git a/src/core/zip/MCZipMac.mm b/src/core/zip/MCZipMac.mm
new file mode 100644
index 00000000..94a8a807
--- /dev/null
+++ b/src/core/zip/MCZipMac.mm
@@ -0,0 +1,30 @@
+//
+// MCZipMac.mm
+// mailcore2
+//
+// Created by juliangsp on 7/7/15.
+// Copyright (c) 2015 MailCore. All rights reserved.
+//
+
+#include "MCZipPrivate.h"
+
+#import "NSObject+MCO.h"
+#import <Foundation/Foundation.h>
+
+using namespace mailcore;
+
+String * mailcore::TemporaryDirectoryForZip()
+{
+ NSError * error;
+ NSString * directoryString;
+
+ error = nil;
+ directoryString = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]];
+ directoryString = [directoryString stringByAppendingString:[[NSUUID UUID] UUIDString]];
+
+ if (![[NSFileManager defaultManager] createDirectoryAtPath:directoryString withIntermediateDirectories:YES attributes:nil error:NULL]) {
+ return nil;
+ }
+
+ return MCO_FROM_OBJC(String, directoryString);
+}
diff --git a/src/core/zip/MCZipPrivate.h b/src/core/zip/MCZipPrivate.h
new file mode 100644
index 00000000..070946f6
--- /dev/null
+++ b/src/core/zip/MCZipPrivate.h
@@ -0,0 +1,20 @@
+//
+// MCZipMac.h
+// mailcore2
+//
+// Created by juliangsp on 7/7/15.
+// Copyright (c) 2015 MailCore. All rights reserved.
+//
+
+#ifndef mailcore2_MCZipMac_h
+#define mailcore2_MCZipMac_h
+
+#include <MailCore/MCBaseTypes.h>
+
+namespace mailcore {
+
+ String * TemporaryDirectoryForZip();
+
+};
+
+#endif