diff options
author | Scott Herscher <scott@porchdogsoft.com> | 2013-02-03 11:02:00 -0800 |
---|---|---|
committer | Scott Herscher <scott@porchdogsoft.com> | 2013-02-03 11:02:00 -0800 |
commit | 57ef6b75d7465a78c09ddbba07379625072077f5 (patch) | |
tree | 3619bb2742a957d4618123460c72bf12644e9837 /src | |
parent | 54b038df296c4bb85bcd1a586f7c90c4c76d09e0 (diff) | |
parent | 61e978ca00aab50aed44c82aaf5d98177629e82c (diff) |
Merge branch 'master' of github.com:MailCore/mailcore2
Diffstat (limited to 'src')
71 files changed, 1739 insertions, 231 deletions
diff --git a/src/core/MCCore.h b/src/core/MCCore.h index d5d6f79d..a909e677 100644 --- a/src/core/MCCore.h +++ b/src/core/MCCore.h @@ -15,6 +15,6 @@ #include <mailcore/MCPOP.h> #include <mailcore/MCRFC822.h> #include <mailcore/MCSMTP.h> -#include <mailcore/MCAsyncIMAP.h> +#include <mailcore/MCRenderer.h> #endif diff --git a/src/core/abstract/MCAbstractMessage.cc b/src/core/abstract/MCAbstractMessage.cc index 00a4b9b9..b7d9b9af 100644 --- a/src/core/abstract/MCAbstractMessage.cc +++ b/src/core/abstract/MCAbstractMessage.cc @@ -39,13 +39,6 @@ String * AbstractMessage::description() } } -#if 0 -String * AbstractMessage::className() -{ - return MCSTR("MessageHeader"); -} -#endif - Object * AbstractMessage::copy() { return new AbstractMessage(this); @@ -63,3 +56,15 @@ void AbstractMessage::setHeader(MessageHeader * header) { MC_SAFE_REPLACE_RETAIN(MessageHeader, mHeader, header); } + +AbstractPart * AbstractMessage::partForContentID(String * contentID) +{ + MCAssert(0); + return NULL; +} + +AbstractPart * AbstractMessage::partForUniqueID(String * uniqueID) +{ + MCAssert(0); + return NULL; +} diff --git a/src/core/abstract/MCAbstractMessage.h b/src/core/abstract/MCAbstractMessage.h index 9f327cad..9dccdbb8 100644 --- a/src/core/abstract/MCAbstractMessage.h +++ b/src/core/abstract/MCAbstractMessage.h @@ -7,6 +7,7 @@ namespace mailcore { + class AbstractPart; class MessageHeader; class AbstractMessage : public Object { @@ -17,6 +18,9 @@ namespace mailcore { virtual MessageHeader * header(); virtual void setHeader(MessageHeader * header); + virtual AbstractPart * partForContentID(String * contentID); + virtual AbstractPart * partForUniqueID(String * uniqueID); + public: //subclass behavior AbstractMessage(AbstractMessage * other); virtual String * description(); diff --git a/src/core/abstract/MCAbstractMessagePart.cc b/src/core/abstract/MCAbstractMessagePart.cc index 6939d060..a52d2196 100644 --- a/src/core/abstract/MCAbstractMessagePart.cc +++ b/src/core/abstract/MCAbstractMessagePart.cc @@ -37,13 +37,6 @@ String * AbstractMessagePart::description() return result; } -#if 0 -String * AbstractMessagePart::className() -{ - return MCSTR("AbstractMessagePart"); -} -#endif - Object * AbstractMessagePart::copy() { return new AbstractMessagePart(this); @@ -86,3 +79,13 @@ void AbstractMessagePart::setMessage(AbstractMessage * message) AbstractPart::setMessage(message); applyMessage(); } + +AbstractPart * AbstractMessagePart::partForContentID(String * contentID) +{ + return mainPart()->partForContentID(contentID); +} + +AbstractPart * AbstractMessagePart::partForUniqueID(String * contentID) +{ + return mainPart()->partForContentID(contentID); +} diff --git a/src/core/abstract/MCAbstractMessagePart.h b/src/core/abstract/MCAbstractMessagePart.h index bfbd00be..789f7676 100644 --- a/src/core/abstract/MCAbstractMessagePart.h +++ b/src/core/abstract/MCAbstractMessagePart.h @@ -24,6 +24,9 @@ namespace mailcore { virtual void setMessage(AbstractMessage * message); + virtual AbstractPart * partForContentID(String * contentID); + virtual AbstractPart * partForUniqueID(String * uniqueID); + public: //subclass behavior AbstractMessagePart(AbstractMessagePart * other); virtual String * description(); diff --git a/src/core/abstract/MCAbstractMultipart.cc b/src/core/abstract/MCAbstractMultipart.cc index fa48d959..2604bcac 100644 --- a/src/core/abstract/MCAbstractMultipart.cc +++ b/src/core/abstract/MCAbstractMultipart.cc @@ -65,13 +65,6 @@ String * AbstractMultipart::description() return result; } -#if 0 -String * AbstractMultipart::className() -{ - return MCSTR("AbstractMultipart"); -} -#endif - Object * AbstractMultipart::copy() { return new AbstractMultipart(this); @@ -93,3 +86,27 @@ void AbstractMultipart::setMessage(AbstractMessage * message) AbstractPart::setMessage(message); applyMessage(); } + +AbstractPart * AbstractMultipart::partForContentID(String * contentID) +{ + for(unsigned int i = 0 ; i < parts()->count() ; i ++) { + mailcore::AbstractPart * subpart = (mailcore::AbstractPart *) parts()->objectAtIndex(i); + mailcore::AbstractPart * result = subpart->partForContentID(contentID); + if (result != NULL) + return result; + } + return NULL; +} + + +AbstractPart * AbstractMultipart::partForUniqueID(String * uniqueID) +{ + for(unsigned int i = 0 ; i < parts()->count() ; i ++) { + mailcore::AbstractPart * subpart = (mailcore::AbstractPart *) parts()->objectAtIndex(i); + mailcore::AbstractPart * result = subpart->partForUniqueID(uniqueID); + if (result != NULL) + return result; + } + return NULL; +} + diff --git a/src/core/abstract/MCAbstractMultipart.h b/src/core/abstract/MCAbstractMultipart.h index 411e8af0..d5d5f343 100644 --- a/src/core/abstract/MCAbstractMultipart.h +++ b/src/core/abstract/MCAbstractMultipart.h @@ -19,6 +19,9 @@ namespace mailcore { virtual void setMessage(AbstractMessage * message); + virtual AbstractPart * partForContentID(String * contentID); + virtual AbstractPart * partForUniqueID(String * uniqueID); + public: //subclass behavior AbstractMultipart(AbstractMultipart * other); virtual String * description(); diff --git a/src/core/abstract/MCAbstractPart.cc b/src/core/abstract/MCAbstractPart.cc index 30c4c8f0..78e2e365 100644 --- a/src/core/abstract/MCAbstractPart.cc +++ b/src/core/abstract/MCAbstractPart.cc @@ -13,6 +13,7 @@ AbstractPart::AbstractPart() AbstractPart::AbstractPart(AbstractPart * other) { init(); + setUniqueID(other->mUniqueID); setFilename(other->mFilename); setMimeType(other->mMimeType); setCharset(other->mCharset); @@ -24,6 +25,7 @@ AbstractPart::AbstractPart(AbstractPart * other) void AbstractPart::init() { + mUniqueID = NULL; mFilename = NULL; mMimeType = NULL; mCharset = NULL; @@ -35,6 +37,7 @@ void AbstractPart::init() AbstractPart::~AbstractPart() { + MC_SAFE_RELEASE(mUniqueID); MC_SAFE_RELEASE(mFilename); MC_SAFE_RELEASE(mMimeType); MC_SAFE_RELEASE(mCharset); @@ -67,13 +70,6 @@ String * AbstractPart::description() return result; } -#if 0 -String * AbstractPart::className() -{ - return MCSTR("AbstractPart"); -} -#endif - Object * AbstractPart::copy() { return new AbstractPart(this); @@ -89,6 +85,16 @@ void AbstractPart::setPartType(PartType type) mPartType = type; } +String * AbstractPart::uniqueID() +{ + return mUniqueID; +} + +void AbstractPart::setUniqueID(String * uniqueID) +{ + MC_SAFE_REPLACE_COPY(String, mUniqueID, uniqueID); +} + String * AbstractPart::filename() { return mFilename; @@ -221,3 +227,24 @@ void AbstractPart::importIMAPFields(struct mailimap_body_fields * fields, } } } + +AbstractPart * AbstractPart::partForContentID(String * contentID) +{ + if (contentID->isEqual(mContentID)) { + return this; + } + else { + return NULL; + } +} + +AbstractPart * AbstractPart::partForUniqueID(String * uniqueID) +{ + if (uniqueID->isEqual(mUniqueID)) { + return this; + } + else { + return NULL; + } +} + diff --git a/src/core/abstract/MCAbstractPart.h b/src/core/abstract/MCAbstractPart.h index f7b29ced..49360089 100644 --- a/src/core/abstract/MCAbstractPart.h +++ b/src/core/abstract/MCAbstractPart.h @@ -28,6 +28,9 @@ namespace mailcore { virtual String * charset(); virtual void setCharset(String * charset); + virtual String * uniqueID(); + virtual void setUniqueID(String * uniqueID); + virtual String * contentID(); virtual void setContentID(String * contentID); @@ -40,15 +43,21 @@ namespace mailcore { virtual AbstractMessage * message(); virtual void setMessage(AbstractMessage * message); - virtual void importIMAPFields(struct mailimap_body_fields * fields, - struct mailimap_body_ext_1part * extension); + virtual AbstractPart * partForContentID(String * contentID); + virtual AbstractPart * partForUniqueID(String * uniqueID); public: // subclass behavior AbstractPart(AbstractPart * other); virtual String * description(); virtual Object * copy(); + public: // private + virtual void importIMAPFields(struct mailimap_body_fields * fields, + struct mailimap_body_ext_1part * extension); + + private: + String * mUniqueID; String * mFilename; String * mMimeType; String * mCharset; diff --git a/src/core/abstract/MCAddress.cc b/src/core/abstract/MCAddress.cc index 25bed974..2ef1cd2b 100644 --- a/src/core/abstract/MCAddress.cc +++ b/src/core/abstract/MCAddress.cc @@ -177,13 +177,6 @@ String * Address::description() return result; } -#if 0 -String * Address::className() -{ - return MCSTR("Address"); -} -#endif - bool Address::isEqual(Object * otherObject) { Address * otherAddress = (Address *) otherObject; diff --git a/src/core/abstract/MCMessageHeader.cc b/src/core/abstract/MCMessageHeader.cc index 765bc085..b0574293 100644 --- a/src/core/abstract/MCMessageHeader.cc +++ b/src/core/abstract/MCMessageHeader.cc @@ -154,13 +154,6 @@ String * MessageHeader::description() return result; } -#if 0 -String * MessageHeader::className() -{ - return MCSTR("MessageHeader"); -} -#endif - Object * MessageHeader::copy() { return new MessageHeader(this); diff --git a/src/core/basetypes/MCArray.cc b/src/core/basetypes/MCArray.cc index 212aa4ed..d457ece5 100644 --- a/src/core/basetypes/MCArray.cc +++ b/src/core/basetypes/MCArray.cc @@ -48,13 +48,6 @@ Array * Array::arrayWithObject(Object * obj) return (Array *) result->autorelease(); } -#if 0 -String * Array::className() -{ - return MCSTR("Array"); -} -#endif - String * Array::description() { String * result = String::string(); diff --git a/src/core/basetypes/MCData.cc b/src/core/basetypes/MCData.cc index c0f7d908..f98f57c7 100644 --- a/src/core/basetypes/MCData.cc +++ b/src/core/basetypes/MCData.cc @@ -110,13 +110,6 @@ void Data::setData(Data * otherData) appendData(otherData); } -#if 0 -String * Data::className() -{ - return MCSTR("Data"); -} -#endif - String * Data::description() { return String::stringWithUTF8Format("<%s:%p %i bytes>", MCUTF8(className()), this, length()); diff --git a/src/core/basetypes/MCHashMap.cc b/src/core/basetypes/MCHashMap.cc index 8dcf0f30..164198f5 100644 --- a/src/core/basetypes/MCHashMap.cc +++ b/src/core/basetypes/MCHashMap.cc @@ -93,13 +93,6 @@ HashMap * HashMap::hashMap() return (HashMap *) result->autorelease(); } -#if 0 -String * HashMap::className() -{ - return MCSTR("HashMap"); -} -#endif - String * HashMap::description() { String * result = String::string(); diff --git a/src/core/basetypes/MCObject.cc b/src/core/basetypes/MCObject.cc index 220a5a16..1665e1ee 100644 --- a/src/core/basetypes/MCObject.cc +++ b/src/core/basetypes/MCObject.cc @@ -11,9 +11,12 @@ #include "MCUtils.h" #include "MCAssert.h" #include "MCMainThread.h" +#include "MCLog.h" using namespace mailcore; +bool mailcore::zombieEnabled = 0; + Object::Object() { init(); @@ -55,9 +58,13 @@ void Object::release() if (mCounter == 0) { shouldRelease = true; } + if (mCounter < 0) { + MCLog("release too much %p %s", this, MCUTF8(className())); + MCAssert(0); + } pthread_mutex_unlock(&mLock); - if (shouldRelease) { + if (shouldRelease && !zombieEnabled) { //MCLog("dealloc %s", className()->description()->UTF8Characters()); delete this; } @@ -73,17 +80,9 @@ String * Object::className() { int status; char * unmangled = abi::__cxa_demangle(typeid(* this).name(), NULL, NULL, &status); - //return mailcore::String::uniquedStringWithUTF8Characters(typeid(* this).name()); return mailcore::String::uniquedStringWithUTF8Characters(unmangled); } -/* -String * Object::className() -{ - return MCSTR("Object"); -} -*/ - String * Object::description() { return String::stringWithUTF8Format("<%s:%p>", className()->UTF8Characters(), this); diff --git a/src/core/basetypes/MCObject.h b/src/core/basetypes/MCObject.h index beda7471..caeded70 100644 --- a/src/core/basetypes/MCObject.h +++ b/src/core/basetypes/MCObject.h @@ -8,6 +8,8 @@ namespace mailcore { + extern bool zombieEnabled; + class String; class Object { diff --git a/src/core/basetypes/MCSet.cc b/src/core/basetypes/MCSet.cc index fcda7f62..d3d14dc8 100644 --- a/src/core/basetypes/MCSet.cc +++ b/src/core/basetypes/MCSet.cc @@ -42,13 +42,6 @@ Set * Set::setWithArray(Array * objects) return (Set *) result->autorelease(); } -#if 0 -String * Set::className() -{ - return MCSTR("Set"); -} -#endif - String * Set::description() { String * result = String::string(); diff --git a/src/core/basetypes/MCString.cc b/src/core/basetypes/MCString.cc index a5607475..d57e70ed 100644 --- a/src/core/basetypes/MCString.cc +++ b/src/core/basetypes/MCString.cc @@ -953,13 +953,6 @@ void String::setCharacters(const UChar * unicodeCharacters) appendCharacters(unicodeCharacters); } -#if 0 -String * String::className() -{ - return MCSTR("String"); -} -#endif - String * String::description() { return this; @@ -1206,7 +1199,7 @@ unsigned int String::replaceOccurrencesOfString(String * occurrence, String * re int delta = replacement->length() - occurrence->length(); int modifiedLength = mLength + delta * count + 1; unicodeChars = (UChar *) malloc(modifiedLength * sizeof(* unicodeChars)); - unicodeChars[modifiedLength] = 0; + unicodeChars[modifiedLength - 1] = 0; UChar * dest_p = unicodeChars; p = mUnicodeChars; while (1) { @@ -1729,7 +1722,9 @@ String * String::flattenHTMLAndShowBlockquoteAndLink(bool showBlockquote, bool s state.linkStack = new Array(); state.paragraphSpacingStack = new Array(); - htmlSAXParseDoc((xmlChar*) UTF8Characters(), "utf-8", &handler, &state); + const char * characters = cleanedHTMLString()->UTF8Characters(); + + htmlSAXParseDoc((xmlChar*) characters, "utf-8", &handler, &state); if (mem_base != xmlMemBlocks()) { MCLog("Leak of %d blocks found in htmlSAXParseDoc", @@ -1979,8 +1974,7 @@ String * String::uniquedStringWithUTF8Characters(const char * UTF8Characters) String * String::htmlEncodedString() { - String * htmlStr; - htmlStr = String::string(); + String * htmlStr = String::string(); #define kBufSz 2000 const char * inStr = UTF8Characters(); @@ -2019,3 +2013,9 @@ String * String::cleanedHTMLString() #warning implement HTML cleaning with tidy return (String *) copy()->autorelease(); } + +bool String::isEqualCaseInsensitive(String * otherString) +{ + return caseInsensitiveCompare(otherString) == 0; +} + diff --git a/src/core/basetypes/MCString.h b/src/core/basetypes/MCString.h index 97db50da..521291d3 100644 --- a/src/core/basetypes/MCString.h +++ b/src/core/basetypes/MCString.h @@ -61,6 +61,8 @@ namespace mailcore { virtual Array * componentsSeparatedByString(String * separator); + virtual bool isEqualCaseInsensitive(String * otherString); + // Additions static String * stringByDecodingMIMEHeaderValue(const char * phrase); virtual Data * encodedAddressDisplayNameValue(); diff --git a/src/core/basetypes/MCUtils.h b/src/core/basetypes/MCUtils.h index 9e3de1ac..30b0cefd 100644 --- a/src/core/basetypes/MCUtils.h +++ b/src/core/basetypes/MCUtils.h @@ -33,6 +33,8 @@ #define MMCUTF8(str) MCUTF8(str) #define MCUTF8DESC(obj) ((obj) != NULL ? (obj)->description()->UTF8Characters() : NULL ) +#define MCLOCALIZEDSTRING(key) key + #endif #endif diff --git a/src/core/basetypes/MCValue.cc b/src/core/basetypes/MCValue.cc index d275d3df..b450e3e3 100644 --- a/src/core/basetypes/MCValue.cc +++ b/src/core/basetypes/MCValue.cc @@ -94,13 +94,6 @@ String * Value::description() } } -#if 0 -String * Value::className() -{ - return MCSTR("Value"); -} -#endif - bool Value::isEqual(Object * otherObject) { Value * otherValue = (Value *) otherObject; diff --git a/src/core/imap/MCIMAPFolder.cc b/src/core/imap/MCIMAPFolder.cc index 0f1b2105..e8f31959 100644 --- a/src/core/imap/MCIMAPFolder.cc +++ b/src/core/imap/MCIMAPFolder.cc @@ -27,13 +27,6 @@ IMAPFolder::~IMAPFolder() MC_SAFE_RELEASE(mPath); } -#if 0 -String * IMAPFolder::className() -{ - return MCSTR("IMAPFolder"); -} -#endif - Object * IMAPFolder::copy() { return new IMAPFolder(this); diff --git a/src/core/imap/MCIMAPMessage.cc b/src/core/imap/MCIMAPMessage.cc index faf91c66..7f5f4427 100644 --- a/src/core/imap/MCIMAPMessage.cc +++ b/src/core/imap/MCIMAPMessage.cc @@ -1,9 +1,17 @@ #include "MCIMAPMessage.h" #include "MCMessageHeader.h" +#include "MCIMAPPart.h" +#include "MCIMAPMessagePart.h" +#include "MCIMAPMultipart.h" +#include "MCHTMLRenderer.h" using namespace mailcore; +static AbstractPart * partForPartIDInPart(AbstractPart * part, String * partID); +static AbstractPart * partForPartIDInMultipart(AbstractMultipart * part, String * partID); +static AbstractPart * partForPartIDInMessagePart(AbstractMessagePart * part, String * partID); + void IMAPMessage::init() { mUid = NULL; @@ -34,13 +42,6 @@ IMAPMessage::~IMAPMessage() MC_SAFE_RELEASE(mLabels); } -#if 0 -String * IMAPMessage::className() -{ - return MCSTR("IMAPMessage"); -} -#endif - Object * IMAPMessage::copy() { return new IMAPMessage(this); @@ -109,3 +110,66 @@ Array * IMAPMessage::gmailLabels() return mLabels; } +AbstractPart * IMAPMessage::partForPartID(String * partID) +{ + return partForPartIDInPart(mainPart(), partID); +} + +static AbstractPart * partForPartIDInPart(AbstractPart * part, String * partID) +{ + switch (part->partType()) { + case PartTypeSingle: + if (partID->isEqual(((IMAPPart *) part)->partID())) { + return part; + } + return NULL; + case mailcore::PartTypeMultipartMixed: + case mailcore::PartTypeMultipartRelated: + case mailcore::PartTypeMultipartAlternative: + if (partID->isEqual(((IMAPMultipart *) part)->partID())) { + return part; + } + return partForPartIDInMultipart((AbstractMultipart *) part, partID); + case mailcore::PartTypeMessage: + if (partID->isEqual(((IMAPMessagePart *) part)->partID())) { + return part; + } + return partForPartIDInMessagePart((AbstractMessagePart *) part, partID); + default: + return NULL; + } +} + +static AbstractPart * partForPartIDInMessagePart(AbstractMessagePart * part, String * partID) +{ + return partForPartIDInPart(part->mainPart(), partID); +} + +static AbstractPart * partForPartIDInMultipart(AbstractMultipart * part, String * partID) +{ + for(unsigned int i = 0 ; i < part->parts()->count() ; i ++) { + mailcore::AbstractPart * subpart = (mailcore::AbstractPart *) part->parts()->objectAtIndex(i); + mailcore::AbstractPart * result = partForPartIDInPart(subpart, partID); + if (result != NULL) + return result; + } + return NULL; +} + +AbstractPart * IMAPMessage::partForContentID(String * contentID) +{ + return mainPart()->partForContentID(contentID); +} + +AbstractPart * IMAPMessage::partForUniqueID(String * uniqueID) +{ + return mainPart()->partForUniqueID(uniqueID); +} + +String * IMAPMessage::htmlRendering(String * folder, + HTMLRendererIMAPCallback * dataCallback, + HTMLRendererTemplateCallback * htmlCallback) +{ + return HTMLRenderer::htmlForIMAPMessage(folder, this, dataCallback, htmlCallback); +} + diff --git a/src/core/imap/MCIMAPMessage.h b/src/core/imap/MCIMAPMessage.h index 692ddc49..b1fd4647 100644 --- a/src/core/imap/MCIMAPMessage.h +++ b/src/core/imap/MCIMAPMessage.h @@ -11,6 +11,10 @@ namespace mailcore { + class IMAPPart; + class HTMLRendererIMAPCallback; + class HTMLRendererTemplateCallback; + class IMAPMessage : public AbstractMessage { public: IMAPMessage(); @@ -31,6 +35,15 @@ namespace mailcore { virtual void setGmailLabels(Array * labels); virtual Array * gmailLabels(); + virtual AbstractPart * partForPartID(String * partID); + + virtual AbstractPart * partForContentID(String * contentID); + virtual AbstractPart * partForUniqueID(String * uniqueID); + + virtual String * htmlRendering(String * folder, + HTMLRendererIMAPCallback * dataCallback, + HTMLRendererTemplateCallback * htmlCallback = NULL); + public: // subclass behavior IMAPMessage(IMAPMessage * other); virtual Object * copy(); diff --git a/src/core/imap/MCIMAPMessagePart.cc b/src/core/imap/MCIMAPMessagePart.cc index 31a6f7e5..bd97657c 100644 --- a/src/core/imap/MCIMAPMessagePart.cc +++ b/src/core/imap/MCIMAPMessagePart.cc @@ -4,24 +4,36 @@ using namespace mailcore; IMAPMessagePart::IMAPMessagePart() { + init(); } IMAPMessagePart::IMAPMessagePart(IMAPMessagePart * other) : AbstractMessagePart(other) { + init(); + MC_SAFE_REPLACE_COPY(String, mPartID, other->mPartID); } IMAPMessagePart::~IMAPMessagePart() { + MC_SAFE_RELEASE(mPartID); } -#if 0 -String * IMAPMessagePart::className() +Object * IMAPMessagePart::copy() { - return MCSTR("IMAPMessagePart"); + return new IMAPMessagePart(this); } -#endif -Object * IMAPMessagePart::copy() +void IMAPMessagePart::init() { - return new IMAPMessagePart(this); + mPartID = NULL; +} + +void IMAPMessagePart::setPartID(String * partID) +{ + MC_SAFE_REPLACE_COPY(String, mPartID, partID); +} + +String * IMAPMessagePart::partID() +{ + return mPartID; } diff --git a/src/core/imap/MCIMAPMessagePart.h b/src/core/imap/MCIMAPMessagePart.h index 03747ac0..8e23eff2 100644 --- a/src/core/imap/MCIMAPMessagePart.h +++ b/src/core/imap/MCIMAPMessagePart.h @@ -13,9 +13,16 @@ namespace mailcore { IMAPMessagePart(); virtual ~IMAPMessagePart(); + virtual void setPartID(String * partID); + virtual String * partID(); + public: // subclass behavior IMAPMessagePart(IMAPMessagePart * other); virtual Object * copy(); + + private: + String * mPartID; + void init(); }; } diff --git a/src/core/imap/MCIMAPMultipart.cc b/src/core/imap/MCIMAPMultipart.cc index a941cbc4..be0b2c8e 100644 --- a/src/core/imap/MCIMAPMultipart.cc +++ b/src/core/imap/MCIMAPMultipart.cc @@ -4,25 +4,36 @@ using namespace mailcore; IMAPMultipart::IMAPMultipart() { + init(); } IMAPMultipart::IMAPMultipart(IMAPMultipart * other) : AbstractMultipart(other) { + init(); + MC_SAFE_REPLACE_COPY(String, mPartID, other->mPartID); } IMAPMultipart::~IMAPMultipart() { + MC_SAFE_RELEASE(mPartID); } -#if 0 -String * IMAPMultipart::className() +Object * IMAPMultipart::copy() { - return MCSTR("IMAPMultipart"); + return new IMAPMultipart(this); } -#endif -Object * IMAPMultipart::copy() +void IMAPMultipart::init() { - return new IMAPMultipart(this); + mPartID = NULL; } +void IMAPMultipart::setPartID(String * partID) +{ + MC_SAFE_REPLACE_COPY(String, mPartID, partID); +} + +String * IMAPMultipart::partID() +{ + return mPartID; +} diff --git a/src/core/imap/MCIMAPMultipart.h b/src/core/imap/MCIMAPMultipart.h index 9a768d0a..02ee5cf8 100644 --- a/src/core/imap/MCIMAPMultipart.h +++ b/src/core/imap/MCIMAPMultipart.h @@ -13,9 +13,16 @@ namespace mailcore { IMAPMultipart(); virtual ~IMAPMultipart(); + virtual void setPartID(String * partID); + virtual String * partID(); + public: // subclass behavior IMAPMultipart(IMAPMultipart * other); virtual Object * copy(); + + private: + String * mPartID; + void init(); }; } diff --git a/src/core/imap/MCIMAPNamespace.cc b/src/core/imap/MCIMAPNamespace.cc index b18752e4..c1c430fa 100644 --- a/src/core/imap/MCIMAPNamespace.cc +++ b/src/core/imap/MCIMAPNamespace.cc @@ -26,13 +26,6 @@ IMAPNamespace::~IMAPNamespace() MC_SAFE_RELEASE(mItems); } -#if 0 -String * IMAPNamespace::className() -{ - return MCSTR("IMAPNamespace"); -} -#endif - String * IMAPNamespace::description() { String * result = String::string(); diff --git a/src/core/imap/MCIMAPNamespaceItem.cc b/src/core/imap/MCIMAPNamespaceItem.cc index 62fca1f0..7a608d68 100644 --- a/src/core/imap/MCIMAPNamespaceItem.cc +++ b/src/core/imap/MCIMAPNamespaceItem.cc @@ -28,13 +28,6 @@ IMAPNamespaceItem::~IMAPNamespaceItem() MC_SAFE_RELEASE(mPrefix); } -#if 0 -String * IMAPNamespaceItem::className() -{ - return MCSTR("IMAPNamespaceItem"); -} -#endif - String * IMAPNamespaceItem::description() { return String::stringWithUTF8Format("<%s:%p %s %c>", diff --git a/src/core/imap/MCIMAPPart.cc b/src/core/imap/MCIMAPPart.cc index 8f7e1e0e..dc1a687f 100644 --- a/src/core/imap/MCIMAPPart.cc +++ b/src/core/imap/MCIMAPPart.cc @@ -33,13 +33,6 @@ IMAPPart::~IMAPPart() MC_SAFE_RELEASE(mPartID); } -#if 0 -String * IMAPPart::className() -{ - return MCSTR("IMAPPart"); -} -#endif - Object * IMAPPart::copy() { return new IMAPPart(this); @@ -161,6 +154,7 @@ IMAPMessagePart * IMAPPart::attachmentWithIMAPBody1PartMessage(struct mailimap_b } attachment = new IMAPMessagePart(); + attachment->setPartID(partID); attachment->header()->importIMAPEnvelope(message->bd_envelope); attachment->importIMAPFields(message->bd_fields, extension); @@ -203,7 +197,8 @@ IMAPPart * IMAPPart::attachmentWithIMAPBody1PartBasic(struct mailimap_body_type_ attachment = new IMAPPart(); attachment->importIMAPFields(basic->bd_fields, extension); - + attachment->setUniqueID(mailcore::String::uuidString()); + mimeType = NULL; switch (basic->bd_media_basic->med_type) { case MAILIMAP_MEDIA_BASIC_APPLICATION: @@ -236,6 +231,7 @@ IMAPPart * IMAPPart::attachmentWithIMAPBody1PartText(struct mailimap_body_type_t IMAPPart * attachment; attachment = new IMAPPart(); + attachment->setUniqueID(mailcore::String::uuidString()); attachment->importIMAPFields(text->bd_fields, extension); attachment->setMimeType(String::stringWithUTF8Format("text/%s", text->bd_media_text)); @@ -272,6 +268,7 @@ IMAPMultipart * IMAPPart::attachmentWithIMAPBodyMultipart(struct mailimap_body_t } attachment = new IMAPMultipart(); + attachment->setPartID(partID); if (strcasecmp(body_mpart->bd_media_subtype, "alternative") == 0) { attachment->setPartType(PartTypeMultipartAlternative); } diff --git a/src/core/imap/MCIMAPPart.h b/src/core/imap/MCIMAPPart.h index 2749a0a0..44d03b2f 100644 --- a/src/core/imap/MCIMAPPart.h +++ b/src/core/imap/MCIMAPPart.h @@ -24,20 +24,21 @@ namespace mailcore { virtual void setSize(unsigned int size); virtual unsigned int size(); + virtual unsigned int decodedSize(); + virtual void setEncoding(Encoding encoding); virtual Encoding encoding(); - unsigned int decodedSize(); - - static AbstractPart * attachmentWithIMAPBody(struct mailimap_body * body); - - virtual void importIMAPFields(struct mailimap_body_fields * fields, - struct mailimap_body_ext_1part * extension); - public: // subclass behavior IMAPPart(IMAPPart * other); virtual Object * copy(); + public: // private + static AbstractPart * attachmentWithIMAPBody(struct mailimap_body * body); + + virtual void importIMAPFields(struct mailimap_body_fields * fields, + struct mailimap_body_ext_1part * extension); + private: String * mPartID; Encoding mEncoding; diff --git a/src/core/imap/MCIMAPSearchExpression.cc b/src/core/imap/MCIMAPSearchExpression.cc index 14875c43..55b0fc7f 100644 --- a/src/core/imap/MCIMAPSearchExpression.cc +++ b/src/core/imap/MCIMAPSearchExpression.cc @@ -64,13 +64,6 @@ String * IMAPSearchExpression::description() } } -#if 0 -String * IMAPSearchExpression::className() -{ - return MCSTR("IMAPSearchExpression"); -} -#endif - Object * IMAPSearchExpression::copy() { return new IMAPSearchExpression(this); diff --git a/src/core/imap/MCIMAPSession.cc b/src/core/imap/MCIMAPSession.cc index dd0b6c6c..f79ebc44 100644 --- a/src/core/imap/MCIMAPSession.cc +++ b/src/core/imap/MCIMAPSession.cc @@ -316,13 +316,6 @@ IMAPSession::~IMAPSession() pthread_mutex_destroy(&mIdleLock); } -#if 0 -String * IMAPSession::className() -{ - return MCSTR("IMAPSession"); -} -#endif - void IMAPSession::setHostname(String * hostname) { MC_SAFE_REPLACE_COPY(String, mHostname, hostname); diff --git a/src/core/pop/MCPOPMessageInfo.cc b/src/core/pop/MCPOPMessageInfo.cc index eafbda9f..a1b1dcfe 100644 --- a/src/core/pop/MCPOPMessageInfo.cc +++ b/src/core/pop/MCPOPMessageInfo.cc @@ -27,13 +27,6 @@ POPMessageInfo::~POPMessageInfo() MC_SAFE_RELEASE(mUid); } -#if 0 -String * POPMessageInfo::className() -{ - return MCSTR("POPMessageInfo"); -} -#endif - String * POPMessageInfo::description() { return String::stringWithUTF8Format("<%s:%p %u %s %u>", diff --git a/src/core/pop/MCPOPSession.cc b/src/core/pop/MCPOPSession.cc index 26a0c868..95880198 100644 --- a/src/core/pop/MCPOPSession.cc +++ b/src/core/pop/MCPOPSession.cc @@ -44,13 +44,6 @@ POPSession::~POPSession() MC_SAFE_RELEASE(mPassword); } -#if 0 -String * POPSession::className() -{ - return MCSTR("POPSession"); -} -#endif - void POPSession::setHostname(String * hostname) { MC_SAFE_REPLACE_COPY(String, mHostname, hostname); diff --git a/src/core/renderer/MCAddressDisplay.cpp b/src/core/renderer/MCAddressDisplay.cpp new file mode 100644 index 00000000..842dd0df --- /dev/null +++ b/src/core/renderer/MCAddressDisplay.cpp @@ -0,0 +1,94 @@ +// +// MCAddressUI.cpp +// testUI +// +// Created by DINH Viêt Hoà on 1/27/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCAddressDisplay.h" + +using namespace mailcore; + +String * AddressDisplay::displayStringForAddress(Address * address) +{ + return address->nonEncodedRFC822String(); +} + +String * AddressDisplay::shortDisplayStringForAddress(Address * address) +{ + if ((address->displayName() != NULL) && (address->displayName()->length() > 0)) { + return address->displayName(); + } + else if (address->mailbox()) { + return address->mailbox(); + } + else { + return MCSTR("invalid"); + } +} + +String * AddressDisplay::veryShortDisplayStringForAddress(Address * address) +{ + if ((address->displayName() != NULL) && (address->displayName()->length() > 0)) { + Array * components; + String * senderName; + + senderName = address->displayName(); + senderName = (String *) senderName->copy()->autorelease(); + + senderName->replaceOccurrencesOfString(MCSTR(","), MCSTR(" ")); + senderName->replaceOccurrencesOfString(MCSTR("'"), MCSTR(" ")); + senderName->replaceOccurrencesOfString(MCSTR("\""), MCSTR(" ")); + components = senderName->componentsSeparatedByString(MCSTR(" ")); + if (components->count() == 0) { + return MCLOCALIZEDSTRING(MCSTR("invalid")); + } + return (String *) components->objectAtIndex(0); + } + else if (address->mailbox()) { + return address->mailbox(); + } + else { + return MCLOCALIZEDSTRING(MCSTR("invalid")); + } +} + +String * AddressDisplay::displayStringForAddresses(Array * addresses) +{ + String * result = String::string(); + for(unsigned int i = 0 ; i < addresses->count() ; i ++) { + Address * address = (Address *) addresses->objectAtIndex(i); + if (i != 0) { + result->appendString(MCSTR(", ")); + } + result->appendString(displayStringForAddress(address)); + } + return result; +} + +String * AddressDisplay::shortDisplayStringForAddresses(Array * addresses) +{ + String * result = String::string(); + for(unsigned int i = 0 ; i < addresses->count() ; i ++) { + Address * address = (Address *) addresses->objectAtIndex(i); + if (i != 0) { + result->appendString(MCSTR(", ")); + } + result->appendString(shortDisplayStringForAddress(address)); + } + return result; +} + +String * AddressDisplay::veryShortDisplayStringForAddresses(Array * addresses) +{ + String * result = String::string(); + for(unsigned int i = 0 ; i < addresses->count() ; i ++) { + Address * address = (Address *) addresses->objectAtIndex(i); + if (i != 0) { + result->appendString(MCSTR(", ")); + } + result->appendString(veryShortDisplayStringForAddress(address)); + } + return result; +} diff --git a/src/core/renderer/MCAddressDisplay.h b/src/core/renderer/MCAddressDisplay.h new file mode 100644 index 00000000..153ad245 --- /dev/null +++ b/src/core/renderer/MCAddressDisplay.h @@ -0,0 +1,34 @@ +// +// MCAddressUI.h +// testUI +// +// Created by DINH Viêt Hoà on 1/27/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef __MCAddressDisplay__ +#define __MCAddressDisplay__ + +#include <mailcore/MCAbstract.h> + +#ifdef __cplusplus + +namespace mailcore { + + class AddressDisplay { + + public: + static String * displayStringForAddress(Address * address); + static String * shortDisplayStringForAddress(Address * address); + static String * veryShortDisplayStringForAddress(Address * address); + + static String * displayStringForAddresses(Array * addresses); + static String * shortDisplayStringForAddresses(Array * addresses); + static String * veryShortDisplayStringForAddresses(Array * addresses); + }; + +}; + +#endif + +#endif /* defined(__MCAddressDisplay__) */ diff --git a/src/core/renderer/MCDateFormatter.cpp b/src/core/renderer/MCDateFormatter.cpp new file mode 100644 index 00000000..0fa86699 --- /dev/null +++ b/src/core/renderer/MCDateFormatter.cpp @@ -0,0 +1,160 @@ +// +// MCDateFormatter.cpp +// testUI +// +// Created by DINH Viêt Hoà on 1/28/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCDateFormatter.h" + +using namespace mailcore; + +DateFormatter::DateFormatter() +{ + mDateFormatter = NULL; + mDateStyle = DateFormatStyleMedium; + mTimeStyle = DateFormatStyleMedium; + mDateFormat = NULL; + mTimezone = NULL; + mLocale = NULL; +} + +DateFormatter::~DateFormatter() +{ + if (mDateFormatter != NULL) { + udat_close(mDateFormatter); + } + MC_SAFE_RELEASE(mDateFormat); + MC_SAFE_RELEASE(mTimezone); + MC_SAFE_RELEASE(mLocale); +} + +DateFormatter * DateFormatter::dateFormatter() +{ + DateFormatter * result = new DateFormatter(); + result->autorelease(); + return result; +} + + +void DateFormatter::setDateStyle(DateFormatStyle style) +{ + mDateStyle = style; +} + +DateFormatStyle DateFormatter::dateStyle() +{ + return mDateStyle; +} + +void DateFormatter::setTimeStyle(DateFormatStyle style) +{ + mTimeStyle = style; +} + +DateFormatStyle DateFormatter::timeStyle() +{ + return mTimeStyle; +} + +void DateFormatter::setLocale(String * locale) +{ + MC_SAFE_REPLACE_COPY(String, mLocale, locale); +} + +String * DateFormatter::locale() +{ + return mLocale; +} + +void DateFormatter::setTimezone(String * timezone) +{ + MC_SAFE_REPLACE_COPY(String, mTimezone, timezone); +} + +String * DateFormatter::timezone() +{ + return mTimezone; +} + +void DateFormatter::setDateFormat(String * dateFormat) +{ + MC_SAFE_REPLACE_COPY(String, mDateFormat, dateFormat); +} + +String * DateFormatter::dateFormat() +{ + return mDateFormat; +} + +String * DateFormatter::stringFromDate(time_t date) +{ + prepare(); + if (mDateFormatter == NULL) + return NULL; + + UErrorCode err = U_ZERO_ERROR; + int32_t len = udat_format(mDateFormatter, ((double) date) * 1000., NULL, 0, NULL, &err); + if(err != U_BUFFER_OVERFLOW_ERROR) { + return NULL; + } + + String * result; + + err = U_ZERO_ERROR; + UChar * unichars = (UChar *) malloc((len + 1) * sizeof(unichars)); + udat_format(mDateFormatter, ((double) date) * 1000., unichars, len + 1, NULL, &err); + result = new String(unichars, len); + free(unichars); + + result->autorelease(); + return result; +} + +time_t DateFormatter::dateFromString(String * dateString) +{ + prepare(); + if (mDateFormatter == NULL) + return (time_t) -1; + + UErrorCode err = U_ZERO_ERROR; + UDate date = udat_parse(mDateFormatter, dateString->unicodeCharacters(), dateString->length(), + NULL, &err); + if (err != U_ZERO_ERROR) { + return (time_t) -1; + } + + return date / 1000.; +} + +void DateFormatter::prepare() +{ + if (mDateFormatter != NULL) + return; + + const UChar * tzID = NULL; + int32_t tzIDLength = -1; + const UChar * pattern = NULL; + int32_t patternLength = -1; + UErrorCode err = U_ZERO_ERROR; + const char * locale = NULL; + + if (mTimezone != NULL) { + tzID = mTimezone->unicodeCharacters(); + tzIDLength = mTimezone->length(); + } + if (mDateFormat != NULL) { + pattern = mDateFormat->unicodeCharacters(); + patternLength = mDateFormat->length(); + } + if (mLocale != NULL) { + locale = mLocale->UTF8Characters(); + } + + mDateFormatter = udat_open((UDateFormatStyle) mTimeStyle, (UDateFormatStyle) mDateStyle, + locale, + tzID, tzIDLength, + pattern, patternLength, + &err); +} diff --git a/src/core/renderer/MCDateFormatter.h b/src/core/renderer/MCDateFormatter.h new file mode 100644 index 00000000..6467aae6 --- /dev/null +++ b/src/core/renderer/MCDateFormatter.h @@ -0,0 +1,69 @@ +// +// MCDateFormatter.h +// testUI +// +// Created by DINH Viêt Hoà on 1/28/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef __testUI__MCDateFormatter__ +#define __testUI__MCDateFormatter__ + +#include <mailcore/MCBaseTypes.h> +#include <unicode/udat.h> + +#ifdef __cplusplus + +namespace mailcore { + + class String; + + enum DateFormatStyle { + DateFormatStyleFull = UDAT_FULL, + DateFormatStyleLong = UDAT_LONG, + DateFormatStyleMedium = UDAT_MEDIUM, + DateFormatStyleShort = UDAT_SHORT, + DateFormatStyleNone = UDAT_NONE, + }; + + class DateFormatter : public Object { + public: + DateFormatter(); + virtual ~DateFormatter(); + + static DateFormatter * dateFormatter(); + + virtual void setDateStyle(DateFormatStyle style); + virtual DateFormatStyle dateStyle(); + + virtual void setTimeStyle(DateFormatStyle style); + virtual DateFormatStyle timeStyle(); + + virtual void setLocale(String * locale); + virtual String * locale(); + + virtual void setTimezone(String * timezone); + virtual String * timezone(); + + virtual void setDateFormat(String * dateFormat); + virtual String * dateFormat(); + + virtual String * stringFromDate(time_t date); + virtual time_t dateFromString(String * dateString); + + private: + UDateFormat * mDateFormatter; + DateFormatStyle mDateStyle; + DateFormatStyle mTimeStyle; + String * mDateFormat; + String * mTimezone; + String * mLocale; + + void prepare(); + }; + +} + +#endif + +#endif /* defined(__testUI__MCDateFormatter__) */ diff --git a/src/core/renderer/MCHTMLRenderer.cpp b/src/core/renderer/MCHTMLRenderer.cpp new file mode 100644 index 00000000..ba78656b --- /dev/null +++ b/src/core/renderer/MCHTMLRenderer.cpp @@ -0,0 +1,448 @@ +// +// MCHTMLRenderer.cpp +// testUI +// +// Created by DINH Viêt Hoà on 1/23/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCHTMLRenderer.h" + +#include <ctemplate/template.h> +#include "MCAddressDisplay.h" +#include "MCDateFormatter.h" +#include "MCSizeFormatter.h" +#include "MCHTMLRendererCallback.h" + +using namespace mailcore; + +enum { + RENDER_STATE_NONE, + RENDER_STATE_HAD_ATTACHMENT, + RENDER_STATE_HAD_ATTACHMENT_THEN_TEXT, +}; + +struct htmlRendererContext { + HTMLRendererIMAPCallback * dataCallback; + HTMLRendererTemplateCallback * htmlCallback; + int firstRendered; + String * folder; + int state; + int pass; + bool hasMixedTextAndAttachments; + bool firstAttachment; + bool hasTextPart; +}; + +class DefaultTemplateCallback : public Object, public HTMLRendererTemplateCallback { +}; + +static bool partContainsMimeType(AbstractPart * part, String * mimeType); +static bool singlePartContainsMimeType(AbstractPart * part, String * mimeType); +static bool multipartContainsMimeType(AbstractMultipart * part, String * mimeType); +static bool messagePartContainsMimeType(AbstractMessagePart * part, String * mimeType); + +static String * htmlForAbstractPart(AbstractPart * part, htmlRendererContext * context); + +static String * renderTemplate(String * templateContent, HashMap * values); + +static String * htmlForAbstractMessage(String * folder, AbstractMessage * message, + HTMLRendererIMAPCallback * dataCallback, + HTMLRendererTemplateCallback * htmlCallback); + +static bool isTextPart(AbstractPart * part, htmlRendererContext * context) +{ + String * mimeType = part->mimeType()->lowercaseString(); + MCAssert(mimeType != NULL); + + if (!part->isInlineAttachment()) { + if ((part->filename() != NULL) && context->firstRendered) { + return false; + } + } + + if (mimeType->isEqual(MCSTR("text/plain"))) { + return true; + } + else if (mimeType->isEqual(MCSTR("text/html"))) { + return true; + } + else { + return false; + } +} + + +static AbstractPart * preferredPartInMultipartAlternative(AbstractMultipart * part) +{ + int htmlPart = -1; + int textPart = -1; + + for(unsigned int i = 0 ; i < part->parts()->count() ; i ++) { + AbstractPart * subpart = (AbstractPart *) part->parts()->objectAtIndex(i); + if (partContainsMimeType(subpart, MCSTR("text/html"))) { + htmlPart = i; + } + else if (partContainsMimeType(subpart, MCSTR("text/plain"))) { + textPart = i; + } + } + if (htmlPart != -1) { + return (AbstractPart *) part->parts()->objectAtIndex(htmlPart); + } + else if (textPart != -1) { + return (AbstractPart *) part->parts()->objectAtIndex(textPart); + } + else if (part->parts()->count() > 0) { + return (AbstractPart *) part->parts()->objectAtIndex(0); + } + else { + return NULL; + } +} + +static bool partContainsMimeType(AbstractPart * part, String * mimeType) +{ + switch (part->partType()) { + case PartTypeSingle: + return singlePartContainsMimeType(part, mimeType); + case PartTypeMessage: + return messagePartContainsMimeType((AbstractMessagePart *) part, mimeType); + case PartTypeMultipartMixed: + case PartTypeMultipartRelated: + case PartTypeMultipartAlternative: + return multipartContainsMimeType((AbstractMultipart *) part, mimeType); + default: + return false; + } +} + +static bool singlePartContainsMimeType(AbstractPart * part, String * mimeType) +{ + return part->mimeType()->lowercaseString()->isEqual(mimeType); +} + +static bool multipartContainsMimeType(AbstractMultipart * part, String * mimeType) +{ + for(unsigned int i = 0 ; i < part->parts()->count() ; i ++) { + AbstractPart * subpart = (AbstractPart *) part->parts()->objectAtIndex(i); + if (partContainsMimeType(subpart, mimeType)) { + return true; + } + } + return false; +} + +static bool messagePartContainsMimeType(AbstractMessagePart * part, String * mimeType) +{ + return partContainsMimeType(part->mainPart(), mimeType); +} + +static String * htmlForAbstractMessage(String * folder, AbstractMessage * message, + HTMLRendererIMAPCallback * dataCallback, + HTMLRendererTemplateCallback * htmlCallback) +{ + AbstractPart * mainPart = NULL; + + if (htmlCallback == NULL) { + htmlCallback = new DefaultTemplateCallback(); + ((DefaultTemplateCallback *) htmlCallback)->autorelease(); + } + + if (message->className()->isEqual(MCSTR("mailcore::IMAPMessage"))) { + mainPart = ((IMAPMessage *) message)->mainPart(); + } + else if (message->className()->isEqual(MCSTR("mailcore::MessageParser"))) { + mainPart = ((MessageParser *) message)->mainPart(); + } + MCAssert(mainPart != NULL); + + htmlRendererContext context; + context.dataCallback = dataCallback; + context.htmlCallback = htmlCallback; + context.firstRendered = 0; + context.folder = folder; + context.state = RENDER_STATE_NONE; + + context.hasMixedTextAndAttachments = false; + context.pass = 0; + context.firstAttachment = false; + context.hasTextPart = false; + htmlForAbstractPart(mainPart, &context); + + context.hasMixedTextAndAttachments = (context.state == RENDER_STATE_HAD_ATTACHMENT_THEN_TEXT); + context.pass = 1; + context.firstAttachment = false; + context.hasTextPart = false; + String * content = htmlForAbstractPart(mainPart, &context); + if (content == NULL) + return NULL; + + content = htmlCallback->filterHTMLForMessage(content); + + HashMap * values = htmlCallback->templateValuesForHeader(message->header()); + String * headerString = renderTemplate(htmlCallback->templateForMainHeader(), values); + + HashMap * msgValues = new HashMap(); + msgValues->setObjectForKey(MCSTR("HEADER"), headerString); + msgValues->setObjectForKey(MCSTR("BODY"), content); + String * result = renderTemplate(htmlCallback->templateForMessage(), msgValues); + msgValues->release(); + + return result; +} + +String * htmlForAbstractSinglePart(AbstractPart * part, htmlRendererContext * context); +String * htmlForAbstractMessagePart(AbstractMessagePart * part, htmlRendererContext * context); +String * htmlForAbstractMultipartRelated(AbstractMultipart * part, htmlRendererContext * context); +String * htmlForAbstractMultipartMixed(AbstractMultipart * part, htmlRendererContext * context); +String * htmlForAbstractMultipartAlternative(AbstractMultipart * part, htmlRendererContext * context); + +String * htmlForAbstractPart(AbstractPart * part, htmlRendererContext * context) +{ + switch (part->partType()) { + case PartTypeSingle: + return htmlForAbstractSinglePart((AbstractPart *) part, context); + case PartTypeMessage: + return htmlForAbstractMessagePart((AbstractMessagePart *) part, context); + case PartTypeMultipartMixed: + return htmlForAbstractMultipartMixed((AbstractMultipart *) part, context); + case PartTypeMultipartRelated: + return htmlForAbstractMultipartRelated((AbstractMultipart *) part, context); + case PartTypeMultipartAlternative: + return htmlForAbstractMultipartAlternative((AbstractMultipart *) part, context); + default: + MCAssert(0); + } + return NULL; +} + +String * htmlForAbstractSinglePart(AbstractPart * part, htmlRendererContext * context) +{ + String * mimeType = part->mimeType()->lowercaseString(); + MCAssert(mimeType != NULL); + + if (isTextPart(part, context)) { + if (context->pass == 0) { + if (context->state == RENDER_STATE_HAD_ATTACHMENT) { + context->state = RENDER_STATE_HAD_ATTACHMENT_THEN_TEXT; + } + return NULL; + } + + context->hasTextPart = true; + + if (mimeType->isEqual(MCSTR("text/plain"))) { + String * charset = part->charset(); + Data * data = NULL; + if (part->className()->isEqual(MCSTR("mailcore::IMAPPart"))) { + data = context->dataCallback->dataForIMAPPart(context->folder, (IMAPPart *) part); + } + else if (part->className()->isEqual(MCSTR("mailcore::Attachment"))) { + data = ((Attachment *) part)->data(); + MCAssert(data != NULL); + } + if (data == NULL) + return NULL; + + String * str = data->stringWithDetectedCharset(charset, false); + context->firstRendered = true; + return str->htmlEncodedString(); + } + else if (mimeType->isEqual(MCSTR("text/html"))) { + String * charset = part->charset(); + Data * data = NULL; + if (part->className()->isEqual(MCSTR("mailcore::IMAPPart"))) { + data = context->dataCallback->dataForIMAPPart(context->folder, (IMAPPart *) part); + } + else if (part->className()->isEqual(MCSTR("mailcore::Attachment"))) { + data = ((Attachment *) part)->data(); + MCAssert(data != NULL); + } + if (data == NULL) + return NULL; + + String * str = data->stringWithDetectedCharset(charset, true); + str = str->cleanedHTMLString(); + str = context->htmlCallback->filterHTMLForPart(str); + context->firstRendered = true; + return str; + } + else { + MCAssert(0); + return NULL; + } + } + else { + if (context->pass == 0) { + if (context->state == RENDER_STATE_NONE) { + context->state = RENDER_STATE_HAD_ATTACHMENT; + } + return NULL; + } + + if (part->uniqueID() == NULL) { + part->setUniqueID(String::uuidString()); + } + + String * result = String::string(); + String * separatorString; + String * content; + + if (!context->firstAttachment && context->hasTextPart) { + separatorString = context->htmlCallback->templateForAttachmentSeparator(); + } + else { + separatorString = MCSTR(""); + } + + context->firstAttachment = true; + + if (context->htmlCallback->canPreviewPart(part)) { + if (part->className()->isEqual(MCSTR("mailcore::IMAPPart"))) { + context->dataCallback->prefetchImageIMAPPart(context->folder, (IMAPPart *) part); + } + String * url = String::stringWithUTF8Format("x-mailcore-image:%s", + part->uniqueID()->UTF8Characters()); + HashMap * values = context->htmlCallback->templateValuesForPart(part); + values->setObjectForKey(MCSTR("URL"), url); + content = renderTemplate(context->htmlCallback->templateForImage(), values); + } + else { + if (part->className()->isEqual(MCSTR("mailcore::IMAPPart"))) { + context->dataCallback->prefetchAttachmentIMAPPart(context->folder, (IMAPPart *) part); + } + HashMap * values = context->htmlCallback->templateValuesForPart(part); + content = renderTemplate(context->htmlCallback->templateForAttachment(), values); + } + + result->appendString(separatorString); + result->appendString(content); + + return result; + } +} + +String * htmlForAbstractMessagePart(AbstractMessagePart * part, htmlRendererContext * context) +{ + String * substring = htmlForAbstractPart(part->mainPart(), context); + if (context->pass == 0) { + return NULL; + } + MCAssert(substring != NULL); + + String * result = String::string(); + HashMap * values = context->htmlCallback->templateValuesForHeader(part->header()); + String * headerString = renderTemplate(context->htmlCallback->templateForMainHeader(), values); + result->appendString(headerString); + result->appendString(substring); + return result; +} + +String * htmlForAbstractMultipartAlternative(AbstractMultipart * part, htmlRendererContext * context) +{ + AbstractPart * preferredAlternative = preferredPartInMultipartAlternative(part); + if (preferredAlternative == NULL) + return MCSTR(""); + + return htmlForAbstractPart(preferredAlternative, context); +} + +String * htmlForAbstractMultipartMixed(AbstractMultipart * part, htmlRendererContext * context) +{ + String * result = String::string(); + for(unsigned int i = 0 ; i < part->parts()->count() ; i ++) { + AbstractPart * subpart = (AbstractPart *) part->parts()->objectAtIndex(i); + String * substring = htmlForAbstractPart(subpart, context); + if (context->pass != 0) { + if (substring == NULL) + return NULL; + + result->appendString(substring); + } + } + return result; +} + +String * htmlForAbstractMultipartRelated(AbstractMultipart * part, htmlRendererContext * context) +{ + if (part->parts()->count() == 0) { + if (context->pass == 0) { + return NULL; + } + else { + return MCSTR(""); + } + } + + AbstractPart * subpart = (AbstractPart *) part->parts()->objectAtIndex(0); + return htmlForAbstractPart(subpart, context); +} + +void fillTemplateDictionaryFromMCHashMap(ctemplate::TemplateDictionary * dict, HashMap * mcHashMap) +{ + Array * keys = mcHashMap->allKeys(); + + for(unsigned int i = 0 ; i < keys->count() ; i ++) { + String * key = (String *) keys->objectAtIndex(i); + Object * value; + + value = mcHashMap->objectForKey(key); + if (value->className()->isEqual(MCSTR("mailcore::String"))) { + String * str; + + str = (String *) value; + dict->SetValue(key->UTF8Characters(), str->UTF8Characters()); + } + else if (value->className()->isEqual(MCSTR("mailcore::Array"))) { + Array * array; + + array = (Array *) value; + for(unsigned int k = 0 ; k < array->count() ; k ++) { + HashMap * item = (HashMap *) array->objectAtIndex(k); + ctemplate::TemplateDictionary * subDict = dict->AddSectionDictionary(key->UTF8Characters()); + fillTemplateDictionaryFromMCHashMap(subDict, item); + } + } + else if (value->className()->isEqual(MCSTR("mailcore::HashMap"))) { + ctemplate::TemplateDictionary * subDict; + HashMap * item; + + item = (HashMap *) value; + subDict = dict->AddSectionDictionary(key->UTF8Characters()); + fillTemplateDictionaryFromMCHashMap(subDict, item); + } + } +} + +String * renderTemplate(String * templateContent, HashMap * values) +{ + ctemplate::TemplateDictionary dict("template dict"); + std::string output; + Data * data; + + fillTemplateDictionaryFromMCHashMap(&dict, values); + data = templateContent->dataUsingEncoding("utf-8"); + ctemplate::Template * tpl = ctemplate::Template::StringToTemplate(data->bytes(), data->length(), ctemplate::DO_NOT_STRIP); + if (tpl == NULL) + return NULL; + if (!tpl->Expand(&output, &dict)) + return NULL; + delete tpl; + + return String::stringWithUTF8Characters(output.c_str()); +} + +String * HTMLRenderer::htmlForRFC822Message(MessageParser * message, + HTMLRendererTemplateCallback * htmlCallback) +{ + return htmlForAbstractMessage(NULL, message, NULL, htmlCallback); +} + +String * HTMLRenderer::htmlForIMAPMessage(String * folder, + IMAPMessage * message, + HTMLRendererIMAPCallback * dataCallback, + HTMLRendererTemplateCallback * htmlCallback) +{ + return htmlForAbstractMessage(folder, message, dataCallback, htmlCallback); +} diff --git a/src/core/renderer/MCHTMLRenderer.h b/src/core/renderer/MCHTMLRenderer.h new file mode 100644 index 00000000..042625cf --- /dev/null +++ b/src/core/renderer/MCHTMLRenderer.h @@ -0,0 +1,38 @@ +// +// MCHTMLRenderer.h +// testUI +// +// Created by DINH Viêt Hoà on 1/23/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef __testUI__MCHTMLRenderer__ +#define __testUI__MCHTMLRenderer__ + +#include <mailcore/MCAbstract.h> +#include <mailcore/MCIMAP.h> +#include <mailcore/MCRFC822.h> + +#ifdef __cplusplus + +namespace mailcore { + + class MessageParser; + class HTMLRendererTemplateCallback; + class HTMLRendererIMAPCallback; + + class HTMLRenderer { + public: + static String * htmlForRFC822Message(MessageParser * message, + HTMLRendererTemplateCallback * htmlCallback); + + static String * htmlForIMAPMessage(String * folder, + IMAPMessage * message, + HTMLRendererIMAPCallback * dataCallback, + HTMLRendererTemplateCallback * htmlCallback); + }; +}; + +#endif + +#endif /* defined(__testUI__MCHTMLRenderer__) */ diff --git a/src/core/renderer/MCHTMLRendererCallback.cpp b/src/core/renderer/MCHTMLRendererCallback.cpp new file mode 100644 index 00000000..3ceaeb40 --- /dev/null +++ b/src/core/renderer/MCHTMLRendererCallback.cpp @@ -0,0 +1,259 @@ +// +// MCHTMLRendererCallback.cpp +// mailcore2 +// +// Created by DINH Viêt Hoà on 2/2/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCHTMLRendererCallback.h" + +#include "MCAddressDisplay.h" +#include "MCDateFormatter.h" +#include "MCSizeFormatter.h" +#include "MCAttachment.h" + +using namespace mailcore; + +mailcore::HashMap * HTMLRendererTemplateCallback::templateValuesForHeader(mailcore::MessageHeader * header) +{ + mailcore::HashMap * result = mailcore::HashMap::hashMap(); + + if (header->from() != NULL) { + result->setObjectForKey(MCSTR("HASFROM"), mailcore::HashMap::hashMap()); + result->setObjectForKey(MCSTR("FROM"), mailcore::AddressDisplay::displayStringForAddress(header->from())->htmlEncodedString()); + result->setObjectForKey(MCSTR("SHORTFROM"), mailcore::AddressDisplay::shortDisplayStringForAddress(header->from())->htmlEncodedString()); + result->setObjectForKey(MCSTR("VERYSHORTFROM"), mailcore::AddressDisplay::veryShortDisplayStringForAddress(header->from())->htmlEncodedString()); + } + else { + result->setObjectForKey(MCSTR("NOFROM"), mailcore::HashMap::hashMap()); + } + + if ((header->to() != NULL) && (header->to()->count() > 0)) { + result->setObjectForKey(MCSTR("HASTO"), mailcore::HashMap::hashMap()); + result->setObjectForKey(MCSTR("TO"), mailcore::AddressDisplay::displayStringForAddresses(header->to())->htmlEncodedString()); + result->setObjectForKey(MCSTR("SHORTTO"), mailcore::AddressDisplay::shortDisplayStringForAddresses(header->to())->htmlEncodedString()); + result->setObjectForKey(MCSTR("VERYSHORTTO"), mailcore::AddressDisplay::veryShortDisplayStringForAddresses(header->to())->htmlEncodedString()); + } + else { + result->setObjectForKey(MCSTR("NOTO"), mailcore::HashMap::hashMap()); + } + + if ((header->cc() != NULL) && (header->cc()->count() > 0)) { + result->setObjectForKey(MCSTR("HASCC"), mailcore::HashMap::hashMap()); + result->setObjectForKey(MCSTR("CC"), mailcore::AddressDisplay::displayStringForAddresses(header->cc())->htmlEncodedString()); + result->setObjectForKey(MCSTR("SHORTCC"), mailcore::AddressDisplay::shortDisplayStringForAddresses(header->cc())->htmlEncodedString()); + result->setObjectForKey(MCSTR("VERYSHORTCC"), mailcore::AddressDisplay::veryShortDisplayStringForAddresses(header->cc())->htmlEncodedString()); + } + else { + result->setObjectForKey(MCSTR("NOCC"), mailcore::HashMap::hashMap()); + } + + if ((header->bcc() != NULL) && (header->bcc()->count() > 0)) { + result->setObjectForKey(MCSTR("HASBCC"), mailcore::HashMap::hashMap()); + result->setObjectForKey(MCSTR("BCC"), mailcore::AddressDisplay::displayStringForAddresses(header->bcc())->htmlEncodedString()); + result->setObjectForKey(MCSTR("SHORTBCC"), mailcore::AddressDisplay::shortDisplayStringForAddresses(header->bcc())->htmlEncodedString()); + result->setObjectForKey(MCSTR("VERYSHORTBCC"), mailcore::AddressDisplay::veryShortDisplayStringForAddresses(header->bcc())->htmlEncodedString()); + } + else { + result->setObjectForKey(MCSTR("NOBCC"), mailcore::HashMap::hashMap()); + } + + mailcore::Array * recipient = new mailcore::Array(); + recipient->addObjectsFromArray(header->to()); + recipient->addObjectsFromArray(header->cc()); + recipient->addObjectsFromArray(header->bcc()); + + if (recipient->count() > 0) { + result->setObjectForKey(MCSTR("HASRECIPIENT"), mailcore::HashMap::hashMap()); + result->setObjectForKey(MCSTR("RECIPIENT"), mailcore::AddressDisplay::displayStringForAddresses(recipient)->htmlEncodedString()); + result->setObjectForKey(MCSTR("SHORTRECIPIENT"), mailcore::AddressDisplay::shortDisplayStringForAddresses(recipient)->htmlEncodedString()); + result->setObjectForKey(MCSTR("VERYSHORTRECIPIENT"), mailcore::AddressDisplay::veryShortDisplayStringForAddresses(recipient)->htmlEncodedString()); + } + else { + result->setObjectForKey(MCSTR("NORECIPIENT"), mailcore::HashMap::hashMap()); + } + recipient->release(); + + if ((header->replyTo() != NULL) && (header->replyTo()->count() > 0)) { + result->setObjectForKey(MCSTR("HASREPLYTO"), mailcore::HashMap::hashMap()); + result->setObjectForKey(MCSTR("REPLYTO"), mailcore::AddressDisplay::displayStringForAddresses(header->replyTo())->htmlEncodedString()); + result->setObjectForKey(MCSTR("SHORTREPLYTO"), mailcore::AddressDisplay::shortDisplayStringForAddresses(header->replyTo())->htmlEncodedString()); + result->setObjectForKey(MCSTR("VERYSHORTREPLYTO"), mailcore::AddressDisplay::veryShortDisplayStringForAddresses(header->replyTo())->htmlEncodedString()); + } + else { + result->setObjectForKey(MCSTR("NOREPLYTO"), mailcore::HashMap::hashMap()); + } + + if ((header->subject() != NULL) && (header->subject()->length() > 0)) { + result->setObjectForKey(MCSTR("EXTRACTEDSUBJECT"), header->partialExtractedSubject()->htmlEncodedString()); + result->setObjectForKey(MCSTR("SUBJECT"), header->subject()->htmlEncodedString()); + result->setObjectForKey(MCSTR("HASSUBJECT"), mailcore::HashMap::hashMap()); + } + else { + result->setObjectForKey(MCSTR("NOSUBJECT"), mailcore::HashMap::hashMap()); + } + + mailcore::String * dateString; + static mailcore::DateFormatter * fullFormatter = NULL; + if (fullFormatter == NULL) { + fullFormatter = new mailcore::DateFormatter(); + fullFormatter->setDateStyle(mailcore::DateFormatStyleFull); + fullFormatter->setTimeStyle(mailcore::DateFormatStyleFull); + } + dateString = fullFormatter->stringFromDate(header->date()); + if (dateString != NULL) { + result->setObjectForKey(MCSTR("FULLDATE"), dateString->htmlEncodedString()); + } + static mailcore::DateFormatter * longFormatter = NULL; + if (longFormatter == NULL) { + longFormatter = new mailcore::DateFormatter(); + longFormatter->setDateStyle(mailcore::DateFormatStyleLong); + longFormatter->setTimeStyle(mailcore::DateFormatStyleLong); + } + dateString = longFormatter->stringFromDate(header->date()); + if (dateString != NULL) { + result->setObjectForKey(MCSTR("LONGDATE"), dateString->htmlEncodedString()); + } + static mailcore::DateFormatter * mediumFormatter = NULL; + if (mediumFormatter == NULL) { + mediumFormatter = new mailcore::DateFormatter(); + mediumFormatter->setDateStyle(mailcore::DateFormatStyleMedium); + mediumFormatter->setTimeStyle(mailcore::DateFormatStyleMedium); + } + dateString = mediumFormatter->stringFromDate(header->date()); + if (dateString != NULL) { + result->setObjectForKey(MCSTR("MEDIUMDATE"), dateString->htmlEncodedString()); + } + static mailcore::DateFormatter * shortFormatter = NULL; + if (shortFormatter == NULL) { + shortFormatter = new mailcore::DateFormatter(); + shortFormatter->setDateStyle(mailcore::DateFormatStyleShort); + shortFormatter->setTimeStyle(mailcore::DateFormatStyleShort); + } + dateString = shortFormatter->stringFromDate(header->date()); + if (dateString != NULL) { + result->setObjectForKey(MCSTR("SHORTDATE"), dateString->htmlEncodedString()); + } + + return result; +} + +mailcore::HashMap * HTMLRendererTemplateCallback::templateValuesForPart(mailcore::AbstractPart * part) +{ + mailcore::HashMap * result = mailcore::HashMap::hashMap(); + mailcore::String * filename = NULL; + + if (part->filename() != NULL) { + filename = part->filename()->lastPathComponent(); + } + + if (filename != NULL) { + result->setObjectForKey(MCSTR("FILENAME"), filename->htmlEncodedString()); + } + + if (part->className()->isEqual(MCSTR("mailcore::IMAPPart"))) { + mailcore::IMAPPart * imapPart = (mailcore::IMAPPart *) part; + mailcore::String * value = mailcore::SizeFormatter::stringWithSize(imapPart->size()); + result->setObjectForKey(MCSTR("SIZE"), value); + result->setObjectForKey(MCSTR("HASSIZE"), mailcore::HashMap::hashMap()); + } + else if (part->className()->isEqual(MCSTR("mailcore::Attachment"))) { + mailcore::Attachment * attachment = (mailcore::Attachment *) part; + mailcore::String * value = mailcore::SizeFormatter::stringWithSize(attachment->data()->length()); + result->setObjectForKey(MCSTR("SIZE"), value); + result->setObjectForKey(MCSTR("HASSIZE"), mailcore::HashMap::hashMap()); + } + else { + result->setObjectForKey(MCSTR("NOSIZE"), mailcore::HashMap::hashMap()); + } + + if (part->contentID() != NULL) { + result->setObjectForKey(MCSTR("CONTENTID"), part->contentID()); + } + if (part->uniqueID() != NULL) { + result->setObjectForKey(MCSTR("UNIQUEID"), part->uniqueID()); + } + + return result; +} + +mailcore::String * HTMLRendererTemplateCallback::templateForMainHeader() +{ + return MCSTR("<div style=\"background-color:#eee\">\ + {{#HASFROM}}\ + <div><b>From:</b> {{FROM}}</div>\ + {{/HASFROM}}\ + {{#HASTO}}\ + <div><b>To:</b> {{TO}}</div>\ + {{/HASTO}}\ + {{#HASCC}}\ + <div><b>Cc:</b> {{CC}}</div>\ + {{/HASCC}}\ + {{#HASBCC}}\ + <div><b>Bcc:</b> {{BCC}}</div>\ + {{/HASBCC}}\ + {{#NORECIPIENT}}\ + <div><b>To:</b> <i>Undisclosed recipient</i></div>\ + {{/NORECIPIENT}}\ + {{#HASSUBJECT}}\ + <div><b>Subject:</b> {{EXTRACTEDSUBJECT}}</div>\ + {{/HASSUBJECT}}\ + {{#NOSUBJECT}}\ + <div><b>Subject:</b> <i>No Subject</i></div>\ + {{/NOSUBJECT}}\ + <div><b>Date:</b> {{LONGDATE}}</div>\ + </div>"); +} + +mailcore::String * HTMLRendererTemplateCallback::templateForHeader() +{ + return templateForMainHeader(); +} + +mailcore::String * HTMLRendererTemplateCallback::templateForImage() +{ + return MCSTR(""); +} + +mailcore::String * HTMLRendererTemplateCallback::templateForAttachment() +{ + return MCSTR("{{#HASSIZE}}\ + <div>- {{FILENAME}}, {{SIZE}}</div>\ + {{/HASSIZE}}\ + {{#NOSIZE}}\ + <div>- {{FILENAME}}</div>\ + {{/NOSIZE}}\ + "); +} + +mailcore::String * HTMLRendererTemplateCallback::templateForMessage() +{ + return MCSTR("<div style=\"padding-bottom: 20px;\">{{HEADER}}</div><div>{{BODY}}</div>"); +} + + +mailcore::String * HTMLRendererTemplateCallback::templateForEmbeddedMessage() +{ + return templateForMessage(); +} + +mailcore::String * HTMLRendererTemplateCallback::templateForAttachmentSeparator() +{ + return MCSTR("<hr/>"); +} + +mailcore::String * HTMLRendererTemplateCallback::filterHTMLForMessage(mailcore::String * html) +{ + return html; +} + +mailcore::String * HTMLRendererTemplateCallback::filterHTMLForPart(mailcore::String * html) +{ + return html; +} + +bool HTMLRendererTemplateCallback::canPreviewPart(AbstractPart * part) +{ + return false; +} diff --git a/src/core/renderer/MCHTMLRendererCallback.h b/src/core/renderer/MCHTMLRendererCallback.h new file mode 100644 index 00000000..2972249e --- /dev/null +++ b/src/core/renderer/MCHTMLRendererCallback.h @@ -0,0 +1,51 @@ +// +// MCHTMLRendererCallback.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 2/2/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef __mailcore2__MCHTMLRendererCallback__ +#define __mailcore2__MCHTMLRendererCallback__ + +#include <mailcore/MCAbstract.h> +#include <mailcore/MCIMAP.h> + +#ifdef __cplusplus + +namespace mailcore { + + class MessageParser; + + class HTMLRendererIMAPCallback { + public: + virtual Data * dataForIMAPPart(String * folder, IMAPPart * part) { return NULL; } + virtual void prefetchAttachmentIMAPPart(String * folder, IMAPPart * part) {} + virtual void prefetchImageIMAPPart(String * folder, IMAPPart * part) {} + }; + + class HTMLRendererTemplateCallback { + public: + virtual bool canPreviewPart(AbstractPart * part); + + virtual HashMap * templateValuesForHeader(MessageHeader * header); + virtual HashMap * templateValuesForPart(AbstractPart * part); + + virtual String * templateForMainHeader(); + virtual String * templateForHeader(); + virtual String * templateForImage(); + virtual String * templateForAttachment(); + virtual String * templateForMessage(); + virtual String * templateForEmbeddedMessage(); + virtual String * templateForAttachmentSeparator(); + + virtual String * filterHTMLForPart(String * html); + virtual String * filterHTMLForMessage(String * html); + }; + +} + +#endif + +#endif /* defined(__mailcore2__MCHTMLRendererCallback__) */ diff --git a/src/core/renderer/MCRenderer.h b/src/core/renderer/MCRenderer.h new file mode 100644 index 00000000..65999f95 --- /dev/null +++ b/src/core/renderer/MCRenderer.h @@ -0,0 +1,14 @@ +// +// MCRenderer.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 2/2/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef mailcore2_MCRenderer_h +#define mailcore2_MCRenderer_h + +#include <mailcore/MCHTMLRendererCallback.h> + +#endif diff --git a/src/core/renderer/MCSizeFormatter.cpp b/src/core/renderer/MCSizeFormatter.cpp new file mode 100644 index 00000000..f0823075 --- /dev/null +++ b/src/core/renderer/MCSizeFormatter.cpp @@ -0,0 +1,43 @@ +// +// MCSizeFormatter.cpp +// testUI +// +// Created by DINH Viêt Hoà on 1/29/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCSizeFormatter.h" + +#include <math.h> + +using namespace mailcore; + +String * SizeFormatter::stringWithSize(unsigned int size) +{ + double divider; + String * unit; + + if (size >= 1024 * 1024 * 1024) { + divider = 1024 * 1024 * 1024; + unit = MCLOCALIZEDSTRING(MCSTR("GB")); + } + else if (size >= 1024 * 1024) { + divider = 1024 * 1024; + unit = MCLOCALIZEDSTRING(MCSTR("MB")); + } + else if (size >= 1024) { + divider = 1024; + unit = MCLOCALIZEDSTRING(MCSTR("KB")); + } + else { + divider = 1; + unit = MCLOCALIZEDSTRING(MCSTR("bytes")); + } + + if ((size / divider) - round(size / divider) < 0.1) { + return String::stringWithUTF8Format("%.0f %s", size / divider, unit->UTF8Characters()); + } + else { + return String::stringWithUTF8Format("%.1f %s", size / divider, unit->UTF8Characters()); + } +} diff --git a/src/core/renderer/MCSizeFormatter.h b/src/core/renderer/MCSizeFormatter.h new file mode 100644 index 00000000..a6c74010 --- /dev/null +++ b/src/core/renderer/MCSizeFormatter.h @@ -0,0 +1,28 @@ +// +// MCSizeFormatter.h +// testUI +// +// Created by DINH Viêt Hoà on 1/29/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef __testUI__MCSizeFormatter__ +#define __testUI__MCSizeFormatter__ + +#include <mailcore/MCBaseTypes.h> + +#ifdef __cplusplus + +namespace mailcore { + class String; + + class SizeFormatter : public Object { + public: + static String * stringWithSize(unsigned int size); + }; + +} + +#endif + +#endif /* defined(__testUI__MCSizeFormatter__) */ diff --git a/src/core/rfc822/MCAttachment.cc b/src/core/rfc822/MCAttachment.cc index 91b8fde3..7926baa9 100644 --- a/src/core/rfc822/MCAttachment.cc +++ b/src/core/rfc822/MCAttachment.cc @@ -231,13 +231,6 @@ String * Attachment::description() return result; } -#if 0 -String * Attachment::className() -{ - return MCSTR("Attachment"); -} -#endif - Object * Attachment::copy() { return new Attachment(this); @@ -464,6 +457,8 @@ Attachment * Attachment::attachmentWithSingleMIME(struct mailmime * mime) MCAssert(mime->mm_type == MAILMIME_SINGLE); result = new Attachment(); + result->setUniqueID(mailcore::String::uuidString()); + data = mime->mm_data.mm_single; bytes = data->dt_data.dt_text.dt_data; length = data->dt_data.dt_text.dt_length; diff --git a/src/core/rfc822/MCAttachment.h b/src/core/rfc822/MCAttachment.h index 0be168aa..ac12a5b5 100644 --- a/src/core/rfc822/MCAttachment.h +++ b/src/core/rfc822/MCAttachment.h @@ -27,13 +27,14 @@ namespace mailcore { virtual void setData(Data * data); virtual Data * data(); - static AbstractPart * attachmentsWithMIME(struct mailmime * mime); - public: // subclass behavior Attachment(Attachment * other); virtual String * description(); virtual Object * copy(); + public: // private + static AbstractPart * attachmentsWithMIME(struct mailmime * mime); + private: Data * mData; void init(); diff --git a/src/core/rfc822/MCMessageBuilder.cc b/src/core/rfc822/MCMessageBuilder.cc index 62482564..07febfbb 100644 --- a/src/core/rfc822/MCMessageBuilder.cc +++ b/src/core/rfc822/MCMessageBuilder.cc @@ -524,13 +524,6 @@ String * MessageBuilder::description() return result; } -#if 0 -String * MessageBuilder::className() -{ - return MCSTR("MessageBuilder"); -} -#endif - Object * MessageBuilder::copy() { return new MessageBuilder(this); diff --git a/src/core/rfc822/MCMessageParser.cc b/src/core/rfc822/MCMessageParser.cc index f301ce3e..a0dcf142 100644 --- a/src/core/rfc822/MCMessageParser.cc +++ b/src/core/rfc822/MCMessageParser.cc @@ -2,6 +2,7 @@ #include "MCAttachment.h" #include "MCMessageHeader.h" +#include "MCHTMLRenderer.h" using namespace mailcore; @@ -69,14 +70,23 @@ String * MessageParser::description() return result; } -#if 0 -String * MessageParser::className() +Object * MessageParser::copy() { - return MCSTR("MessageParser"); + return new MessageParser(this); } -#endif -Object * MessageParser::copy() +AbstractPart * MessageParser::partForContentID(String * contentID) { - return new MessageParser(this); + return mainPart()->partForContentID(contentID); } + +AbstractPart * MessageParser::partForUniqueID(String * uniqueID) +{ + return mainPart()->partForUniqueID(uniqueID); +} + +String * MessageParser::htmlRendering(HTMLRendererTemplateCallback * htmlCallback) +{ + return HTMLRenderer::htmlForRFC822Message(this, htmlCallback); +} + diff --git a/src/core/rfc822/MCMessageParser.h b/src/core/rfc822/MCMessageParser.h index 06673ec4..ff2f1f50 100644 --- a/src/core/rfc822/MCMessageParser.h +++ b/src/core/rfc822/MCMessageParser.h @@ -10,6 +10,8 @@ namespace mailcore { + class HTMLRendererTemplateCallback; + class MessageParser : public AbstractMessage { public: static MessageParser * messageParserWithData(Data * data); @@ -20,6 +22,11 @@ namespace mailcore { virtual AbstractPart * mainPart(); virtual Data * data(); + virtual AbstractPart * partForContentID(String * contentID); + virtual AbstractPart * partForUniqueID(String * uniqueID); + + virtual String * htmlRendering(HTMLRendererTemplateCallback * htmlCallback = NULL); + public: // subclass behavior MessageParser(MessageParser * other); virtual String * description(); diff --git a/src/core/rfc822/MCMessagePart.cc b/src/core/rfc822/MCMessagePart.cc index 8a2122c3..21d61181 100644 --- a/src/core/rfc822/MCMessagePart.cc +++ b/src/core/rfc822/MCMessagePart.cc @@ -14,13 +14,6 @@ MessagePart::~MessagePart() { } -#if 0 -String * MessagePart::className() -{ - return MCSTR("MessagePart"); -} -#endif - Object * MessagePart::copy() { return new MessagePart(this); diff --git a/src/core/rfc822/MCMultipart.cc b/src/core/rfc822/MCMultipart.cc index 6ab1f0db..e048669e 100644 --- a/src/core/rfc822/MCMultipart.cc +++ b/src/core/rfc822/MCMultipart.cc @@ -14,13 +14,6 @@ Multipart::~Multipart() { } -#if 0 -String * Multipart::className() -{ - return MCSTR("Multipart"); -} -#endif - Object * Multipart::copy() { return new Multipart(this); diff --git a/src/core/smtp/MCSMTPSession.cc b/src/core/smtp/MCSMTPSession.cc index 12066146..96bd9787 100644 --- a/src/core/smtp/MCSMTPSession.cc +++ b/src/core/smtp/MCSMTPSession.cc @@ -51,13 +51,6 @@ SMTPSession::~SMTPSession() MCLog("dealloc4"); } -#if 0 -String * SMTPSession::className() -{ - return MCSTR("SMTPSession"); -} -#endif - void SMTPSession::setHostname(String * hostname) { MC_SAFE_REPLACE_COPY(String, mHostname, hostname); diff --git a/src/objc/MCOConstants.h b/src/objc/MCOConstants.h index 355fceb3..257b0d68 100644 --- a/src/objc/MCOConstants.h +++ b/src/objc/MCOConstants.h @@ -1,3 +1,7 @@ +#ifndef __MAILCORE_MCOCONSTANTS_H_ + +#define __MAILCORE_MCOCONSTANTS_H_ + typedef enum { MCOConnectionTypeClear = 1 << 0, MCOConnectionTypeStartTLS = 1 << 1, @@ -15,3 +19,5 @@ typedef enum { MCOAuthTypeSASLNTLM = 1 << 6, MCOAuthTypeSASLKerberosV4 = 1 << 7, } MCOAuthType; + +#endif diff --git a/src/objc/MCObjC.h b/src/objc/MCObjC.h index 364d5692..8468d298 100644 --- a/src/objc/MCObjC.h +++ b/src/objc/MCObjC.h @@ -14,11 +14,16 @@ #import <mailcore/MCOObjectWrapper.h> #import <mailcore/NSData+MCO.h> #import <mailcore/NSString+MCO.h> +#import <mailcore/NSDictionary+MCO.h> +#import <mailcore/NSArray+MCO.h> +#import <mailcore/NSObject+MCO.h> +#import <mailcore/MCOObjectWrapper.h> #import <mailcore/NSError+MCO.h> #import <mailcore/MCOIMAPSession.h> #import <mailcore/MCOOperation.h> #import <mailcore/MCOCheckAccountOperation.h> - +#import <mailcore/MCOFetchFoldersOperation.h> +#import <mailcore/MCOConstants.h> #endif diff --git a/src/objc/imap/MCOCheckAccountOperation.mm b/src/objc/imap/MCOCheckAccountOperation.mm index 47ea0fc8..4c9f5bca 100644 --- a/src/objc/imap/MCOCheckAccountOperation.mm +++ b/src/objc/imap/MCOCheckAccountOperation.mm @@ -6,7 +6,7 @@ // Copyright (c) 2013 __MyCompanyName__. All rights reserved. // -#import <mailcore/MCCore.h> +#import <mailcore/MCAsync.h> #import "MCOOperation+Internals.h" #import "MCOCheckAccountOperation.h" diff --git a/src/objc/imap/MCOOperation+Internals.h b/src/objc/imap/MCOOperation+Internals.h index 58b10559..2862a929 100644 --- a/src/objc/imap/MCOOperation+Internals.h +++ b/src/objc/imap/MCOOperation+Internals.h @@ -13,6 +13,8 @@ @interface MCOOperation () - (id)initWithOperation:(mailcore::Operation *)op; +#ifdef __cplusplus - (mailcore::Operation *)operation; +#endif - (void)start; @end
\ No newline at end of file diff --git a/src/objc/utils/MCOObjectWrapper.h b/src/objc/utils/MCOObjectWrapper.h index eac1a457..6827bde9 100644 --- a/src/objc/utils/MCOObjectWrapper.h +++ b/src/objc/utils/MCOObjectWrapper.h @@ -8,7 +8,11 @@ #import <Foundation/Foundation.h> -#include <mailcore/MCObject.h> +#ifdef __cplusplus +namespace mailcore { + class Object; +} +#endif @interface MCOObjectWrapper : NSObject diff --git a/src/objc/utils/MCOObjectWrapper.mm b/src/objc/utils/MCOObjectWrapper.mm index 74a2afe7..e4fda2ae 100644 --- a/src/objc/utils/MCOObjectWrapper.mm +++ b/src/objc/utils/MCOObjectWrapper.mm @@ -9,6 +9,7 @@ #import "MCOObjectWrapper.h" #include "MCUtils.h" +#include "MCObject.h" @implementation MCOObjectWrapper { mailcore::Object * mObject; diff --git a/src/objc/utils/NSArray+MCO.h b/src/objc/utils/NSArray+MCO.h new file mode 100644 index 00000000..8d95acbc --- /dev/null +++ b/src/objc/utils/NSArray+MCO.h @@ -0,0 +1,23 @@ +// +// NSArray+MCO.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/29/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#import <Foundation/Foundation.h> + +#ifdef __cplusplus +namespace mailcore { + class Array; +} +#endif + +@interface NSArray (MCO) + +#ifdef __cplusplus +- (mailcore::Array *) mco_mcArray; +#endif + +@end diff --git a/src/objc/utils/NSArray+MCO.mm b/src/objc/utils/NSArray+MCO.mm new file mode 100644 index 00000000..1c4ef3e6 --- /dev/null +++ b/src/objc/utils/NSArray+MCO.mm @@ -0,0 +1,26 @@ +// +// NSArray+MCO.cpp +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/29/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#import "NSArray+MCO.h" + +#include "MCBaseTypes.h" + +#import "NSObject+MCO.h" + +@implementation NSArray (MCO) + +- (mailcore::Array *) mco_mcArray +{ + mailcore::Array * result = mailcore::Array::array(); + for(NSObject * value in self) { + [value mco_mcObject]; + } + return result; +} + +@end diff --git a/src/objc/utils/NSData+MCO.h b/src/objc/utils/NSData+MCO.h index 105fd325..9a0b39cc 100644 --- a/src/objc/utils/NSData+MCO.h +++ b/src/objc/utils/NSData+MCO.h @@ -8,7 +8,11 @@ #import <Foundation/Foundation.h> -#include <mailcore/MCData.h> +#ifdef __cplusplus +namespace mailcore { + class Data; +} +#endif @interface NSData (MCO) diff --git a/src/objc/utils/NSData+MCO.mm b/src/objc/utils/NSData+MCO.mm index 70838280..dd279554 100644 --- a/src/objc/utils/NSData+MCO.mm +++ b/src/objc/utils/NSData+MCO.mm @@ -8,6 +8,8 @@ #import "NSData+MCO.h" +#include "MCData.h" + @implementation NSData (MCO) + (NSData *) mco_dataWithMCData:(mailcore::Data *)cppData diff --git a/src/objc/utils/NSDictionary+MCO.h b/src/objc/utils/NSDictionary+MCO.h new file mode 100644 index 00000000..71812a46 --- /dev/null +++ b/src/objc/utils/NSDictionary+MCO.h @@ -0,0 +1,23 @@ +// +// NSDictionary+MCO.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/29/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#import <Foundation/Foundation.h> + +#ifdef __cplusplus +namespace mailcore { + class HashMap; +} +#endif + +@interface NSDictionary (MCO) + +#ifdef __cplusplus +- (mailcore::HashMap *) mco_mcHashMap; +#endif + +@end diff --git a/src/objc/utils/NSDictionary+MCO.mm b/src/objc/utils/NSDictionary+MCO.mm new file mode 100644 index 00000000..a751f85b --- /dev/null +++ b/src/objc/utils/NSDictionary+MCO.mm @@ -0,0 +1,27 @@ +// +// NSDictionary+MCO.m +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/29/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#import "NSDictionary+MCO.h" + +#include "MCBaseTypes.h" + +#import "NSObject+MCO.h" + +@implementation NSDictionary (MCO) + +- (mailcore::HashMap *) mco_mcHashMap +{ + mailcore::HashMap * result = mailcore::HashMap::hashMap(); + for(NSObject * key in self) { + NSObject * value = [self objectForKey:key]; + result->setObjectForKey([key mco_mcObject], [value mco_mcObject]); + } + return result; +} + +@end diff --git a/src/objc/utils/NSObject+MCO.h b/src/objc/utils/NSObject+MCO.h new file mode 100644 index 00000000..349bd27a --- /dev/null +++ b/src/objc/utils/NSObject+MCO.h @@ -0,0 +1,23 @@ +// +// NSObject+MCO.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/29/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#import <Foundation/Foundation.h> + +#ifdef __cplusplus +namespace mailcore { + class Object; +} +#endif + +@interface NSObject (MCO) + +#ifdef __cplusplus +- (mailcore::Object *) mco_mcObject; +#endif + +@end diff --git a/src/objc/utils/NSObject+MCO.mm b/src/objc/utils/NSObject+MCO.mm new file mode 100644 index 00000000..e25db319 --- /dev/null +++ b/src/objc/utils/NSObject+MCO.mm @@ -0,0 +1,42 @@ +// +// NSObject+MCO.m +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/29/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#import "NSObject+MCO.h" + +#import "NSData+MCO.h" +#import "NSString+MCO.h" +#import "NSDictionary+MCO.h" +#import "NSArray+MCO.h" + +#include "MCBaseTypes.h" +#include "MCUtils.h" + +@implementation NSObject (MCO) + +- (mailcore::Object *) mco_mcObject +{ + if ([self isKindOfClass:[NSData class]]) { + return [(NSData *) self mco_mcData]; + } + else if ([self isKindOfClass:[NSString class]]) { + return [(NSString *) self mco_mcString]; + } + else if ([self isKindOfClass:[NSArray class]]) { + return [(NSArray *) self mco_mcArray]; + } + else if ([self isKindOfClass:[NSDictionary class]]) { + return [(NSDictionary *) self mco_mcHashMap]; + } + else { + MCAssert(0); + return nil; + } + +} + +@end diff --git a/src/objc/utils/NSString+MCO.h b/src/objc/utils/NSString+MCO.h index e7057116..33cc0b67 100644 --- a/src/objc/utils/NSString+MCO.h +++ b/src/objc/utils/NSString+MCO.h @@ -8,7 +8,12 @@ #import <Foundation/Foundation.h> -#include <mailcore/MCString.h> +#ifdef __cplusplus +namespace mailcore { + class String; + class Object; +} +#endif @interface NSString (MCO) diff --git a/src/objc/utils/NSString+MCO.mm b/src/objc/utils/NSString+MCO.mm index 803e9f24..3d692b76 100644 --- a/src/objc/utils/NSString+MCO.mm +++ b/src/objc/utils/NSString+MCO.mm @@ -8,6 +8,8 @@ #import "NSString+MCO.h" +#include "MCString.h" + @implementation NSString (MCO) + (NSString *) mco_stringWithMCString:(mailcore::String *)cppString |