aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--build-mac/mailcore2.xcodeproj/project.pbxproj70
-rwxr-xr-xscripts/prepare.sh1
-rw-r--r--src/core/abstract/MCAbstractMessage.cc12
-rw-r--r--src/core/abstract/MCAbstractMessage.h4
-rw-r--r--src/core/abstract/MCAbstractMessagePart.cc10
-rw-r--r--src/core/abstract/MCAbstractMessagePart.h3
-rw-r--r--src/core/abstract/MCAbstractMultipart.cc24
-rw-r--r--src/core/abstract/MCAbstractMultipart.h3
-rw-r--r--src/core/abstract/MCAbstractPart.cc21
-rw-r--r--src/core/abstract/MCAbstractPart.h9
-rw-r--r--src/core/basetypes/MCString.cc10
-rw-r--r--src/core/basetypes/MCString.h2
-rw-r--r--src/core/imap/MCIMAPMessage.cc71
-rw-r--r--src/core/imap/MCIMAPMessage.h13
-rw-r--r--src/core/imap/MCIMAPMessagePart.cc19
-rw-r--r--src/core/imap/MCIMAPMessagePart.h7
-rw-r--r--src/core/imap/MCIMAPMultipart.cc18
-rw-r--r--src/core/imap/MCIMAPMultipart.h7
-rw-r--r--src/core/imap/MCIMAPPart.cc2
-rw-r--r--src/core/imap/MCIMAPPart.h11
-rw-r--r--src/core/renderer/MCAddressDisplay.cpp94
-rw-r--r--src/core/renderer/MCAddressDisplay.h34
-rw-r--r--src/core/renderer/MCDateFormatter.cpp160
-rw-r--r--src/core/renderer/MCDateFormatter.h69
-rw-r--r--src/core/renderer/MCHTMLRenderer.cpp446
-rw-r--r--src/core/renderer/MCHTMLRenderer.h38
-rw-r--r--src/core/renderer/MCHTMLRendererCallback.cpp259
-rw-r--r--src/core/renderer/MCHTMLRendererCallback.h51
-rw-r--r--src/core/renderer/MCRenderer.h18
-rw-r--r--src/core/renderer/MCSizeFormatter.cpp43
-rw-r--r--src/core/renderer/MCSizeFormatter.h28
-rw-r--r--src/core/rfc822/MCAttachment.h5
-rw-r--r--src/core/rfc822/MCMessageParser.cc17
-rw-r--r--src/core/rfc822/MCMessageParser.h7
34 files changed, 1571 insertions, 15 deletions
diff --git a/build-mac/mailcore2.xcodeproj/project.pbxproj b/build-mac/mailcore2.xcodeproj/project.pbxproj
index 9c797b14..e345b82d 100644
--- a/build-mac/mailcore2.xcodeproj/project.pbxproj
+++ b/build-mac/mailcore2.xcodeproj/project.pbxproj
@@ -47,6 +47,17 @@
C62C6F0716A7E7CC00737497 /* MCPOPFetchMessagesOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C62C6F0516A7E54400737497 /* MCPOPFetchMessagesOperation.h */; };
C62C6F0A16A8F58000737497 /* MCIMAPAsyncSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C62C6F0816A8F57000737497 /* MCIMAPAsyncSession.cpp */; };
C62C6F0B16A936CA00737497 /* MCIMAPAsyncSession.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C62C6F0916A8F57700737497 /* MCIMAPAsyncSession.h */; };
+ C63CD67F16BDCDD400DB18F1 /* MCAddressDisplay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C63CD67716BDCDD400DB18F1 /* MCAddressDisplay.cpp */; };
+ C63CD68016BDCDD400DB18F1 /* MCDateFormatter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C63CD67916BDCDD400DB18F1 /* MCDateFormatter.cpp */; };
+ C63CD68116BDCDD400DB18F1 /* MCHTMLRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C63CD67B16BDCDD400DB18F1 /* MCHTMLRenderer.cpp */; };
+ C63CD68216BDCDD400DB18F1 /* MCSizeFormatter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C63CD67D16BDCDD400DB18F1 /* MCSizeFormatter.cpp */; };
+ C63CD68616BE148B00DB18F1 /* MCHTMLRendererCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C63CD68416BE148B00DB18F1 /* MCHTMLRendererCallback.cpp */; };
+ C63CD68816BE1BBF00DB18F1 /* MCAddressDisplay.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C63CD67816BDCDD400DB18F1 /* MCAddressDisplay.h */; };
+ C63CD68916BE1BC100DB18F1 /* MCDateFormatter.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C63CD67A16BDCDD400DB18F1 /* MCDateFormatter.h */; };
+ C63CD68A16BE1BC400DB18F1 /* MCSizeFormatter.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C63CD67E16BDCDD400DB18F1 /* MCSizeFormatter.h */; };
+ C63CD68B16BE1BC600DB18F1 /* MCHTMLRenderer.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C63CD67C16BDCDD400DB18F1 /* MCHTMLRenderer.h */; };
+ C63CD68C16BE1BC800DB18F1 /* MCHTMLRendererCallback.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C63CD68516BE148B00DB18F1 /* MCHTMLRendererCallback.h */; };
+ C63CD68D16BE1BCA00DB18F1 /* MCRenderer.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C63CD68716BE1AB600DB18F1 /* MCRenderer.h */; };
C64EA6F4169E847800778456 /* MCAbstractMessage.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA694169E847800778456 /* MCAbstractMessage.cc */; };
C64EA6F6169E847800778456 /* MCAbstractMessagePart.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA696169E847800778456 /* MCAbstractMessagePart.cc */; };
C64EA6F8169E847800778456 /* MCAbstractMultipart.cc in Sources */ = {isa = PBXBuildFile; fileRef = C64EA698169E847800778456 /* MCAbstractMultipart.cc */; };
@@ -174,14 +185,14 @@
C6D42C2A16AE0507002BB4F9 /* NSData+MCO.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6D42C1916AE03D6002BB4F9 /* NSData+MCO.h */; };
C6D42C2C16AE0509002BB4F9 /* NSString+MCO.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6D42C1B16AE03D6002BB4F9 /* NSString+MCO.h */; };
C6EB30DE16B5B8050091F4F1 /* MCObjC.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6EB30DC16B5B7770091F4F1 /* MCObjC.h */; };
- F87F190C16BB62B00012652F /* MCOFetchFoldersOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = F87F190B16BB62B00012652F /* MCOFetchFoldersOperation.mm */; };
- F8EA941716BB1C9D0011AC6F /* MCOIMAPSession.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = F8EA941416BAED6E0011AC6F /* MCOIMAPSession.h */; };
C6EB30F716B8C9480091F4F1 /* NSDictionary+MCO.mm in Sources */ = {isa = PBXBuildFile; fileRef = C6EB30F616B8C9480091F4F1 /* NSDictionary+MCO.mm */; };
C6EB30F816B8DED30091F4F1 /* NSDictionary+MCO.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6EB30F516B8C9480091F4F1 /* NSDictionary+MCO.h */; };
C6EB30FE16B8E50F0091F4F1 /* NSArray+MCO.mm in Sources */ = {isa = PBXBuildFile; fileRef = C6EB30FC16B8E50F0091F4F1 /* NSArray+MCO.mm */; };
C6EB310116B8E6E60091F4F1 /* NSObject+MCO.mm in Sources */ = {isa = PBXBuildFile; fileRef = C6EB310016B8E6E50091F4F1 /* NSObject+MCO.mm */; };
C6EB310216B8E7D60091F4F1 /* NSObject+MCO.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6EB30FF16B8E6E50091F4F1 /* NSObject+MCO.h */; };
C6EB310316B8E7D80091F4F1 /* NSArray+MCO.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6EB30FD16B8E50F0091F4F1 /* NSArray+MCO.h */; };
+ F87F190C16BB62B00012652F /* MCOFetchFoldersOperation.mm in Sources */ = {isa = PBXBuildFile; fileRef = F87F190B16BB62B00012652F /* MCOFetchFoldersOperation.mm */; };
+ F8EA941716BB1C9D0011AC6F /* MCOIMAPSession.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = F8EA941416BAED6E0011AC6F /* MCOIMAPSession.h */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -201,7 +212,13 @@
dstPath = include/mailcore;
dstSubfolderSpec = 16;
files = (
+ C63CD68C16BE1BC800DB18F1 /* MCHTMLRendererCallback.h in CopyFiles */,
+ C63CD68816BE1BBF00DB18F1 /* MCAddressDisplay.h in CopyFiles */,
+ C63CD68D16BE1BCA00DB18F1 /* MCRenderer.h in CopyFiles */,
C62C6EE016A696AB00737497 /* MCAsyncIMAP.h in CopyFiles */,
+ C63CD68B16BE1BC600DB18F1 /* MCHTMLRenderer.h in CopyFiles */,
+ C63CD68A16BE1BC400DB18F1 /* MCSizeFormatter.h in CopyFiles */,
+ C63CD68916BE1BC100DB18F1 /* MCDateFormatter.h in CopyFiles */,
C6EB30DE16B5B8050091F4F1 /* MCObjC.h in CopyFiles */,
C6EB310216B8E7D60091F4F1 /* NSObject+MCO.h in CopyFiles */,
C6EB310316B8E7D80091F4F1 /* NSArray+MCO.h in CopyFiles */,
@@ -336,6 +353,17 @@
C62C6F0516A7E54400737497 /* MCPOPFetchMessagesOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCPOPFetchMessagesOperation.h; sourceTree = "<group>"; };
C62C6F0816A8F57000737497 /* MCIMAPAsyncSession.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCIMAPAsyncSession.cpp; sourceTree = "<group>"; };
C62C6F0916A8F57700737497 /* MCIMAPAsyncSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPAsyncSession.h; sourceTree = "<group>"; };
+ C63CD67716BDCDD400DB18F1 /* MCAddressDisplay.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCAddressDisplay.cpp; sourceTree = "<group>"; };
+ C63CD67816BDCDD400DB18F1 /* MCAddressDisplay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCAddressDisplay.h; sourceTree = "<group>"; };
+ C63CD67916BDCDD400DB18F1 /* MCDateFormatter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCDateFormatter.cpp; sourceTree = "<group>"; };
+ C63CD67A16BDCDD400DB18F1 /* MCDateFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCDateFormatter.h; sourceTree = "<group>"; };
+ C63CD67B16BDCDD400DB18F1 /* MCHTMLRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCHTMLRenderer.cpp; sourceTree = "<group>"; };
+ C63CD67C16BDCDD400DB18F1 /* MCHTMLRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCHTMLRenderer.h; sourceTree = "<group>"; };
+ C63CD67D16BDCDD400DB18F1 /* MCSizeFormatter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCSizeFormatter.cpp; sourceTree = "<group>"; };
+ C63CD67E16BDCDD400DB18F1 /* MCSizeFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCSizeFormatter.h; sourceTree = "<group>"; };
+ C63CD68416BE148B00DB18F1 /* MCHTMLRendererCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCHTMLRendererCallback.cpp; sourceTree = "<group>"; };
+ C63CD68516BE148B00DB18F1 /* MCHTMLRendererCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCHTMLRendererCallback.h; sourceTree = "<group>"; };
+ C63CD68716BE1AB600DB18F1 /* MCRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCRenderer.h; sourceTree = "<group>"; };
C64EA537169E772200778456 /* libmailcore2.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libmailcore2.a; sourceTree = BUILT_PRODUCTS_DIR; };
C64EA68C169E847800778456 /* MCIMAPAsyncConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCIMAPAsyncConnection.h; sourceTree = "<group>"; };
C64EA68F169E847800778456 /* MCSMTPAsyncSession.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCSMTPAsyncSession.cc; sourceTree = "<group>"; };
@@ -487,15 +515,15 @@
C6D42C1B16AE03D6002BB4F9 /* NSString+MCO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+MCO.h"; sourceTree = "<group>"; };
C6D42C1C16AE03D6002BB4F9 /* NSString+MCO.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSString+MCO.mm"; sourceTree = "<group>"; };
C6EB30DC16B5B7770091F4F1 /* MCObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCObjC.h; sourceTree = "<group>"; };
- F87F190816BB62690012652F /* MCOFetchFoldersOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOFetchFoldersOperation.h; sourceTree = "<group>"; };
- F87F190B16BB62B00012652F /* MCOFetchFoldersOperation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOFetchFoldersOperation.mm; sourceTree = "<group>"; };
- F8EA941416BAED6E0011AC6F /* MCOIMAPSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOIMAPSession.h; sourceTree = "<group>"; };
C6EB30F516B8C9480091F4F1 /* NSDictionary+MCO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+MCO.h"; sourceTree = "<group>"; };
C6EB30F616B8C9480091F4F1 /* NSDictionary+MCO.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSDictionary+MCO.mm"; sourceTree = "<group>"; };
C6EB30FC16B8E50F0091F4F1 /* NSArray+MCO.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSArray+MCO.mm"; sourceTree = "<group>"; };
C6EB30FD16B8E50F0091F4F1 /* NSArray+MCO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+MCO.h"; sourceTree = "<group>"; };
C6EB30FF16B8E6E50091F4F1 /* NSObject+MCO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+MCO.h"; sourceTree = "<group>"; };
C6EB310016B8E6E50091F4F1 /* NSObject+MCO.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSObject+MCO.mm"; sourceTree = "<group>"; };
+ F87F190816BB62690012652F /* MCOFetchFoldersOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOFetchFoldersOperation.h; sourceTree = "<group>"; };
+ F87F190B16BB62B00012652F /* MCOFetchFoldersOperation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOFetchFoldersOperation.mm; sourceTree = "<group>"; };
+ F8EA941416BAED6E0011AC6F /* MCOIMAPSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOIMAPSession.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -519,6 +547,24 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
+ C63CD67616BDCDD300DB18F1 /* renderer */ = {
+ isa = PBXGroup;
+ children = (
+ C63CD67716BDCDD400DB18F1 /* MCAddressDisplay.cpp */,
+ C63CD67816BDCDD400DB18F1 /* MCAddressDisplay.h */,
+ C63CD67916BDCDD400DB18F1 /* MCDateFormatter.cpp */,
+ C63CD67A16BDCDD400DB18F1 /* MCDateFormatter.h */,
+ C63CD67D16BDCDD400DB18F1 /* MCSizeFormatter.cpp */,
+ C63CD67E16BDCDD400DB18F1 /* MCSizeFormatter.h */,
+ C63CD67B16BDCDD400DB18F1 /* MCHTMLRenderer.cpp */,
+ C63CD67C16BDCDD400DB18F1 /* MCHTMLRenderer.h */,
+ C63CD68416BE148B00DB18F1 /* MCHTMLRendererCallback.cpp */,
+ C63CD68516BE148B00DB18F1 /* MCHTMLRendererCallback.h */,
+ C63CD68716BE1AB600DB18F1 /* MCRenderer.h */,
+ );
+ path = renderer;
+ sourceTree = "<group>";
+ };
C64EA52C169E772200778456 = {
isa = PBXGroup;
children = (
@@ -653,6 +699,7 @@
C64EA691169E847800778456 /* core */ = {
isa = PBXGroup;
children = (
+ C63CD67616BDCDD300DB18F1 /* renderer */,
C64EA692169E847800778456 /* abstract */,
C64EA6A1169E847800778456 /* basetypes */,
C64EA6C3169E847800778456 /* imap */,
@@ -1027,6 +1074,11 @@
C6EB30F716B8C9480091F4F1 /* NSDictionary+MCO.mm in Sources */,
C6EB30FE16B8E50F0091F4F1 /* NSArray+MCO.mm in Sources */,
C6EB310116B8E6E60091F4F1 /* NSObject+MCO.mm in Sources */,
+ C63CD67F16BDCDD400DB18F1 /* MCAddressDisplay.cpp in Sources */,
+ C63CD68016BDCDD400DB18F1 /* MCDateFormatter.cpp in Sources */,
+ C63CD68116BDCDD400DB18F1 /* MCHTMLRenderer.cpp in Sources */,
+ C63CD68216BDCDD400DB18F1 /* MCSizeFormatter.cpp in Sources */,
+ C63CD68616BE148B00DB18F1 /* MCHTMLRendererCallback.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1076,11 +1128,13 @@
HEADER_SEARCH_PATHS = (
"$(SRCROOT)/../Externals/libetpan/include",
"$(SRCROOT)/../Externals/icu4c/include",
+ "$(SRCROOT)/../Externals/ctemplate/include",
/usr/include/libxml2,
);
LIBRARY_SEARCH_PATHS = (
"$(SRCROOT)/../Externals/libetpan/lib",
"$(SRCROOT)/../Externals/icu4c/lib",
+ "$(SRCROOT)/../Externals/ctemplate/lib",
);
MACOSX_DEPLOYMENT_TARGET = 10.8;
ONLY_ACTIVE_ARCH = YES;
@@ -1109,11 +1163,13 @@
HEADER_SEARCH_PATHS = (
"$(SRCROOT)/../Externals/libetpan/include",
"$(SRCROOT)/../Externals/icu4c/include",
+ "$(SRCROOT)/../Externals/ctemplate/include",
/usr/include/libxml2,
);
LIBRARY_SEARCH_PATHS = (
"$(SRCROOT)/../Externals/libetpan/lib",
"$(SRCROOT)/../Externals/icu4c/lib",
+ "$(SRCROOT)/../Externals/ctemplate/lib",
);
MACOSX_DEPLOYMENT_TARGET = 10.8;
SDKROOT = macosx;
@@ -1141,7 +1197,9 @@
C64EA799169F259300778456 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ CLANG_CXX_LIBRARY = "libstdc++";
OTHER_LDFLAGS = (
+ "-lctemplate",
"-letpan",
"-licudata",
"-licui18n",
@@ -1160,7 +1218,9 @@
C64EA79A169F259300778456 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ CLANG_CXX_LIBRARY = "libstdc++";
OTHER_LDFLAGS = (
+ "-lctemplate",
"-letpan",
"-licudata",
"-licui18n",
diff --git a/scripts/prepare.sh b/scripts/prepare.sh
index 3e3cb9b1..11b41a24 100755
--- a/scripts/prepare.sh
+++ b/scripts/prepare.sh
@@ -1,3 +1,4 @@
#!/bin/sh
./prepare-icu4c-macos.sh
./prepare-libetpan-macos.sh
+./prepare-ctemplate-macos.sh
diff --git a/src/core/abstract/MCAbstractMessage.cc b/src/core/abstract/MCAbstractMessage.cc
index f1768aec..b7d9b9af 100644
--- a/src/core/abstract/MCAbstractMessage.cc
+++ b/src/core/abstract/MCAbstractMessage.cc
@@ -56,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 98acec98..a52d2196 100644
--- a/src/core/abstract/MCAbstractMessagePart.cc
+++ b/src/core/abstract/MCAbstractMessagePart.cc
@@ -79,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 207b2962..2604bcac 100644
--- a/src/core/abstract/MCAbstractMultipart.cc
+++ b/src/core/abstract/MCAbstractMultipart.cc
@@ -86,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 b2e6281d..78e2e365 100644
--- a/src/core/abstract/MCAbstractPart.cc
+++ b/src/core/abstract/MCAbstractPart.cc
@@ -227,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 db034654..49360089 100644
--- a/src/core/abstract/MCAbstractPart.h
+++ b/src/core/abstract/MCAbstractPart.h
@@ -43,14 +43,19 @@ 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;
diff --git a/src/core/basetypes/MCString.cc b/src/core/basetypes/MCString.cc
index 97b6d7d4..d57e70ed 100644
--- a/src/core/basetypes/MCString.cc
+++ b/src/core/basetypes/MCString.cc
@@ -1722,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",
@@ -2011,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/imap/MCIMAPMessage.cc b/src/core/imap/MCIMAPMessage.cc
index 6d8311ed..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;
@@ -102,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..38d25ea4 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);
+
public: // subclass behavior
IMAPMessage(IMAPMessage * other);
virtual Object * copy();
diff --git a/src/core/imap/MCIMAPMessagePart.cc b/src/core/imap/MCIMAPMessagePart.cc
index b250ef4b..bd97657c 100644
--- a/src/core/imap/MCIMAPMessagePart.cc
+++ b/src/core/imap/MCIMAPMessagePart.cc
@@ -4,17 +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);
}
Object * IMAPMessagePart::copy()
{
return new IMAPMessagePart(this);
}
+
+void IMAPMessagePart::init()
+{
+ 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 63a3384f..be0b2c8e 100644
--- a/src/core/imap/MCIMAPMultipart.cc
+++ b/src/core/imap/MCIMAPMultipart.cc
@@ -4,14 +4,18 @@ 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);
}
Object * IMAPMultipart::copy()
@@ -19,3 +23,17 @@ Object * IMAPMultipart::copy()
return new IMAPMultipart(this);
}
+void IMAPMultipart::init()
+{
+ 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/MCIMAPPart.cc b/src/core/imap/MCIMAPPart.cc
index 787c0257..dc1a687f 100644
--- a/src/core/imap/MCIMAPPart.cc
+++ b/src/core/imap/MCIMAPPart.cc
@@ -154,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);
@@ -267,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 e93b644e..44d03b2f 100644
--- a/src/core/imap/MCIMAPPart.h
+++ b/src/core/imap/MCIMAPPart.h
@@ -29,15 +29,16 @@ namespace mailcore {
virtual void setEncoding(Encoding encoding);
virtual Encoding encoding();
- 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/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__) */
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/MCMessageParser.cc b/src/core/rfc822/MCMessageParser.cc
index bdf2a87d..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;
@@ -73,3 +74,19 @@ Object * MessageParser::copy()
{
return new MessageParser(this);
}
+
+AbstractPart * MessageParser::partForContentID(String * contentID)
+{
+ 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..5737920d 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);
+
public: // subclass behavior
MessageParser(MessageParser * other);
virtual String * description();