diff options
author | CodaFi <devteam.codafi@gmail.com> | 2013-04-28 13:13:25 -0600 |
---|---|---|
committer | CodaFi <devteam.codafi@gmail.com> | 2013-04-28 13:13:25 -0600 |
commit | 10c9d0abf0e8009277fb2006cffb76b8a26865c7 (patch) | |
tree | 73dd16206a521984a5a26b479038a4d7300070c9 /src | |
parent | 6216eee4d6c6514c2b1e324d1a999b0d7018ab7a (diff) | |
parent | 9a5c778214090b9c0fa58d65521c35b01cbcd663 (diff) |
Merge remote-tracking branch 'upstream/master' into Providers-API
Merge upstream/master
Diffstat (limited to 'src')
30 files changed, 1256 insertions, 298 deletions
diff --git a/src/core/abstract/MCAbstractPart.cc b/src/core/abstract/MCAbstractPart.cc index b07063ad..f0446167 100644 --- a/src/core/abstract/MCAbstractPart.cc +++ b/src/core/abstract/MCAbstractPart.cc @@ -3,6 +3,7 @@ #include <string.h> #include <stdlib.h> #include <libetpan/libetpan.h> +#include "MCData.h" using namespace mailcore; @@ -249,3 +250,15 @@ AbstractPart * AbstractPart::partForUniqueID(String * uniqueID) } } +String * AbstractPart::decodedStringForData(Data * data) +{ + String *lowerMimeType = mMimeType ? mMimeType->lowercaseString() : NULL; + + if (lowerMimeType && lowerMimeType->hasPrefix(MCSTR("text/"))) { + bool isHTML = lowerMimeType->isEqual(MCSTR("text/html")); + return data->stringWithDetectedCharset(mCharset, isHTML); + } + else { + return NULL; + } +} diff --git a/src/core/abstract/MCAbstractPart.h b/src/core/abstract/MCAbstractPart.h index 970b5e04..b01ba4f4 100644 --- a/src/core/abstract/MCAbstractPart.h +++ b/src/core/abstract/MCAbstractPart.h @@ -46,6 +46,8 @@ namespace mailcore { virtual AbstractPart * partForContentID(String * contentID); virtual AbstractPart * partForUniqueID(String * uniqueID); + virtual String * decodedStringForData(Data * data); + public: // subclass behavior AbstractPart(AbstractPart * other); virtual String * description(); diff --git a/src/core/abstract/MCAddress.cc b/src/core/abstract/MCAddress.cc index 4f6fc303..dce52cff 100644 --- a/src/core/abstract/MCAddress.cc +++ b/src/core/abstract/MCAddress.cc @@ -206,6 +206,32 @@ Array * Address::addressesWithNonEncodedRFC822String(String * string) return result; } +String * Address::RFC822StringForAddresses(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(address->RFC822String()); + } + return result; +} + +String * Address::nonEncodedRFC822StringForAddresses(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(address->nonEncodedRFC822String()); + } + return result; +} + String * Address::description() { String * result = String::string(); diff --git a/src/core/abstract/MCAddress.h b/src/core/abstract/MCAddress.h index 4c132ed3..ad8a36f6 100644 --- a/src/core/abstract/MCAddress.h +++ b/src/core/abstract/MCAddress.h @@ -21,6 +21,9 @@ namespace mailcore { static Array * addressesWithRFC822String(String * string); static Array * addressesWithNonEncodedRFC822String(String * string); + static String * RFC822StringForAddresses(Array * addresses); + static String * nonEncodedRFC822StringForAddresses(Array * addresses); + virtual void setDisplayName(String * displayName); virtual String * displayName(); diff --git a/src/core/abstract/MCMessageHeader.cc b/src/core/abstract/MCMessageHeader.cc index 61c126ff..e0476743 100644 --- a/src/core/abstract/MCMessageHeader.cc +++ b/src/core/abstract/MCMessageHeader.cc @@ -1070,8 +1070,9 @@ Array * MessageHeader::recipientWithReplyAll(bool replyAll, bool includeTo, bool hasCc = false; addedAddresses = new Set(); - if (senderEmails->containsObject(from()->mailbox()->lowercaseString()) || - senderEmails->containsObject(sender()->mailbox()->lowercaseString())) { + if (senderEmails != NULL && + (senderEmails->containsObject(from()->mailbox()->lowercaseString()) || + senderEmails->containsObject(sender()->mailbox()->lowercaseString()))) { Array * recipient; recipient = new Array(); @@ -1130,7 +1131,7 @@ Array * MessageHeader::recipientWithReplyAll(bool replyAll, bool includeTo, bool else { addedAddresses->addObjectsFromArray(senderEmails); - if (replyTo()->count() > 0) { + if (replyTo() != NULL && replyTo()->count() > 0) { hasTo = true; toField = replyTo(); for(unsigned int i = 0 ; i < replyTo()->count() ; i ++) { @@ -1141,7 +1142,7 @@ Array * MessageHeader::recipientWithReplyAll(bool replyAll, bool includeTo, bool } } else { - if (from()->mailbox() != NULL) { + if (from() != NULL && from()->mailbox() != NULL) { hasTo = true; toField = Array::arrayWithObject(from()); addedAddresses->addObject(from()->mailbox()->lowercaseString()); @@ -1201,14 +1202,23 @@ MessageHeader * MessageHeader::replyHeader(bool replyAll, Array * addressesExclu Array * inReplyTo; Array * toValue; Array * ccValue; - + + referencesValue = NULL; + inReplyTo = NULL; + result = new MessageHeader(); subjectValue = MCSTR("Re: ")->stringByAppendingString(subject()); - referencesValue = (Array *) (references()->copy()); - referencesValue->autorelease(); - referencesValue->addObject(messageID()); - inReplyTo = Array::array(); - inReplyTo->addObject(messageID()); + if (references() != NULL) { + referencesValue = (Array *) (references()->copy()); + referencesValue->autorelease(); + if (messageID() != NULL ) { + referencesValue->addObject(messageID()); + } + } + if (messageID()) { + inReplyTo = Array::array(); + inReplyTo->addObject(messageID()); + } toValue = recipientWithReplyAll(replyAll, true, false, addressesExcludedFromRecipient); ccValue = recipientWithReplyAll(replyAll, false, true, addressesExcludedFromRecipient);; @@ -1229,13 +1239,22 @@ MessageHeader * MessageHeader::forwardHeader() Array * referencesValue; Array * inReplyTo; + referencesValue = NULL; + inReplyTo = NULL; + result = new MessageHeader(); subjectValue = MCSTR("Fw: ")->stringByAppendingString(subject()); - referencesValue = (Array *) (references()->copy()); - referencesValue->autorelease(); - referencesValue->addObject(messageID()); - inReplyTo = Array::array(); - inReplyTo->addObject(messageID()); + if (references() != NULL) { + referencesValue = (Array *) (references()->copy()); + referencesValue->autorelease(); + if (messageID() != NULL ) { + referencesValue->addObject(messageID()); + } + } + if (messageID()) { + inReplyTo = Array::array(); + inReplyTo->addObject(messageID()); + } result->setSubject(subjectValue); result->setReferences(referencesValue); result->setInReplyTo(inReplyTo); diff --git a/src/core/basetypes/MCArray.cc b/src/core/basetypes/MCArray.cc index 73921085..c77d29ad 100644 --- a/src/core/basetypes/MCArray.cc +++ b/src/core/basetypes/MCArray.cc @@ -204,7 +204,7 @@ static int sortCompare(Object ** pa, Object ** pb, struct sortData * data) return data->compare(a, b, data->context); } -Array * Array::sortedArray(int (* compare)(void *, void *, void *), void * context) +Array * Array::sortedArray(int (* compare)(void * a, void * b, void * context), void * context) { struct sortData data; Array * result = (Array *) this->copy()->autorelease(); @@ -212,13 +212,13 @@ Array * Array::sortedArray(int (* compare)(void *, void *, void *), void * conte data.context = context; #ifdef __MACH__ qsort_r(carray_data(result->mArray), carray_count(result->mArray), - sizeof(* carray_data(result->mArray)), this, + sizeof(* carray_data(result->mArray)), &data, (int (*)(void *, const void *, const void *)) sortCompare); #else qsort_r(carray_data(result->mArray), carray_count(result->mArray), sizeof(* carray_data(result->mArray)), (int (*)(const void *, const void *, void *)) sortCompare, - this); + &data); #endif return result; } diff --git a/src/core/basetypes/MCArray.h b/src/core/basetypes/MCArray.h index ebbf1e5f..564924f8 100644 --- a/src/core/basetypes/MCArray.h +++ b/src/core/basetypes/MCArray.h @@ -34,7 +34,7 @@ namespace mailcore { virtual Object * lastObject(); virtual bool containsObject(Object * obj); - virtual Array * sortedArray(int (* compare)(void *, void *, void *), void * context); + virtual Array * sortedArray(int (* compare)(void * a, void * b, void * context), void * context); virtual String * componentsJoinedByString(String * delimiter); public: // subclass behavior diff --git a/src/core/basetypes/MCBaseTypes.h b/src/core/basetypes/MCBaseTypes.h index 6d08cdaa..4919e1f5 100644 --- a/src/core/basetypes/MCBaseTypes.h +++ b/src/core/basetypes/MCBaseTypes.h @@ -23,5 +23,7 @@ #include <MailCore/MCOperationQueue.h> #include <MailCore/MCOperationCallback.h> #include <MailCore/MCLibetpanTypes.h> +#include <MailCore/MCICUTypes.h> +#include <MailCore/MCIterator.h> #endif diff --git a/src/core/basetypes/MCICUTypes.h b/src/core/basetypes/MCICUTypes.h new file mode 100644 index 00000000..e1cff6d6 --- /dev/null +++ b/src/core/basetypes/MCICUTypes.h @@ -0,0 +1,18 @@ +// +// MCICUTypes.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 4/18/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef __MAILCORE_MCICUTYPES_H_ +#define __MAILCORE_MCICUTYPES_H_ + +#if defined(__CHAR16_TYPE__) +typedef __CHAR16_TYPE__ UChar; +#else +typedef uint16_t UChar; +#endif + +#endif diff --git a/src/core/basetypes/MCIterator.h b/src/core/basetypes/MCIterator.h new file mode 100644 index 00000000..00ff38db --- /dev/null +++ b/src/core/basetypes/MCIterator.h @@ -0,0 +1,128 @@ +// +// MCIterator.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 4/18/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef __MAILCORE_ITERATOR_H_ +#define __MAILCORE_ITERATOR_H_ + +#include <MailCore/MCArray.h> +#include <MailCore/MCHashMap.h> +#include <MailCore/MCAutoreleasePool.h> +#include <string.h> + +#ifdef __cplusplus + +#define mc_foreacharray(type, __variable, __array) \ +type * __variable; \ +mailcore::ArrayIterator __variable##__iterator = mailcore::ArrayIteratorInit(__array); \ +for (; NULL != (__variable = (type *) mailcore::ArrayIteratorNext(&__variable##__iterator)); ) + +#define mc_foreacharrayIndex(__index, type, __variable, __array) \ +type * __variable; \ +mailcore::ArrayIterator __variable##__iterator = mailcore::ArrayIteratorInit(__array); \ +for (unsigned int __index = 0; NULL != (__variable = mailcore::ArrayIteratorNext(&__variable##__iterator)); __index++) + +#define mc_foreachdictionaryKey(keyType, __key, __dictionary) \ +keyType * __key; \ +DictionaryIterator __key##__iterator = DictionaryIteratorInit(__dictionary, true, false); \ +while (DictionaryIteratorRun(&__key##__iterator)) \ +while (DictionaryIteratorNext(&__key##__iterator, &__key, NULL)) + +#define mc_foreachdictionaryValue(valueType, __value, __dictionary) \ +valueType * __value; \ +DictionaryIterator __value##__iterator = DictionaryIteratorInit(__dictionary, false, true); \ +while (DictionaryIteratorRun(&__value##__iterator)) \ +while (DictionaryIteratorNext(&__value##__iterator, NULL, &__value)) + +#define mc_foreachdictionaryKeyAndValue(__key, __value, __dictionary) \ +keyType * __key; \ +valueType * __value; \ +DictionaryIterator __key##__value##__iterator = DictionaryIteratorInit(__dictionary, true, true); \ +while (DictionaryIteratorRun(&__key##__value##__iterator)) \ +while (DictionaryIteratorNext(&__key##__value##__iterator, &__key, &__value)) + +namespace mailcore { + + struct ArrayIterator { + unsigned index; + unsigned count; + Array * array; + }; + + static inline ArrayIterator ArrayIteratorInit(Array * array) + { + ArrayIterator iterator = { 0, array->count(), array }; + return iterator; + } + + static inline Object * ArrayIteratorNext(ArrayIterator * iterator) + { + if (iterator->index >= iterator->count) { + return NULL; + } + + Object * result = iterator->array->objectAtIndex(iterator->index); + ++ iterator->index; + return result; + } + + + struct HashMapIterator { + bool cleanup; + unsigned index; + unsigned count; + Array * keys; + Array * values; + }; + + static inline HashMapIterator FastDictionaryIteratorInit(HashMap * hashmap, bool useKeys, bool useValues) + { + AutoreleasePool * pool = new AutoreleasePool(); + Array * keys = useKeys ? hashmap->allKeys() : NULL; + Array * values = useValues ? hashmap->allValues() : NULL; + keys->retain(); + values->retain(); + HashMapIterator iterator = { false, 0, hashmap->count(), keys, values }; + pool->release(); + + return iterator; + } + + static inline bool HashMapIteratorNext(HashMapIterator * iterator, Object ** keyp, Object ** valuep) + { + if (iterator->index >= iterator->count) { + return false; + } + + if (keyp != NULL) { + * keyp = iterator->keys->objectAtIndex(iterator->index); + } + if (valuep != NULL) { + * valuep = iterator->values->objectAtIndex(iterator->index); + } + iterator->index ++; + return true; + } + + + static inline bool DictionaryIteratorRun(HashMapIterator * iterator) + { + if (iterator->cleanup) { + iterator->cleanup = true; + return true; + } else { + iterator->keys->release(); + iterator->values->release(); + return false; + } + } + +}; + +#endif + +#endif diff --git a/src/core/basetypes/MCJSON.cpp b/src/core/basetypes/MCJSON.cpp index f6bc5956..20b4876f 100644 --- a/src/core/basetypes/MCJSON.cpp +++ b/src/core/basetypes/MCJSON.cpp @@ -10,241 +10,32 @@ #include <string.h> -#include "libjson.h" -#include "MCNull.h" -#include <MailCore/MCUtils.h> -#include <MailCore/MCAssert.h> +#include "MCJSONParser.h" using namespace mailcore; -String * JSON::objectToJSONString(Object * object, bool pretty) -{ - void * node = objectToJSON(object); - char * cstr; - if (pretty) { - cstr = json_write_formatted(node); - } - else { - cstr = json_write(node); - } - - String * result = String::stringWithUTF8Characters(cstr); - - json_free(cstr); - json_delete(node); - - return result; -} - -Data * JSON::objectToJSONData(Object * object, bool pretty) -{ - void * node = objectToJSON(object); - char * cstr; - if (pretty) { - cstr = json_write_formatted(node); - } - else { - cstr = json_write(node); - } - - Data * result = Data::dataWithBytes(cstr, (unsigned int) strlen(cstr)); - - json_free(cstr); - json_delete(node); - - return result; -} - -Object * JSON::objectFromJSONString(String * json) -{ - void * node = json_parse(json->UTF8Characters()); - Object * object = objectFromJSON(node); - json_delete(node); - return object; -} - -Object * JSON::objectFromJSONData(Data * json) -{ - //printf("rcv: [%.*s]\n", (int) json->length(), json->bytes()); - - void * node = json_parse(json->bytes()); - Object * object = objectFromJSON(node); - json_delete(node); - return object; -} - -void * JSON::hashMapToJSON(HashMap * hashmap) -{ - JSONNODE * result = json_new(JSON_NODE); - Array * keys = hashmap->allKeys(); - for(unsigned int i = 0 ; i < keys->count() ; i ++) { - String * key = (String *) keys->objectAtIndex(i); - JSONNODE * item = objectToJSON(hashmap->objectForKey(key)); - json_set_name(item, key->UTF8Characters()); - json_push_back(result, item); - } - return result; -} - -void * JSON::arrayToJSON(Array * array) -{ - JSONNODE * result = json_new(JSON_ARRAY); - for(unsigned int i = 0 ; i < array->count() ; i ++) { - Object * value = array->objectAtIndex(i); - JSONNODE * item = objectToJSON(value); - json_push_back(result, item); - } - return result; -} - -void * JSON::stringToJSON(String * string) -{ - return json_new_a("", string->UTF8Characters()); -} +static Object * objectFromData(Data * data); +static Object * objectFromString(String * str); -void * JSON::doubleToJSON(Value * value) -{ - switch (value->type()) { - case ValueTypeChar: - return json_new_f("", value->charValue()); - case ValueTypeUnsignedChar: - return json_new_f("", value->unsignedCharValue()); - case ValueTypeShort: - return json_new_f("", value->shortValue()); - case ValueTypeUnsignedShort: - return json_new_f("", value->unsignedShortValue()); - case ValueTypeInt: - return json_new_f("", value->intValue()); - case ValueTypeUnsignedInt: - return json_new_f("", value->unsignedIntValue()); - case ValueTypeLong: - return json_new_f("", value->longValue()); - case ValueTypeUnsignedLong: - return json_new_f("", value->unsignedLongValue()); - case ValueTypeLongLong: - return json_new_f("", value->longLongValue()); - case ValueTypeUnsignedLongLong: - return json_new_f("", value->unsignedLongLongValue()); - case ValueTypeFloat: - return json_new_f("", value->floatValue()); - case ValueTypeDouble: - return json_new_f("", value->doubleValue()); - default: - return json_new_f("", 0.); - } -} - -void * JSON::boolToJSON(Value * value) -{ - return json_new_b("", value->boolValue()); -} - -void * JSON::nullToJSON(Null * value) -{ - return json_new(JSON_NULL); -} - -void * JSON::objectToJSON(Object * object) -{ - String * name = object->className(); - if (name->isEqual(MCSTR("mailcore::Null"))) { - return nullToJSON((Null *) object); - } - else if (name->isEqual(MCSTR("mailcore::Value"))) { - Value * value = (Value *) object; - if (value->type() == ValueTypeBool) { - return boolToJSON(value); - } - else { - return doubleToJSON(value); - } - } - else if (name->isEqual(MCSTR("mailcore::String"))) { - return stringToJSON((String *) object); - } - else if (name->isEqual(MCSTR("mailcore::Array"))) { - return arrayToJSON((Array *) object); - } - else if (name->isEqual(MCSTR("mailcore::HashMap"))) { - return hashMapToJSON((HashMap *) object); - } - else { - MCAssert(0); - return NULL; - } -} +static Data * dataFromObject(Object * object); +static String * stringFromObject(Object * object); -HashMap * JSON::hashMapFromJSON(void * json) +String * JSON::objectToJSONString(Object * object) { - HashMap * result = HashMap::hashMap(); - JSONNODE_ITERATOR i = json_begin(json); - while (i != json_end(json)){ - json_char * ckey = json_name(*i); - String * key = String::stringWithUTF8Characters(ckey); - Object * value = objectFromJSON(* i); - - result->setObjectForKey(key, value); - - json_free(ckey); - ++i; - } - return result; + return JSONParser::stringFromObject(object); } -Array * JSON::arrayFromJSON(void * json) +Data * JSON::objectToJSONData(Object * object) { - Array * result = Array::array(); - JSONNODE_ITERATOR i = json_begin(json); - while (i != json_end(json)){ - Object * obj = objectFromJSON(* i); - result->addObject(obj); - ++i; - } - return result; + return JSONParser::dataFromObject(object); } -String * JSON::stringFromJSON(void * json) -{ - json_char * cstr = json_as_string(json); - String * result = String::stringWithUTF8Characters(cstr); - json_free(cstr); - return result; -} - -Value * JSON::doubleFromJSON(void * json) -{ - json_number value = json_as_float(json); - return Value::valueWithDoubleValue(value); -} - -Value * JSON::boolFromJSON(void * json) -{ - json_bool_t value = json_as_bool(json); - return Value::valueWithBoolValue(value); -} - -Null * JSON::nullFromJSON(void * json) +Object * JSON::objectFromJSONString(String * json) { - return Null::null(); + return JSONParser::objectFromString(json); } -Object * JSON::objectFromJSON(void * json) +Object * JSON::objectFromJSONData(Data * json) { - switch (json_type(json)) { - case JSON_NULL: - return nullFromJSON(json); - case JSON_STRING: - return stringFromJSON(json); - case JSON_NUMBER: - return doubleFromJSON(json); - case JSON_BOOL: - return boolFromJSON(json); - case JSON_ARRAY: - return arrayFromJSON(json); - case JSON_NODE: - return hashMapFromJSON(json); - default: - MCAssert(0); - return NULL; - } + return JSONParser::objectFromData(json); } diff --git a/src/core/basetypes/MCJSON.h b/src/core/basetypes/MCJSON.h index 77100991..c49fd813 100644 --- a/src/core/basetypes/MCJSON.h +++ b/src/core/basetypes/MCJSON.h @@ -24,27 +24,10 @@ namespace mailcore { class JSON { public: - static String * objectToJSONString(Object * object, bool pretty = false); - static Data * objectToJSONData(Object * object, bool pretty = false); + static String * objectToJSONString(Object * object); + static Data * objectToJSONData(Object * object); static Object * objectFromJSONString(String * json); static Object * objectFromJSONData(Data * json); - - private: - static void * hashMapToJSON(HashMap * hashmap); - static void * arrayToJSON(Array * array); - static void * stringToJSON(String * string); - static void * doubleToJSON(Value * value); - static void * boolToJSON(Value * value); - static void * nullToJSON(Null * value); - static void * objectToJSON(Object * object); - - static HashMap * hashMapFromJSON(void * json); - static Array * arrayFromJSON(void * json); - static String * stringFromJSON(void * json); - static Value * doubleFromJSON(void * json); - static Value * boolFromJSON(void * json); - static Null * nullFromJSON(void * json); - static Object * objectFromJSON(void * json); }; } diff --git a/src/core/basetypes/MCJSONParser.cpp b/src/core/basetypes/MCJSONParser.cpp new file mode 100644 index 00000000..c72f0c8b --- /dev/null +++ b/src/core/basetypes/MCJSONParser.cpp @@ -0,0 +1,827 @@ +// +// JSONParser.cpp +// mailcore2 +// +// Created by DINH Viêt Hoà on 4/17/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include "MCJSONParser.h" + +#include <stdlib.h> + +#include "MCUtils.h" +#include "MCString.h" +#include "MCData.h" +#include "MCHashMap.h" +#include "MCArray.h" +#include "MCValue.h" +#include "MCNull.h" +#include "MCAutoreleasePool.h" +#include "MCAssert.h" + +using namespace mailcore; + +void JSONParser::init() +{ + mContent = NULL; + mResult = NULL; + mPosition = 0; +} + +JSONParser::JSONParser() +{ + init(); +} + +JSONParser::~JSONParser() +{ + MC_SAFE_RELEASE(mResult); + MC_SAFE_RELEASE(mContent); +} + +String * JSONParser::content() +{ + return mContent; +} + +void JSONParser::setContent(String * content) +{ + MC_SAFE_REPLACE_COPY(String, mContent, content); +} + +unsigned int JSONParser::position() +{ + return mPosition; +} + +void JSONParser::setPosition(unsigned int position) +{ + mPosition = position; +} + +Object * JSONParser::result() +{ + return mResult; +} + +bool JSONParser::parse() +{ + skipBlank(); + if (parseDictionary()) + return true; + if (parseArray()) + return true; + if (parseBoolean()) + return true; + if (parseNull()) + return true; + if (parseFloat()) + return true; + if (parseString()) + return true; + + return false; +} + +bool JSONParser::isEndOfExpression() +{ + if (mPosition == mContent->length()) + return true; + + if (mContent->characterAtIndex(mPosition) == ';') + return true; + + return false; +} + +void JSONParser::skipBlank() +{ + mPosition = skipBlank(mPosition); +} + +unsigned int JSONParser::skipBlank(unsigned int position) +{ + while (1) { + UChar ch; + + if (position >= mContent->length()) + break; + + ch = mContent->characterAtIndex(position); + if ((ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == '\n')) + position ++; + else + break; + } + + return position; +} + +bool JSONParser::parseDictionary() +{ + int position; + HashMap * dict; + + position = mPosition; + + if (!scanCharacter('{', position)) { + return false; + } + position ++; + position = skipBlank(position); + + dict = HashMap::hashMap(); + + if (scanCharacter('}', position)) { + position ++; + } + else { + while (1) { + JSONParser * keyParser; + JSONParser * valueParser; + String * key; + Object * value; + + if (position >= mContent->length()) + return false; + + key = NULL; + keyParser = new JSONParser(); + keyParser->autorelease(); + keyParser->setContent(mContent); + keyParser->setPosition(position); + if (!keyParser->parse()) + return false; + + if (!keyParser->result()->className()->isEqual(MCSTR("mailcore::String"))) + return false; + + key = (String *) keyParser->result(); + position = keyParser->position(); + + position = skipBlank(position); + + if (!scanCharacter(':', position)) + return false; + position ++; + + position = skipBlank(position); + + value = NULL; + valueParser = new JSONParser(); + valueParser->autorelease(); + valueParser->setContent(mContent); + valueParser->setPosition(position); + if (!valueParser->parse()) + return false; + + value = valueParser->result(); + position = valueParser->position(); + + dict->setObjectForKey(key, value); + + position = skipBlank(position); + + if (scanCharacter(',', position)) { + position ++; + position = skipBlank(position); + } + else if (scanCharacter('}', position)) { + position ++; + break; + } + else { + return false; + } + } + } + + mResult = dict->retain(); + mPosition = position; + + return true; +} + +bool JSONParser::scanCharacter(UChar ch, unsigned int position) +{ + if (position >= mContent->length()) + return false; + + if (mContent->characterAtIndex(position) != ch) + return false; + + return true; +} + +bool JSONParser::scanKeyword(String * str, unsigned int position) +{ + bool result; + AutoreleasePool * pool; + + if (position + str->length() >= mContent->length()) + return false; + + pool = new AutoreleasePool(); + + result = false; + if (mContent->substringWithRange(RangeMake(position, str->length()))->isEqual(str)) + result = true; + pool->release(); + + return result; +} + +bool JSONParser::parseArray() +{ + int position; + Array * array; + + position = mPosition; + + if (!scanCharacter('[', position)) { + return false; + } + position ++; + position = skipBlank(position); + + array = Array::array(); + + if (scanCharacter(']', position)) { + position ++; + } + else { + while (1) { + JSONParser * valueParser; + Object * value; + + if (position >= mContent->length()) + return false; + + value = NULL; + valueParser = new JSONParser(); + valueParser->setContent(mContent); + valueParser->setPosition(position); + valueParser->autorelease(); + if (!valueParser->parse()) + return false; + + value = valueParser->result(); + + position = valueParser->position(); + array->addObject(value); + + position = skipBlank(position); + + if (scanCharacter(',', position)) { + position ++; + position = skipBlank(position); + } + else if (scanCharacter(']', position)) { + position ++; + break; + } + else { + return false; + } + } + } + + mResult = array->retain(); + mPosition = position; + + return true; +} + +static inline int hexToInt(UChar inCharacter) +{ + if (inCharacter >= '0' && inCharacter <= '9') { + return inCharacter - '0'; + } + else if (inCharacter >= 'a' && inCharacter <= 'f') { + return inCharacter - 'a' + 10; + } + else if (inCharacter >= 'A' && inCharacter <= 'F') { + return inCharacter - 'A' + 10; + } + else { + return -1; + } +} + +bool JSONParser::parseString() +{ + unsigned int position; + String * str; + bool doubleQuote = false; + bool startString; + bool endOfString; + + position = mPosition; + + startString = false; + if (scanCharacter('\"', position)) { + doubleQuote = true; + startString = true; + } + else if (scanCharacter('\'', position)) { + startString = true; + } + + if (!startString) + return false; + + position ++; + + str = String::string(); + + endOfString = false; + while (1) { + UChar ch; + + if (position >= mContent->length()) + return false; + + ch = mContent->characterAtIndex(position); + switch (ch) { + case '\\': + { + position ++; + + if (position >= mContent->length()) + return false; + + ch = mContent->characterAtIndex(position); + switch (ch) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': { + UChar char_value; + unsigned int count; + + count = 0; + char_value = 0; + while ((ch >= '0') && (ch <= '7')) { + int value; + + value = hexToInt(ch); + if (value == -1) + break; + + char_value = char_value * 8 + value; + count ++; + position ++; + if (count >= 3) + break; + if (position >= mContent->length()) + break; + ch = mContent->characterAtIndex(position); + } + UChar characters[2]; + characters[0] = char_value; + characters[1] = 0; + str->appendCharactersLength(characters, 1); + break; + } + case 'b': + str->appendString(MCSTR("\b")); + position ++; + break; + case 't': + str->appendString(MCSTR("\t")); + position ++; + break; + case 'n': + str->appendString(MCSTR("\n")); + position ++; + break; + case 'r': + str->appendString(MCSTR("\r")); + position ++; + break; + case 'f': + str->appendString(MCSTR("\f")); + position ++; + break; + case 'v': + str->appendString(MCSTR("\v")); + position ++; + break; + case '\"': + str->appendString(MCSTR("\"")); + position ++; + break; + case '\'': + str->appendString(MCSTR("\'")); + position ++; + break; + case '\\': + str->appendString(MCSTR("\\")); + position ++; + break; + case '/': + str->appendString(MCSTR("/")); + position ++; + break; + case 'u': { + unsigned int i; + UChar char_value; + + position ++; + char_value = 0; + for(i = 0 ; i < 4 ; i ++) { + int value; + + if (position >= mContent->length()) + return false; + ch = mContent->characterAtIndex(position); + value = hexToInt(ch); + if (value == -1) + break; + + char_value = char_value * 16 + value; + position ++; + } + + UChar characters[2]; + characters[0] = char_value; + characters[1] = 0; + str->appendCharactersLength(characters, 1); + + break; + } + case 'x': { + unsigned int i; + UChar char_value; + + position ++; + char_value = 0; + for(i = 0 ; i < 2 ; i ++) { + int value; + + if (position >= mContent->length()) + return false; + ch = mContent->characterAtIndex(position); + value = hexToInt(ch); + if (value == -1) + break; + + char_value = char_value * 16 + value; + position ++; + } + + UChar characters[2]; + characters[0] = char_value; + characters[1] = 0; + str->appendCharactersLength(characters, 1); + + break; + } + default: { + UChar characters[3]; + characters[0] = '\\'; + characters[1] = ch; + characters[2] = 0; + str->appendCharactersLength(characters, 2); + + position ++; + break; + } + } + break; + } + + case '\'': + position ++; + if (!doubleQuote) + endOfString = true; + else + str->appendString(MCSTR("\'")); + break; + case '\"': + position ++; + if (doubleQuote) + endOfString = true; + else + str->appendString(MCSTR("\"")); + break; + default: { + position ++; + UChar characters[2]; + characters[0] = ch; + characters[1] = 0; + str->appendCharactersLength(characters, 1); + break; + } + } + + if (endOfString) + break; + } + + mResult = str->retain(); + mPosition = position; + + return true; +} + +bool JSONParser::parseBoolean() +{ + if (scanKeyword(MCSTR("true"), mPosition)) { + mPosition += MCSTR("true")->length(); + mResult = Value::valueWithBoolValue(true)->retain();; + return true; + } + + if (scanKeyword(MCSTR("false"), mPosition)) { + mPosition += MCSTR("false")->length(); + mResult = Value::valueWithBoolValue(false)->retain();; + return true; + } + + return false; +} + +bool JSONParser::parseNull() +{ + if (scanKeyword(MCSTR("null"), mPosition)) { + mPosition += MCSTR("null")->length(); + mResult = Null::null()->retain(); + return true; + } + + return false; +} + +bool JSONParser::parseFloat() +{ + const char * str; + char * endptr; + double value; + char * endptrInt; + long long valueInt; + + AutoreleasePool * pool; + + pool = new AutoreleasePool(); + if (mContent->length() > mPosition + 50) { + str = mContent->substringWithRange(RangeMake(mPosition, 50))->UTF8Characters(); + } + else { + str = mContent->substringFromIndex(mPosition)->UTF8Characters(); + } + value = strtod(str, &endptr); + if (endptr == str) { + pool->release(); + return false; + } + valueInt = strtoll(str, &endptrInt, 0); + if (endptr == endptrInt) { + mPosition += endptrInt - str; + mResult = Value::valueWithLongLongValue(valueInt)->retain(); + } + else { + mPosition += endptr - str; + mResult = Value::valueWithDoubleValue(value); + } + pool->release(); + + return true; +} + +Object * JSONParser::objectFromData(Data * data) +{ + String * str = NULL; + Object * result; + + str = String::stringWithData(data, "utf-8"); + if (str == NULL) + return NULL; + + result = objectFromString(str); + + return result; +} + +Object * JSONParser::objectFromString(String * str) +{ + Object * result; + JSONParser * parser; + + parser = new JSONParser(); + parser->setContent(str); + parser->parse(); + result = parser->result(); + result->retain()->autorelease(); + parser->release(); + + return result; +} + +Data * JSONParser::dataFromObject(Object * object) +{ + return stringFromObject(object)->dataUsingEncoding("utf-8"); +} + +String * JSONParser::stringFromObject(Object * object) +{ + String * result; + + result = String::string(); + appendStringFromObject(object, result); + + return result; +} + + +String * JSONParser::JSStringFromString(String * str) +{ + unsigned int i; + String * result; + + result = String::string(); + for(i = 0 ; i < str->length() ; i ++) { + UChar ch; + + ch = str->characterAtIndex(i); + if ((ch >= '0') && (ch <= '9')) { + UChar characters[2]; + characters[0] = ch; + characters[1] = 0; + result->appendCharactersLength(characters, 1); + } + else if ((ch >= 'a') && (ch <= 'z')) { + UChar characters[2]; + characters[0] = ch; + characters[1] = 0; + result->appendCharactersLength(characters, 1); + } + else if ((ch >= 'A') && (ch <= 'Z')) { + UChar characters[2]; + characters[0] = ch; + characters[1] = 0; + result->appendCharactersLength(characters, 1); + } + else { + switch (ch) { + case ' ': + case '.': + case ',': + case '<': + case '>': + case '(': + case ')': + case '!': + case '@': + case '#': + case '$': + case '%': + case '^': + case '&': + case '*': + case '-': + case '_': + case '+': + case '=': + case '?': + case '{': + case '}': + case '[': + case ']': + case ':': + case ';': + case '|': + case '~': + case '\'': { + UChar characters[2]; + characters[0] = ch; + characters[1] = 0; + result->appendCharactersLength(characters, 1); + break; + } + case '"': + case '/': + case '\\': { + UChar characters[3]; + characters[0] = '\\'; + characters[1] = ch; + characters[2] = 0; + result->appendCharactersLength(characters, 2); + break; + } + default: { + result->appendUTF8Format("\\u%04x", (unsigned int) ch); + break; + } + } + } + } + + return result; +} + +void JSONParser::appendStringFromObject(Object * object, String * string) +{ + if (object->className()->isEqual(MCSTR("mailcore::String"))) { + string->appendString(MCSTR("\"")); + string->appendString(JSStringFromString((String *) object)); + string->appendString(MCSTR("\"")); + } + else if (object->className()->isEqual(MCSTR("mailcore::Value"))) { + Value * value = (Value *) object; + switch (value->type()) { + case ValueTypeBool: + string->appendString(value->boolValue() ? MCSTR("true") : MCSTR("false")); + break; + case ValueTypeChar: + string->appendUTF8Format("%i", (int) value->charValue()); + break; + case ValueTypeUnsignedChar: + string->appendUTF8Format("%i", (int) value->unsignedCharValue()); + break; + case ValueTypeShort: + string->appendUTF8Format("%i", (int) value->shortValue()); + break; + case ValueTypeUnsignedShort: + string->appendUTF8Format("%i", (int) value->unsignedShortValue()); + break; + case ValueTypeInt: + string->appendUTF8Format("%i", (int) value->intValue()); + break; + case ValueTypeUnsignedInt: + string->appendUTF8Format("%u", (int) value->unsignedIntValue()); + break; + case ValueTypeLong: + string->appendUTF8Format("%ld", value->longValue()); + break; + case ValueTypeUnsignedLong: + string->appendUTF8Format("%lu", value->unsignedLongValue()); + break; + case ValueTypeLongLong: + string->appendUTF8Format("%lld", value->longLongValue()); + break; + case ValueTypeUnsignedLongLong: + string->appendUTF8Format("%llu", value->unsignedLongLongValue()); + break; + case ValueTypeFloat: + string->appendUTF8Format("%g", value->floatValue()); + break; + case ValueTypeDouble: + string->appendUTF8Format("%lg", value->doubleValue()); + break; + default: + MCAssert(0); + break; + } + } + else if (object->className()->isEqual(MCSTR("mailcore::Null"))) { + string->appendString(MCSTR("null")); + } + else if (object->className()->isEqual(MCSTR("mailcore::Array"))) { + Array * array; + bool first; + + first = true; + array = (Array *) object; + string->appendString(MCSTR("[")); + for(unsigned int i = 0 ; i < array->count() ; i ++) { + Object * arrayElement = array->objectAtIndex(i); + if (first) { + first = false; + } + else { + string->appendString(MCSTR(",")); + } + appendStringFromObject(arrayElement, string); + } + string->appendString(MCSTR("]")); + } + else if (object->className()->isEqual(MCSTR("mailcore::HashMap"))) { + HashMap * dict; + bool first; + + first = true; + dict = (HashMap *) object; + string->appendString(MCSTR("{")); + Array * keys = dict->allKeys(); + for(unsigned int i = 0 ; i < keys->count() ; i ++) { + String * key = (String *) keys->objectAtIndex(i); + + if (first) { + first = false; + } + else { + string->appendString(MCSTR(",")); + } + appendStringFromObject(key, string); + string->appendString(MCSTR(":")); + appendStringFromObject(dict->objectForKey(key), string); + } + string->appendString(MCSTR("}")); + } +} diff --git a/src/core/basetypes/MCJSONParser.h b/src/core/basetypes/MCJSONParser.h new file mode 100644 index 00000000..f27e924e --- /dev/null +++ b/src/core/basetypes/MCJSONParser.h @@ -0,0 +1,66 @@ +// +// JSONParser.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 4/17/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef __MAILCORE_MCJSONPARSER_H_ +#define __MAILCORE_MCJSONPARSER_H_ + +#include <MailCore/MCObject.h> +#include <MailCore/MCICUTypes.h> + +namespace mailcore { + + class Data; + class String; + + class JSONParser : public Object { + + public: + JSONParser(); + virtual ~JSONParser(); + + virtual String * content(); + virtual void setContent(String * content); + + virtual unsigned int position(); + virtual void setPosition(unsigned int position); + + virtual Object * result(); + + virtual bool parse(); + + virtual bool isEndOfExpression(); + + static Object * objectFromData(Data * data); + static Object * objectFromString(String * str); + + static Data * dataFromObject(Object * object); + static String * stringFromObject(Object * object); + + private: + Object * mResult; + unsigned int mPosition; + String * mContent; + void init(); + + void skipBlank(); + unsigned int skipBlank(unsigned int position); + bool parseDictionary(); + bool scanCharacter(UChar ch, unsigned int position); + bool scanKeyword(String * str, unsigned int position); + bool parseArray(); + bool parseString(); + bool parseBoolean(); + bool parseNull(); + bool parseFloat(); + static String * JSStringFromString(String * str); + static void appendStringFromObject(Object * object, String * string); + }; + +} + +#endif
\ No newline at end of file diff --git a/src/core/basetypes/MCString.h b/src/core/basetypes/MCString.h index c7da4788..fdbf174a 100644 --- a/src/core/basetypes/MCString.h +++ b/src/core/basetypes/MCString.h @@ -4,17 +4,12 @@ #include <MailCore/MCObject.h> #include <MailCore/MCRange.h> +#include <MailCore/MCICUTypes.h> #include <stdarg.h> #ifdef __cplusplus -#if defined(__CHAR16_TYPE__) -typedef __CHAR16_TYPE__ UChar; -#else -typedef uint16_t UChar; -#endif - namespace mailcore { class Data; @@ -44,6 +39,7 @@ namespace mailcore { virtual void appendString(String * otherString); virtual void appendUTF8Format(const char * format, ...); virtual void appendCharacters(const UChar * unicodeCharacters); + virtual void appendCharactersLength(const UChar * unicodeCharacters, unsigned int length); virtual void appendUTF8Characters(const char * UTF8Characters); virtual void setString(String * otherString); virtual void setUTF8Characters(const char * UTF8Characters); @@ -126,7 +122,6 @@ namespace mailcore { unsigned int mLength; unsigned int mAllocated; void allocate(unsigned int length); - void appendCharactersLength(const UChar * unicodeCharacters, unsigned int length); void reset(); int compareWithCaseSensitive(String * otherString, bool caseSensitive); void appendBytes(const char * bytes, unsigned int length, const char * charset); diff --git a/src/core/renderer/MCAddressDisplay.cpp b/src/core/renderer/MCAddressDisplay.cpp index 842dd0df..4a0fe44b 100644 --- a/src/core/renderer/MCAddressDisplay.cpp +++ b/src/core/renderer/MCAddressDisplay.cpp @@ -56,15 +56,7 @@ String * AddressDisplay::veryShortDisplayStringForAddress(Address * address) 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; + return Address::nonEncodedRFC822StringForAddresses(addresses); } String * AddressDisplay::shortDisplayStringForAddresses(Array * addresses) diff --git a/src/core/renderer/MCHTMLRenderer.cpp b/src/core/renderer/MCHTMLRenderer.cpp index 71454a0e..7d03f650 100644 --- a/src/core/renderer/MCHTMLRenderer.cpp +++ b/src/core/renderer/MCHTMLRenderer.cpp @@ -328,17 +328,21 @@ String * htmlForAbstractSinglePart(AbstractPart * part, htmlRendererContext * co String * htmlForAbstractMessagePart(AbstractMessagePart * part, htmlRendererContext * context) { - String * substring = htmlForAbstractPart(part->mainPart(), context); if (context->pass == 0) { return NULL; } + String * substring = htmlForAbstractPart(part->mainPart(), context); MCAssert(substring != NULL); - String * result = String::string(); HashMap * values = context->htmlCallback->templateValuesForHeader(part->header()); String * headerString = renderTemplate(context->htmlCallback->templateForEmbeddedMessageHeader(), values); - result->appendString(headerString); - result->appendString(substring); + + HashMap * msgValues = new HashMap(); + msgValues->setObjectForKey(MCSTR("HEADER"), headerString); + msgValues->setObjectForKey(MCSTR("BODY"), substring); + String * result = renderTemplate(context->htmlCallback->templateForEmbeddedMessage(), msgValues); + msgValues->release(); + return result; } diff --git a/src/core/rfc822/MCAttachment.cc b/src/core/rfc822/MCAttachment.cc index c75e689a..b6167941 100644 --- a/src/core/rfc822/MCAttachment.cc +++ b/src/core/rfc822/MCAttachment.cc @@ -247,6 +247,17 @@ Data * Attachment::data() return mData; } +String * Attachment::decodedString() +{ + if (mData) { + return decodedStringForData(mData); + } + else { + return NULL; + } +} + + AbstractPart * Attachment::attachmentsWithMIME(struct mailmime * mime) { return attachmentsWithMIMEWithMain(mime, true); diff --git a/src/core/rfc822/MCAttachment.h b/src/core/rfc822/MCAttachment.h index c1fc232e..272e589d 100644 --- a/src/core/rfc822/MCAttachment.h +++ b/src/core/rfc822/MCAttachment.h @@ -26,6 +26,7 @@ namespace mailcore { virtual void setData(Data * data); virtual Data * data(); + virtual String * decodedString(); public: // subclass behavior Attachment(Attachment * other); diff --git a/src/objc/abstract/MCOAbstractMessageRendererCallback.mm b/src/objc/abstract/MCOAbstractMessageRendererCallback.mm index 8905acf5..883cb25f 100644 --- a/src/objc/abstract/MCOAbstractMessageRendererCallback.mm +++ b/src/objc/abstract/MCOAbstractMessageRendererCallback.mm @@ -104,7 +104,7 @@ mailcore::String * MCOAbstractMessageRendererCallback::templateForEmbeddedMessag { mailcore::String * result = NULL; if ([mRendererDelegate respondsToSelector:@selector(MCOAbstractMessage_templateForEmbeddedMessage:)]) { - return MCO_FROM_OBJC(mailcore::String, [mRendererDelegate MCOAbstractMessage_templateForEmbeddedMessage:mMessage]); + result = MCO_FROM_OBJC(mailcore::String, [mRendererDelegate MCOAbstractMessage_templateForEmbeddedMessage:mMessage]); } if (result == NULL) { result = mailcore::HTMLRendererTemplateCallback::templateForEmbeddedMessage(); @@ -116,7 +116,7 @@ mailcore::String * MCOAbstractMessageRendererCallback::templateForEmbeddedMessag { mailcore::String * result = NULL; if ([mRendererDelegate respondsToSelector:@selector(MCOAbstractMessage_templateForEmbeddedMessageHeader:)]) { - return MCO_FROM_OBJC(mailcore::String, [mRendererDelegate MCOAbstractMessage_templateForEmbeddedMessageHeader:mMessage]); + result = MCO_FROM_OBJC(mailcore::String, [mRendererDelegate MCOAbstractMessage_templateForEmbeddedMessageHeader:mMessage]); } if (result == NULL) { result = mailcore::HTMLRendererTemplateCallback::templateForEmbeddedMessageHeader(); diff --git a/src/objc/abstract/MCOAbstractPart.h b/src/objc/abstract/MCOAbstractPart.h index 6fb14fcd..5c636a19 100644 --- a/src/objc/abstract/MCOAbstractPart.h +++ b/src/objc/abstract/MCOAbstractPart.h @@ -74,6 +74,9 @@ typedef enum { // Returns the part with the given unique identifier among this part and its subparts. - (MCOAbstractPart *) partForUniqueID:(NSString *)uniqueID; +// Returns a string representation of the data according to charset. +- (NSString *) decodedStringForData:(NSData *)data; + @end #endif diff --git a/src/objc/abstract/MCOAbstractPart.mm b/src/objc/abstract/MCOAbstractPart.mm index 1d17ca20..47191ce9 100644 --- a/src/objc/abstract/MCOAbstractPart.mm +++ b/src/objc/abstract/MCOAbstractPart.mm @@ -14,6 +14,7 @@ #import "NSString+MCO.h" #import "NSObject+MCO.h" +#import "NSData+MCO.h" @implementation MCOAbstractPart { mailcore::AbstractPart * _part; @@ -68,4 +69,8 @@ MCO_OBJC_SYNTHESIZE(AbstractMessage, setMessage, message) return MCO_TO_OBJC(MCO_NATIVE_INSTANCE->partForUniqueID([uniqueID mco_mcString])); } +- (NSString *) decodedStringForData:(NSData *)data +{ + return [NSString mco_stringWithMCString:MCO_NATIVE_INSTANCE->decodedStringForData([data mco_mcData])]; +} @end diff --git a/src/objc/abstract/MCOAddress.h b/src/objc/abstract/MCOAddress.h index 33f2c545..c7552676 100644 --- a/src/objc/abstract/MCOAddress.h +++ b/src/objc/abstract/MCOAddress.h @@ -31,6 +31,17 @@ // Example: [MCOAddress addressWithRFC822String:@"DINH Viêt Hoà <hoa@etpan.org>"] + (MCOAddress *) addressWithNonEncodedRFC822String:(NSString *)nonEncodedRFC822String; +// Returns an NSArray of MCOAddress objects that contain the parsed +// forms of the RFC822 encoded addresses. +// For example: @[ @"DINH Vi=C3=AAt Ho=C3=A0 <hoa@etpan.org>" ] ++ (NSArray *) addressesWithRFC822String:(NSString *)string; + +// Returns an NSArray of MCOAddress objects that contain the parsed +// forms of non-encoded RFC822 addresses. +// For example: @[ "DINH Viêt Hoà <hoa@etpan.org>" ] ++ (NSArray *) addressesWithNonEncodedRFC822String:(NSString *)string; + + // Returns the display name of the address. @property (nonatomic, copy) NSString * displayName; @@ -47,17 +58,13 @@ @end -@interface MCOAddress (MCONSArray) +@interface NSArray (MCONSArray) -// Returns an NSArray of MCOAddress objects that contain the parsed -// forms of the RFC822 encoded addresses. -// For example: @[ @"DINH Vi=C3=AAt Ho=C3=A0 <hoa@etpan.org>" ] -+ (NSArray *) addressesWithRFC822String:(NSString *)string; +// Returns the RFC822 encoding of the addresses. +- (NSString *) mco_RFC822StringForAddresses; -// Returns an NSArray of MCOAddress objects that contain the parsed -// forms of non-encoded RFC822 addresses. -// For example: @[ "DINH Viêt Hoà <hoa@etpan.org>" ] -+ (NSArray *) addressesWithNonEncodedRFC822String:(NSString *)string; +// Returns the non-MIME-encoded RFC822 of the addresses. +- (NSString *) mco_nonEncodedRFC822StringForAddresses; @end diff --git a/src/objc/abstract/MCOAddress.mm b/src/objc/abstract/MCOAddress.mm index 6676e1a2..7a398421 100644 --- a/src/objc/abstract/MCOAddress.mm +++ b/src/objc/abstract/MCOAddress.mm @@ -83,6 +83,17 @@ return result; } ++ (NSArray *) addressesWithRFC822String:(NSString *)string +{ + return [NSArray mco_arrayWithMCArray:mailcore::Address::addressesWithRFC822String(string.mco_mcString)]; +} + ++ (NSArray *) addressesWithNonEncodedRFC822String:(NSString *)string +{ + return [NSArray mco_arrayWithMCArray:mailcore::Address::addressesWithNonEncodedRFC822String(string.mco_mcString)]; +} + + - (id) init { self = [super init]; @@ -136,16 +147,16 @@ MCO_OBJC_SYNTHESIZE_STRING(setMailbox, mailbox) @end -@implementation MCOAddress (MCONSArray) +@implementation NSArray (MCONSArray) -+ (NSArray *) addressesWithRFC822String:(NSString *)string +- (NSString *) mco_RFC822StringForAddresses { - return [NSArray mco_arrayWithMCArray:mailcore::Address::addressesWithRFC822String(string.mco_mcString)]; + return [NSString mco_stringWithMCString:mailcore::Address::RFC822StringForAddresses([self mco_mcArray])]; } -+ (NSArray *) addressesWithNonEncodedRFC822String:(NSString *)string -{ - return [NSArray mco_arrayWithMCArray:mailcore::Address::addressesWithNonEncodedRFC822String(string.mco_mcString)]; +- (NSString *) mco_nonEncodedRFC822StringForAddresses +{ + return [NSString mco_stringWithMCString:mailcore::Address::nonEncodedRFC822StringForAddresses([self mco_mcArray ])]; } @end diff --git a/src/objc/rfc822/MCOAttachment.h b/src/objc/rfc822/MCOAttachment.h index 7c6a0d7b..584bdece 100644 --- a/src/objc/rfc822/MCOAttachment.h +++ b/src/objc/rfc822/MCOAttachment.h @@ -34,6 +34,9 @@ // Decoded data of the part. @property (nonatomic, strong) NSData * data; + +// Returns string representation according to charset +- (NSString *) decodedString; @end diff --git a/src/objc/rfc822/MCOAttachment.mm b/src/objc/rfc822/MCOAttachment.mm index 55430f78..423ac0df 100644 --- a/src/objc/rfc822/MCOAttachment.mm +++ b/src/objc/rfc822/MCOAttachment.mm @@ -86,4 +86,10 @@ MCO_OBJC_SYNTHESIZE_DATA(setData, data) +- (NSString *) decodedString +{ + mailcore::String *result = MCO_NATIVE_INSTANCE->decodedString(); + return [NSString mco_stringWithMCString:result]; +} + @end diff --git a/src/objc/rfc822/MCOMessageBuilder.mm b/src/objc/rfc822/MCOMessageBuilder.mm index 5537b895..2cb26448 100644 --- a/src/objc/rfc822/MCOMessageBuilder.mm +++ b/src/objc/rfc822/MCOMessageBuilder.mm @@ -23,6 +23,14 @@ MCORegisterClass(self, &typeid(nativeType)); } +- (id)init +{ + mailcore::MessageBuilder * message = new mailcore::MessageBuilder(); + self = [super initWithMCMessage:message]; + MC_SAFE_RELEASE(message); + return self; +} + - (id) copyWithZone:(NSZone *)zone { nativeType * nativeObject = (nativeType *) [self mco_mcObject]->copy(); diff --git a/src/objc/utils/NSArray+MCO.mm b/src/objc/utils/NSArray+MCO.mm index 0b8b21bf..022960f0 100644 --- a/src/objc/utils/NSArray+MCO.mm +++ b/src/objc/utils/NSArray+MCO.mm @@ -32,7 +32,7 @@ { mailcore::Array * result = mailcore::Array::array(); for(NSObject * value in self) { - [value mco_mcObject]; + result->addObject([value mco_mcObject]); } return result; } diff --git a/src/objc/utils/NSString+MCO.h b/src/objc/utils/NSString+MCO.h index b459a846..8e6bbf6b 100644 --- a/src/objc/utils/NSString+MCO.h +++ b/src/objc/utils/NSString+MCO.h @@ -28,6 +28,13 @@ namespace mailcore { - (mailcore::String *) mco_mcString; #endif +- (NSString *) mco_flattenHTML; +- (NSString *) mco_flattenHTMLAndShowBlockquote:(BOOL)showBlockquote; +- (NSString *) mco_flattenHTMLAndShowBlockquote:(BOOL)showBlockquote showLink:(BOOL)showLink; + +- (NSString *) mco_htmlEncodedString; +- (NSString *) mco_cleanedHTMLString; + @end #endif diff --git a/src/objc/utils/NSString+MCO.mm b/src/objc/utils/NSString+MCO.mm index 3b8253ce..e9933fab 100644 --- a/src/objc/utils/NSString+MCO.mm +++ b/src/objc/utils/NSString+MCO.mm @@ -39,4 +39,31 @@ return mailcore::String::stringWithCharacters(characters, (unsigned int) [self length]); } +- (NSString *) mco_flattenHTML +{ + return [NSString mco_stringWithMCString:[self mco_mcString]->flattenHTML()]; +} + +- (NSString *) mco_flattenHTMLAndShowBlockquote:(BOOL)showBlockquote +{ + return [NSString mco_stringWithMCString:[self mco_mcString]->flattenHTMLAndShowBlockquote(showBlockquote)]; +} + +- (NSString *) mco_flattenHTMLAndShowBlockquote:(BOOL)showBlockquote showLink:(BOOL)showLink +{ + return [NSString mco_stringWithMCString:[self mco_mcString]->flattenHTMLAndShowBlockquoteAndLink(showBlockquote, showLink)]; +} + + +- (NSString *) mco_htmlEncodedString +{ + return [NSString mco_stringWithMCString:[self mco_mcString]->htmlEncodedString()]; +} + +- (NSString *) mco_cleanedHTMLString +{ + return [NSString mco_stringWithMCString:[self mco_mcString]->cleanedHTMLString()]; +} + + @end |