aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rwxr-xr-xbuild-mac/mailcore2.xcodeproj/project.pbxproj34
-rw-r--r--src/core/basetypes/MCData.cc80
-rw-r--r--src/core/basetypes/MCString.cc152
-rw-r--r--unittest/unittest.mm9
4 files changed, 240 insertions, 35 deletions
diff --git a/build-mac/mailcore2.xcodeproj/project.pbxproj b/build-mac/mailcore2.xcodeproj/project.pbxproj
index f3a2e701..8005804b 100755
--- a/build-mac/mailcore2.xcodeproj/project.pbxproj
+++ b/build-mac/mailcore2.xcodeproj/project.pbxproj
@@ -4558,15 +4558,11 @@
OTHER_LDFLAGS = (
"-lctemplate-ios",
"-letpan-ios",
- "-licudata",
- "-licui18n",
- "-licuuc",
"-lxml2",
"-lsasl2",
"-liconv",
"-ltidy",
"-lz",
- "-licucore",
"-ObjC",
);
PRODUCT_NAME = "MailCore-ios";
@@ -4588,15 +4584,11 @@
OTHER_LDFLAGS = (
"-lctemplate-ios",
"-letpan-ios",
- "-licudata",
- "-licui18n",
- "-licuuc",
"-lxml2",
"-lsasl2",
"-liconv",
"-ltidy",
"-lz",
- "-licucore",
"-ObjC",
);
PRODUCT_NAME = "MailCore-ios";
@@ -4652,8 +4644,8 @@
"LIBRARY_SEARCH_PATHS[sdk=macosx*]" = "$(OSX_LIBRARY_SEARCH_PATHS)";
MACOSX_DEPLOYMENT_TARGET = 10.8;
ONLY_ACTIVE_ARCH = YES;
- OSX_HEADERS_SEARCH_PATHS = "\"$(SRCROOT)/../Externals/libetpan/include\" \"$(SRCROOT)/../Externals/icu4c/include\" \"$(SRCROOT)/../Externals/ctemplate/include\" /usr/include/tidy /usr/include/libxml2";
- OSX_LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/../Externals/libetpan/lib\" \"$(SRCROOT)/../Externals/icu4c/lib\" \"$(SRCROOT)/../Externals/ctemplate/lib\"";
+ OSX_HEADERS_SEARCH_PATHS = "\"$(SRCROOT)/../Externals/libetpan/include\" \"$(SRCROOT)/../Externals/icu4c/include\" \"$(SRCROOT)/../Externals/ctemplate/include\" \"$(SRCROOT)/../Externals/uchardet/include\" /usr/include/tidy /usr/include/libxml2";
+ OSX_LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/../Externals/libetpan/lib\" \"$(SRCROOT)/../Externals/icu4c/lib\" \"$(SRCROOT)/../Externals/uchardet/lib\" \"$(SRCROOT)/../Externals/ctemplate/lib\"";
};
name = Debug;
};
@@ -4699,8 +4691,8 @@
"LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*]" = "$(IOS_LIBRARY_SEARCH_PATHS)";
"LIBRARY_SEARCH_PATHS[sdk=macosx*]" = "$(OSX_LIBRARY_SEARCH_PATHS)";
MACOSX_DEPLOYMENT_TARGET = 10.8;
- OSX_HEADERS_SEARCH_PATHS = "\"$(SRCROOT)/../Externals/libetpan/include\" \"$(SRCROOT)/../Externals/icu4c/include\" \"$(SRCROOT)/../Externals/ctemplate/include\" /usr/include/tidy /usr/include/libxml2";
- OSX_LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/../Externals/libetpan/lib\" \"$(SRCROOT)/../Externals/icu4c/lib\" \"$(SRCROOT)/../Externals/ctemplate/lib\"";
+ OSX_HEADERS_SEARCH_PATHS = "\"$(SRCROOT)/../Externals/libetpan/include\" \"$(SRCROOT)/../Externals/icu4c/include\" \"$(SRCROOT)/../Externals/ctemplate/include\" \"$(SRCROOT)/../Externals/uchardet/include\" /usr/include/tidy /usr/include/libxml2";
+ OSX_LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/../Externals/libetpan/lib\" \"$(SRCROOT)/../Externals/icu4c/lib\" \"$(SRCROOT)/../Externals/uchardet/lib\" \"$(SRCROOT)/../Externals/ctemplate/lib\"";
};
name = Release;
};
@@ -4756,16 +4748,12 @@
OTHER_LDFLAGS = (
"-lctemplate-ios",
"-letpan-ios",
- "-licudata",
- "-licui18n",
- "-licuuc",
"-lxml2",
"-lsasl2",
"-liconv",
"-all_load",
"-ltidy",
"-lz",
- "-licucore",
);
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -4791,16 +4779,12 @@
OTHER_LDFLAGS = (
"-lctemplate-ios",
"-letpan-ios",
- "-licudata",
- "-licui18n",
- "-licuuc",
"-lxml2",
"-lsasl2",
"-liconv",
"-all_load",
"-ltidy",
"-lz",
- "-licucore",
);
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -4913,9 +4897,6 @@
OTHER_LDFLAGS = (
"-lctemplate",
"-letpan",
- "-licudata",
- "-licui18n",
- "-licuuc",
"-lxml2",
"-lssl",
"-lcrypto",
@@ -4924,7 +4905,7 @@
"-all_load",
"-ltidy",
"-lz",
- "-licucore",
+ "-luchardet",
);
PRODUCT_NAME = MailCore;
SDKROOT = macosx;
@@ -4944,9 +4925,6 @@
OTHER_LDFLAGS = (
"-lctemplate",
"-letpan",
- "-licudata",
- "-licui18n",
- "-licuuc",
"-lxml2",
"-lssl",
"-lcrypto",
@@ -4955,7 +4933,7 @@
"-all_load",
"-ltidy",
"-lz",
- "-licucore",
+ "-luchardet",
);
PRODUCT_NAME = MailCore;
SDKROOT = macosx;
diff --git a/src/core/basetypes/MCData.cc b/src/core/basetypes/MCData.cc
index d7d4e7a6..9845d77a 100644
--- a/src/core/basetypes/MCData.cc
+++ b/src/core/basetypes/MCData.cc
@@ -1,9 +1,15 @@
#include "MCData.h"
+#define USE_UCHARDET 1
+
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
+#if USE_UCHARDET
+#include <uchardet/uchardet.h>
+#else
#include <unicode/ucsdet.h>
+#endif
#include <libetpan/libetpan.h>
#include <iconv.h>
#if __APPLE__
@@ -202,6 +208,7 @@ static bool isHintCharsetValid(String * hintCharset)
if (knownCharset == NULL) {
knownCharset = new Set();
+#if !USE_UCHARDET
UCharsetDetector * detector;
UEnumeration * iterator;
UErrorCode err = U_ZERO_ERROR;
@@ -218,6 +225,41 @@ static bool isHintCharsetValid(String * hintCharset)
}
uenum_close(iterator);
ucsdet_close(detector);
+#else
+ const char * charset_list[] = {
+ "Big5",
+ "EUC-JP",
+ "EUC-KR",
+ "x-euc-tw",
+ "gb18030",
+ "ISO-8859-8",
+ "windows-1255",
+ "windows-1252",
+ "Shift_JIS",
+ "UTF-8",
+ "UTF-16",
+ "HZ-GB-2312",
+ "ISO-2022-CN",
+ "ISO-2022-JP",
+ "ISO-2022-KR",
+ "ISO-8859-5"
+ "windows-1251"
+ "KOI8-R"
+ "x-mac-cyrillic"
+ "IBM866"
+ "IBM855"
+ "ISO-8859-7"
+ "windows-1253"
+ "ISO-8859-2"
+ "windows-1250"
+ "TIS-620"
+ };
+ for(unsigned int i = 0 ; i < sizeof(charset_list) / sizeof(charset_list[0]) ; i ++) {
+ String * str = String::stringWithUTF8Characters(charset_list[i]);
+ str = str->lowercaseString();
+ knownCharset->addObject(str);
+ }
+#endif
}
pthread_mutex_unlock(&lock);
@@ -322,6 +364,7 @@ String * Data::stringWithDetectedCharset(String * hintCharset, bool isHTML)
String * Data::charsetWithFilteredHTMLWithoutHint(bool filterHTML)
{
+#if !USE_UCHARDET
UCharsetDetector * detector;
const UCharsetMatch * match;
UErrorCode err = U_ZERO_ERROR;
@@ -343,6 +386,21 @@ String * Data::charsetWithFilteredHTMLWithoutHint(bool filterHTML)
ucsdet_close(detector);
return result;
+#else
+ String * result = NULL;
+ uchardet_t ud = uchardet_new();
+ int r = uchardet_handle_data(ud, bytes(), length());
+ if (r == 0) {
+ uchardet_data_end(ud);
+ const char * charset = uchardet_get_charset(ud);
+ if (charset[0] != 0) {
+ result = String::stringWithUTF8Characters(charset);
+ }
+ }
+ uchardet_delete(ud);
+
+ return result;
+#endif
}
String * Data::charsetWithFilteredHTML(bool filterHTML, String * hintCharset)
@@ -350,6 +408,7 @@ String * Data::charsetWithFilteredHTML(bool filterHTML, String * hintCharset)
if (hintCharset == NULL)
return charsetWithFilteredHTMLWithoutHint(filterHTML);
+#if !USE_UCHARDET
const UCharsetMatch ** matches;
int32_t matchesCount;
UCharsetDetector * detector;
@@ -413,6 +472,27 @@ String * Data::charsetWithFilteredHTML(bool filterHTML, String * hintCharset)
result = hintCharset;
return result;
+#else
+ String * result;
+ uchardet_t ud = uchardet_new();
+ int r = uchardet_handle_data(ud, bytes(), length());
+ if (r == 0) {
+ uchardet_data_end(ud);
+ const char * charset = uchardet_get_charset(ud);
+ if (charset[0] == 0) {
+ result = hintCharset;
+ }
+ else {
+ result = String::stringWithUTF8Characters(charset);
+ }
+ }
+ else {
+ result = hintCharset;
+ }
+ uchardet_delete(ud);
+
+ return result;
+#endif
}
void Data::takeBytesOwnership(char * bytes, unsigned int length)
diff --git a/src/core/basetypes/MCString.cc b/src/core/basetypes/MCString.cc
index dbf43943..88c61a99 100644
--- a/src/core/basetypes/MCString.cc
+++ b/src/core/basetypes/MCString.cc
@@ -1,10 +1,14 @@
#include "MCString.h"
+#define DISABLE_ICU 1
+
#include <string.h>
#include <stdlib.h>
+#if !DISABLE_ICU
#include <unicode/ustring.h>
#include <unicode/ucnv.h>
#include <unicode/utypes.h>
+#endif
#include <uuid/uuid.h>
#include <pthread.h>
#include <libetpan/libetpan.h>
@@ -30,9 +34,68 @@
using namespace mailcore;
+#if DISABLE_ICU
+static int32_t u_strlen(const UChar *s) {
+ if (s == NULL) {
+ return 0;
+ }
+ const UChar * p = s;
+ while (* p != 0) {
+ p ++;
+ }
+ return (int32_t) (p - s);
+}
+
+static UChar * u_memcpy(UChar * dest, const UChar * src, int32_t count) {
+ memcpy(dest, src, count * sizeof(* src));
+ return dest;
+}
+
+static UChar * u_strstr(const UChar * s, const UChar * substring)
+{
+ if (s == NULL) {
+ return NULL;
+ }
+ CFStringRef cfS = CFStringCreateWithCharactersNoCopy(NULL, (const UniChar *) s, u_strlen(s), kCFAllocatorNull);
+ CFStringRef cfSubstring = CFStringCreateWithCharactersNoCopy(NULL, (const UniChar *) substring, u_strlen(substring), kCFAllocatorNull);
+
+ CFRange range = CFStringFind(cfS, cfSubstring, 0);
+ CFRelease(cfSubstring);
+ CFRelease(cfS);
+ if (range.length == 0) {
+ return NULL;
+ }
+ return (UChar *) (s + range.location);
+}
+
+static UChar * u_strrstr(const UChar * s, const UChar * substring)
+{
+ if (s == NULL) {
+ return NULL;
+ }
+ CFStringRef cfS = CFStringCreateWithCharactersNoCopy(NULL, (const UniChar *) s, u_strlen(s), kCFAllocatorNull);
+ CFStringRef cfSubstring = CFStringCreateWithCharactersNoCopy(NULL, (const UniChar *) substring, u_strlen(substring), kCFAllocatorNull);
+
+ CFRange range = CFStringFind(cfS, cfSubstring, kCFCompareBackwards);
+ CFRelease(cfSubstring);
+ CFRelease(cfS);
+ if (range.length == 0) {
+ return NULL;
+ }
+ return (UChar *) (s + range.location);
+}
+
+static int32_t u_memcmp(const UChar * buf1, const UChar * buf2, int32_t count)
+{
+ return memcmp(buf1, buf2, count * sizeof(* buf1));
+}
+#endif
+
void mailcore::setICUDataDirectory(String * directory)
{
+#if !DISABLE_ICU
u_setDataDirectory(directory->fileSystemRepresentation());
+#endif
}
#pragma mark quote headers string
@@ -833,7 +896,11 @@ void String::appendCharactersLength(const UChar * unicodeCharacters, unsigned in
return;
}
allocate(mLength + length);
+#if DISABLE_ICU
+ memcpy(&mUnicodeChars[mLength], unicodeCharacters, length * sizeof(* mUnicodeChars));
+#else
u_strncpy(&mUnicodeChars[mLength], unicodeCharacters, length);
+#endif
mLength += length;
mUnicodeChars[mLength] = 0;
}
@@ -862,7 +929,16 @@ void String::appendUTF8CharactersLength(const char * UTF8Characters, unsigned in
if (UTF8Characters == NULL) {
return;
}
-
+
+#if DISABLE_ICU
+ CFStringRef cfStr = CFStringCreateWithBytes(NULL, (const UInt8 *) UTF8Characters, length,
+ kCFStringEncodingUTF8, false);
+ UniChar * characters = (UniChar *) malloc(sizeof(* characters) * CFStringGetLength(cfStr));
+ CFStringGetCharacters(cfStr, CFRangeMake(0, CFStringGetLength(cfStr)), characters);
+ appendCharactersLength(characters, (unsigned int) CFStringGetLength(cfStr));
+ free(characters);
+ CFRelease(cfStr);
+#else
UChar * dest;
int32_t destLength;
int32_t destCapacity;
@@ -885,6 +961,7 @@ void String::appendUTF8CharactersLength(const char * UTF8Characters, unsigned in
appendCharactersLength(dest, destLength);
free(dest);
+#endif
}
void String::appendUTF8Characters(const char * UTF8Characters)
@@ -907,6 +984,17 @@ const UChar * String::unicodeCharacters()
const char * String::UTF8Characters()
{
+#if DISABLE_ICU
+ CFStringRef cfStr = CFStringCreateWithCharactersNoCopy(NULL, mUnicodeChars, mLength, kCFAllocatorNull);
+ char * buffer = (char *) malloc(mLength * 6 + 1);
+ CFIndex usedBufLen;
+ CFStringGetBytes(cfStr, CFRangeMake(0, mLength), kCFStringEncodingUTF8, '?', false, (UInt8 *) buffer, mLength * 6, &usedBufLen);
+ buffer[usedBufLen] = 0;
+ Data * data = Data::dataWithBytes(buffer, (unsigned int) usedBufLen + 1);
+ free(buffer);
+
+ return data->bytes();
+#else
char * dest;
int32_t destLength;
int32_t destCapacity;
@@ -924,6 +1012,7 @@ const char * String::UTF8Characters()
free(dest);
return data->bytes();
+#endif
}
unsigned int String::length()
@@ -1111,12 +1200,21 @@ int String::compareWithCaseSensitive(String * otherString, bool caseSensitive)
return -1;
}
+#if DISABLE_ICU
+ CFStringRef cfThis = CFStringCreateWithCharactersNoCopy(NULL, mUnicodeChars, mLength, kCFAllocatorNull);
+ CFStringRef cfOther = CFStringCreateWithCharactersNoCopy(NULL, otherString->mUnicodeChars, otherString->mLength, kCFAllocatorNull);
+ CFComparisonResult result = CFStringCompare(cfThis, cfOther, caseSensitive ? 0 : kCFCompareCaseInsensitive);
+ CFRelease(cfThis);
+ CFRelease(cfOther);
+ return result;
+#else
if (caseSensitive) {
return u_strcmp(unicodeCharacters(), otherString->unicodeCharacters());
}
else {
return u_strcasecmp(unicodeCharacters(), otherString->unicodeCharacters(), 0);
}
+#endif
}
int String::compare(String * otherString)
@@ -1129,8 +1227,20 @@ int String::caseInsensitiveCompare(String * otherString)
return compareWithCaseSensitive(otherString, false);
}
+//Any-Lower, Any-Upper
String * String::lowercaseString()
{
+#if DISABLE_ICU
+ CFMutableStringRef cfStr = CFStringCreateMutable(NULL, 0);
+ CFStringAppendCharacters(cfStr, (const UniChar *) mUnicodeChars, mLength);
+ CFStringLowercase(cfStr, NULL);
+ UniChar * characters = (UniChar *) malloc(sizeof(* characters) * mLength);
+ CFStringGetCharacters(cfStr, CFRangeMake(0, mLength), characters);
+ String * result = String::stringWithCharacters(characters, mLength);
+ free(characters);
+ CFRelease(cfStr);
+ return result;
+#else
UErrorCode err;
String * result = (String *) copy()->autorelease();
err = U_ZERO_ERROR;
@@ -1138,10 +1248,22 @@ String * String::lowercaseString()
result->mUnicodeChars, result->mLength,
NULL, &err);
return result;
+#endif
}
String * String::uppercaseString()
{
+#if DISABLE_ICU
+ CFMutableStringRef cfStr = CFStringCreateMutable(NULL, 0);
+ CFStringAppendCharacters(cfStr, (const UniChar *) mUnicodeChars, mLength);
+ CFStringUppercase(cfStr, NULL);
+ UniChar * characters = (UniChar *) malloc(sizeof(* characters) * mLength);
+ CFStringGetCharacters(cfStr, CFRangeMake(0, mLength), characters);
+ String * result = String::stringWithCharacters(characters, mLength);
+ free(characters);
+ CFRelease(cfStr);
+ return result;
+#else
UErrorCode err;
String * result = (String *) copy()->autorelease();
err = U_ZERO_ERROR;
@@ -1149,6 +1271,7 @@ String * String::uppercaseString()
result->mUnicodeChars, result->mLength,
NULL, &err);
return result;
+#endif
}
void String::appendBytes(const char * bytes, unsigned int length, const char * charset)
@@ -1291,7 +1414,14 @@ unsigned int String::replaceOccurrencesOfString(String * occurrence, String * re
}
// copy remaining
if(p) {
- u_strcpy(dest_p, p);
+#if DISABLE_ICU
+ unsigned int remainingLength = mLength - (unsigned int) (p - mUnicodeChars);
+ memcpy(dest_p, p, remainingLength * sizeof(* p));
+ dest_p += remainingLength;
+ * dest_p = 0;
+#else
+ u_strcpy(dest_p, p);
+#endif
}
free(mUnicodeChars);
@@ -1319,7 +1449,11 @@ void String::deleteCharactersInRange(Range range)
}
int32_t count = mLength - (int32_t) (range.location + range.length);
+#if DISABLE_ICU
+ memmove(&mUnicodeChars[range.location], &mUnicodeChars[range.location + range.length], count * sizeof(* mUnicodeChars));
+#else
u_memmove(&mUnicodeChars[range.location], &mUnicodeChars[range.location + range.length], count);
+#endif
mLength -= range.length;
mUnicodeChars[mLength] = 0;
}
@@ -1882,7 +2016,14 @@ String * String::lastPathComponent()
// TODO: Improve Windows compatibility.
if (mUnicodeChars == NULL)
return MCSTR("");
+#if DISABLE_ICU
+ UChar slash[2];
+ slash[0] = '/';
+ slash[1] = 0;
+ UChar * component = u_strrstr(mUnicodeChars, slash);
+#else
UChar * component = u_strrchr(mUnicodeChars, '/');
+#endif
if (component == NULL)
return (String *) this->copy()->autorelease();
return String::stringWithCharacters(component + 1);
@@ -1890,7 +2031,14 @@ String * String::lastPathComponent()
String * String::pathExtension()
{
+#if DISABLE_ICU
+ UChar point[2];
+ point[0] = '.';
+ point[1] = 0;
+ UChar * component = u_strrstr(mUnicodeChars, point);
+#else
UChar * component = u_strrchr(mUnicodeChars, '.');
+#endif
if (component == NULL)
return MCSTR("");
return String::stringWithCharacters(component + 1);
diff --git a/unittest/unittest.mm b/unittest/unittest.mm
index 44e367d1..ee543766 100644
--- a/unittest/unittest.mm
+++ b/unittest/unittest.mm
@@ -104,8 +104,6 @@
}
- (void)testMessageBuilder1 {
- // This is an example of a functional test case.
- //XCTAssert(YES, @"Pass");
MCOMessageBuilder * builder = [[MCOMessageBuilder alloc] init];
[[builder header] setFrom:[MCOAddress addressWithRFC822String:@"HoĆ  <dinh.viet.hoa@gmail.com>"]];
[[builder header] setTo:@[[MCOAddress addressWithRFC822String:@"Foo Bar <dinh.viet.hoa@gmail.com>"]]];
@@ -117,7 +115,8 @@
NSData * expectedData = [NSData dataWithContentsOfFile:path];
[builder _setBoundaries:@[@"1", @"2", @"3", @"4", @"5"]];
//[[builder data] writeToFile:@"/Users/hoa/builder1-now.eml" atomically:YES];
- XCTAssertEqualObjects([builder data], expectedData, @"Pass");
+ XCTAssertEqualObjects([[NSString alloc] initWithData:[builder data] encoding:NSUTF8StringEncoding], [[NSString alloc] initWithData:expectedData encoding:NSUTF8StringEncoding], @"Pass");
+ //XCTAssertEqualObjects([builder data], expectedData, @"Pass");
}
- (void)testMessageBuilder2 {
@@ -137,7 +136,7 @@
path = [_builderOutputPath stringByAppendingPathComponent:@"builder2.eml"];
NSData * expectedData = [NSData dataWithContentsOfFile:path];
//[[builder data] writeToFile:@"/Users/hoa/builder2-now.eml" atomically:YES];
- XCTAssertEqualObjects([builder data], expectedData, @"Pass");
+ XCTAssertEqualObjects([[NSString alloc] initWithData:[builder data] encoding:NSUTF8StringEncoding], [[NSString alloc] initWithData:expectedData encoding:NSUTF8StringEncoding], @"Pass");
}
- (void)testMessageBuilder3 {
@@ -159,7 +158,7 @@
path = [_builderOutputPath stringByAppendingPathComponent:@"builder3.eml"];
NSData * expectedData = [NSData dataWithContentsOfFile:path];
//[[builder data] writeToFile:@"/Users/hoa/builder3-now.eml" atomically:YES];
- XCTAssertEqualObjects([builder data], expectedData, @"Pass");
+ XCTAssertEqualObjects([[NSString alloc] initWithData:[builder data] encoding:NSUTF8StringEncoding], [[NSString alloc] initWithData:expectedData encoding:NSUTF8StringEncoding], @"Pass");
}
- (void)testMessageParser {