diff options
Diffstat (limited to 'src/core/renderer')
-rw-r--r-- | src/core/renderer/MCAddressDisplay.cpp | 94 | ||||
-rw-r--r-- | src/core/renderer/MCAddressDisplay.h | 34 | ||||
-rw-r--r-- | src/core/renderer/MCDateFormatter.cpp | 160 | ||||
-rw-r--r-- | src/core/renderer/MCDateFormatter.h | 69 | ||||
-rw-r--r-- | src/core/renderer/MCHTMLRenderer.cpp | 446 | ||||
-rw-r--r-- | src/core/renderer/MCHTMLRenderer.h | 38 | ||||
-rw-r--r-- | src/core/renderer/MCHTMLRendererCallback.cpp | 259 | ||||
-rw-r--r-- | src/core/renderer/MCHTMLRendererCallback.h | 51 | ||||
-rw-r--r-- | src/core/renderer/MCRenderer.h | 18 | ||||
-rw-r--r-- | src/core/renderer/MCSizeFormatter.cpp | 43 | ||||
-rw-r--r-- | src/core/renderer/MCSizeFormatter.h | 28 |
11 files changed, 1240 insertions, 0 deletions
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..10066fc4 --- /dev/null +++ b/src/core/renderer/MCHTMLRenderer.cpp @@ -0,0 +1,446 @@ +// +// 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->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..10b704d6 --- /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}}\ + {{#HASSIZE}}\ + <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..a03b5be9 --- /dev/null +++ b/src/core/renderer/MCRenderer.h @@ -0,0 +1,18 @@ +// +// 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/MCAddressDisplay.h> +#include <mailcore/MCDateFormatter.h> +#include <mailcore/MCSizeFormatter.h> +#include <mailcore/MCHTMLRenderer.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..c3795c63 --- /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 %@", 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__) */ |