diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/abstract/MCAbstractMultipart.cc | 3 | ||||
-rw-r--r-- | src/core/abstract/MCAbstractPart.cc | 7 | ||||
-rw-r--r-- | src/core/abstract/MCMessageConstants.h | 1 | ||||
-rw-r--r-- | src/core/basetypes/MCString.cc | 16 | ||||
-rw-r--r-- | src/core/basetypes/MCUtils.h | 2 | ||||
-rw-r--r-- | src/core/imap/MCIMAPMessage.cc | 1 | ||||
-rw-r--r-- | src/core/renderer/MCHTMLRenderer.cc | 21 | ||||
-rw-r--r-- | src/core/rfc822/MCAttachment.cc | 81 | ||||
-rw-r--r-- | src/core/rfc822/MCAttachment.h | 8 | ||||
-rw-r--r-- | src/core/rfc822/MCMessageBuilder.cc | 81 |
10 files changed, 194 insertions, 27 deletions
diff --git a/src/core/abstract/MCAbstractMultipart.cc b/src/core/abstract/MCAbstractMultipart.cc index e3a2f9f7..d46a0c75 100644 --- a/src/core/abstract/MCAbstractMultipart.cc +++ b/src/core/abstract/MCAbstractMultipart.cc @@ -57,6 +57,9 @@ String * AbstractMultipart::description() case PartTypeMultipartAlternative: partTypeName = "alternative"; break; + case PartTypeMultipartSigned: + partTypeName = "signed"; + break; } result->appendUTF8Format("<%s:%p %s %s>", diff --git a/src/core/abstract/MCAbstractPart.cc b/src/core/abstract/MCAbstractPart.cc index 08cd83e3..50f12249 100644 --- a/src/core/abstract/MCAbstractPart.cc +++ b/src/core/abstract/MCAbstractPart.cc @@ -294,6 +294,7 @@ void AbstractPart::applyUniquePartID() case PartTypeMultipartMixed: case PartTypeMultipartRelated: case PartTypeMultipartAlternative: + case PartTypeMultipartSigned: queue->addObjectsFromArray(((AbstractMultipart *) part)->parts()); break; } @@ -348,6 +349,9 @@ HashMap * AbstractPart::serializable() case PartTypeMultipartAlternative: partTypeStr = MCSTR("multipart/alternative"); break; + case PartTypeMultipartSigned: + partTypeStr = MCSTR("multipart/signed"); + break; } result->setObjectForKey(MCSTR("partType"), partTypeStr); @@ -386,5 +390,8 @@ void AbstractPart::importSerializable(HashMap * serializable) else if (value->isEqual(MCSTR("multipart/alternative"))) { setPartType(PartTypeMultipartAlternative); } + else if (value->isEqual(MCSTR("multipart/signed"))) { + setPartType(PartTypeMultipartSigned); + } } } diff --git a/src/core/abstract/MCMessageConstants.h b/src/core/abstract/MCMessageConstants.h index 42d7c332..222ca322 100644 --- a/src/core/abstract/MCMessageConstants.h +++ b/src/core/abstract/MCMessageConstants.h @@ -255,6 +255,7 @@ namespace mailcore { PartTypeMultipartMixed, PartTypeMultipartRelated, PartTypeMultipartAlternative, + PartTypeMultipartSigned, }; // Private type - It should not be used directly. diff --git a/src/core/basetypes/MCString.cc b/src/core/basetypes/MCString.cc index 64ec81cc..5c2da323 100644 --- a/src/core/basetypes/MCString.cc +++ b/src/core/basetypes/MCString.cc @@ -761,6 +761,9 @@ String * String::string() String * String::stringWithData(Data * data, const char * charset) { + if (data == NULL) { + return String::string(); + } String * result = NULL; result = new String(data->bytes(), data->length(), charset); result->autorelease(); @@ -807,6 +810,9 @@ String * String::stringWithCharacters(const UChar * characters, unsigned int len void String::appendCharactersLength(const UChar * unicodeCharacters, unsigned int length) { + if (unicodeCharacters == NULL) { + return; + } allocate(mLength + length); u_strncpy(&mUnicodeChars[mLength], unicodeCharacters, length); mLength += length; @@ -815,6 +821,9 @@ void String::appendCharactersLength(const UChar * unicodeCharacters, unsigned in void String::appendString(String * otherString) { + if (otherString == NULL) { + return; + } appendCharactersLength(otherString->unicodeCharacters(), otherString->length()); } @@ -831,8 +840,9 @@ void String::appendUTF8Format(const char * format, ...) void String::appendUTF8CharactersLength(const char * UTF8Characters, unsigned int length) { - if (UTF8Characters == NULL) + if (UTF8Characters == NULL) { return; + } UChar * dest; int32_t destLength; @@ -1124,6 +1134,10 @@ String * String::uppercaseString() void String::appendBytes(const char * bytes, unsigned int length, const char * charset) { + if (bytes == NULL) { + return; + } + #if __APPLE__ CFStringEncoding encoding; if (strcasecmp(charset, "mutf-7") == 0) { diff --git a/src/core/basetypes/MCUtils.h b/src/core/basetypes/MCUtils.h index e1bef841..ad9c4db5 100644 --- a/src/core/basetypes/MCUtils.h +++ b/src/core/basetypes/MCUtils.h @@ -29,7 +29,7 @@ #define MCSTR(str) mailcore::String::uniquedStringWithUTF8Characters("" str "") -#define MCUTF8(str) ((str) != NULL ? (str)->UTF8Characters() : NULL ) +#define MCUTF8(str) MCUTF8DESC(str) #define MCUTF8DESC(obj) ((obj) != NULL ? (obj)->description()->UTF8Characters() : NULL ) #define MCLOCALIZEDSTRING(key) key diff --git a/src/core/imap/MCIMAPMessage.cc b/src/core/imap/MCIMAPMessage.cc index dfb26752..6cb1472c 100644 --- a/src/core/imap/MCIMAPMessage.cc +++ b/src/core/imap/MCIMAPMessage.cc @@ -185,6 +185,7 @@ static AbstractPart * partForPartIDInPart(AbstractPart * part, String * partID) case mailcore::PartTypeMultipartMixed: case mailcore::PartTypeMultipartRelated: case mailcore::PartTypeMultipartAlternative: + case mailcore::PartTypeMultipartSigned: if (partID->isEqual(((IMAPMultipart *) part)->partID())) { return part; } diff --git a/src/core/renderer/MCHTMLRenderer.cc b/src/core/renderer/MCHTMLRenderer.cc index bbc0d591..8b561e71 100644 --- a/src/core/renderer/MCHTMLRenderer.cc +++ b/src/core/renderer/MCHTMLRenderer.cc @@ -147,6 +147,7 @@ static bool partContainsMimeType(AbstractPart * part, String * mimeType) case PartTypeMultipartMixed: case PartTypeMultipartRelated: case PartTypeMultipartAlternative: + case PartTypeMultipartSigned: return multipartContainsMimeType((AbstractMultipart *) part, mimeType); default: return false; @@ -254,6 +255,8 @@ static String * htmlForAbstractPart(AbstractPart * part, htmlRendererContext * c return htmlForAbstractMultipartRelated((AbstractMultipart *) part, context); case PartTypeMultipartAlternative: return htmlForAbstractMultipartAlternative((AbstractMultipart *) part, context); + case PartTypeMultipartSigned: + return htmlForAbstractMultipartMixed((AbstractMultipart *) part, context); default: MCAssert(0); } @@ -404,8 +407,22 @@ String * htmlForAbstractMultipartAlternative(AbstractMultipart * part, htmlRende AbstractPart * preferredAlternative = preferredPartInMultipartAlternative(part); if (preferredAlternative == NULL) return MCSTR(""); - - return htmlForAbstractPart(preferredAlternative, context); + + // Exchange sends calendar invitation as alternative part. We need to extract it. + AbstractPart * calendar = NULL; + for(unsigned int i = 0 ; i < part->parts()->count() ; i ++) { + AbstractPart * subpart = (AbstractPart *) part->parts()->objectAtIndex(i); + if (partContainsMimeType(subpart, MCSTR("text/calendar"))) { + calendar = subpart; + } + } + + String * result = String::string(); + result->appendString(htmlForAbstractPart(preferredAlternative, context)); + if (calendar != NULL) { + result->appendString(htmlForAbstractPart(calendar, context)); + } + return result; } static String * htmlForAbstractMultipartMixed(AbstractMultipart * part, htmlRendererContext * context) diff --git a/src/core/rfc822/MCAttachment.cc b/src/core/rfc822/MCAttachment.cc index 331d7d28..172881cb 100644 --- a/src/core/rfc822/MCAttachment.cc +++ b/src/core/rfc822/MCAttachment.cc @@ -211,6 +211,8 @@ Attachment * Attachment::attachmentWithText(String * text) void Attachment::init() { mData = NULL; + mContentTypeParameters = NULL; + mlcContentTypeParameters = NULL; setMimeType(MCSTR("application/octet-stream")); } @@ -223,11 +225,14 @@ Attachment::Attachment(Attachment * other) : AbstractPart(other) { init(); MC_SAFE_REPLACE_RETAIN(Data, mData, other->mData); + setContentTypeParameters(other->mContentTypeParameters); } Attachment::~Attachment() { MC_SAFE_RELEASE(mData); + MC_SAFE_RELEASE(mContentTypeParameters); + MC_SAFE_RELEASE(mlcContentTypeParameters); } String * Attachment::description() @@ -256,6 +261,11 @@ String * Attachment::description() else { result->appendUTF8Format("no data\n"); } + if (mContentTypeParameters != NULL) { + mc_foreachhashmapKeyAndValue(String, key, String, value, mContentTypeParameters) { + result->appendUTF8Format("%s: %s\n", key->UTF8Characters(), value->UTF8Characters()); + } + } result->appendUTF8Format(">"); return result; @@ -286,6 +296,55 @@ String * Attachment::decodedString() } } +void Attachment::setContentTypeParameters(HashMap * parameters) +{ + MC_SAFE_REPLACE_COPY(HashMap, mContentTypeParameters, parameters); + MC_SAFE_RELEASE(mlcContentTypeParameters); + if (mContentTypeParameters != NULL) { + mlcContentTypeParameters = new HashMap(); + mc_foreachhashmapKeyAndValue(String, key, String, value, mContentTypeParameters) { + mlcContentTypeParameters->setObjectForKey(key->lowercaseString(), value); + } + } +} + +Array * Attachment::allContentTypeParametersNames() +{ + if (mContentTypeParameters == NULL) + return Array::array(); + return mContentTypeParameters->allKeys(); +} + +void Attachment::setContentTypeParameter(String * name, String * object) +{ + if (mContentTypeParameters == NULL) { + mContentTypeParameters = new HashMap(); + } + if (mlcContentTypeParameters == NULL) { + mlcContentTypeParameters = new HashMap(); + } + if (object == NULL) { + removeContentTypeParameter(name); + return; + } + mContentTypeParameters->setObjectForKey(name, object); + mlcContentTypeParameters->setObjectForKey(name->lowercaseString(), object); +} + +void Attachment::removeContentTypeParameter(String * name) +{ + if (mContentTypeParameters == NULL) + return; + mContentTypeParameters->removeObjectForKey(name); + mlcContentTypeParameters->removeObjectForKey(name); +} + +String * Attachment::contentTypeParameterValueForName(String * name) +{ + if (mlcContentTypeParameters == NULL) + return NULL; + return (String *) mlcContentTypeParameters->objectForKey(name->lowercaseString()); +} AbstractPart * Attachment::attachmentsWithMIME(struct mailmime * mime) { @@ -341,6 +400,14 @@ AbstractPart * Attachment::attachmentsWithMIMEWithMain(struct mailmime * mime, b fillMultipartSubAttachments(attachment, mime); return (Multipart *) attachment->autorelease(); } + else if ((mime->mm_content_type != NULL) && (mime->mm_content_type->ct_subtype != NULL) && + (strcasecmp(mime->mm_content_type->ct_subtype, "signed") == 0)) { + Multipart * attachment; + attachment = new Multipart(); + attachment->setPartType(PartTypeMultipartSigned); + fillMultipartSubAttachments(attachment, mime); + return (Multipart *) attachment->autorelease(); + } else { Multipart * attachment; attachment = new Multipart(); @@ -495,6 +562,7 @@ Attachment * Attachment::attachmentWithSingleMIME(struct mailmime * mime) char * description; char * loc; Encoding encoding; + clist * ct_parameters; MCAssert(mime->mm_type == MAILMIME_SINGLE); @@ -523,6 +591,7 @@ Attachment * Attachment::attachmentWithSingleMIME(struct mailmime * mime) content_id = single_fields.fld_id; description = single_fields.fld_description; loc = single_fields.fld_location; + ct_parameters = single_fields.fld_content->ct_parameters; if (filename != NULL) { result->setFilename(String::stringByDecodingMIMEHeaderValue(filename)); @@ -543,6 +612,18 @@ Attachment * Attachment::attachmentWithSingleMIME(struct mailmime * mime) result->setContentLocation(String::stringWithUTF8Characters(loc)); } + if (ct_parameters != NULL) { + clistiter * iter = clist_begin(ct_parameters); + struct mailmime_parameter * param; + while (iter != NULL) { + param = (struct mailmime_parameter *) clist_content(iter); + if (param != NULL) { + result->setContentTypeParameter(String::stringWithUTF8Characters(param->pa_name), String::stringWithUTF8Characters(param->pa_value)); + } + iter = clist_next(iter); + } + } + if (single_fields.fld_disposition != NULL) { if (single_fields.fld_disposition->dsp_type != NULL) { if (single_fields.fld_disposition->dsp_type->dsp_type == MAILMIME_DISPOSITION_TYPE_INLINE) { diff --git a/src/core/rfc822/MCAttachment.h b/src/core/rfc822/MCAttachment.h index 7dd15b89..069688f2 100644 --- a/src/core/rfc822/MCAttachment.h +++ b/src/core/rfc822/MCAttachment.h @@ -29,6 +29,11 @@ namespace mailcore { virtual Data * data(); virtual String * decodedString(); + virtual void setContentTypeParameter(String * name, String * value); + virtual void removeContentTypeParameter(String * name); + virtual String * contentTypeParameterValueForName(String *name); + virtual Array * allContentTypeParametersNames(); + public: // subclass behavior Attachment(Attachment * other); virtual String * description(); @@ -39,6 +44,8 @@ namespace mailcore { private: Data * mData; + HashMap * mContentTypeParameters; + HashMap * mlcContentTypeParameters; void init(); static void fillMultipartSubAttachments(AbstractMultipart * multipart, struct mailmime * mime); static AbstractPart * attachmentsWithMIMEWithMain(struct mailmime * mime, bool isMain); @@ -46,6 +53,7 @@ namespace mailcore { static MessagePart * attachmentWithMessageMIME(struct mailmime * mime); static Encoding encodingForMIMEEncoding(struct mailmime_mechanism * mechanism, int defaultMimeEncoding); static HashMap * readMimeTypesFile(String * filename); + void setContentTypeParameters(HashMap * parameters); }; } diff --git a/src/core/rfc822/MCMessageBuilder.cc b/src/core/rfc822/MCMessageBuilder.cc index cd87009e..3e63ce4a 100644 --- a/src/core/rfc822/MCMessageBuilder.cc +++ b/src/core/rfc822/MCMessageBuilder.cc @@ -134,7 +134,7 @@ err: static struct mailmime * get_text_part(const char * mime_type, const char * charset, const char * content_id, const char * description, - const char * text, size_t length, int encoding_type) + const char * text, size_t length, int encoding_type, clist * contentTypeParameters) { struct mailmime_fields * mime_fields; struct mailmime * mime; @@ -165,6 +165,10 @@ static struct mailmime * get_text_part(const char * mime_type, const char * char param = mailmime_param_new_with_data((char *) "charset", (char *) charset); } clist_append(content->ct_parameters, param); + if (contentTypeParameters != NULL) { + clist_concat(content->ct_parameters, contentTypeParameters); + } + mime = part_new_empty(content, mime_fields, NULL, 1); mailmime_set_body_text(mime, (char *) text, length); @@ -173,7 +177,7 @@ static struct mailmime * get_text_part(const char * mime_type, const char * char static struct mailmime * get_plain_text_part(const char * mime_type, const char * charset, const char * content_id, const char * description, - const char * text, size_t length) + const char * text, size_t length, clist * contentTypeParameters) { bool needsQuotedPrintable; int mechanism; @@ -189,20 +193,20 @@ static struct mailmime * get_plain_text_part(const char * mime_type, const char if (needsQuotedPrintable) { mechanism = MAILMIME_MECHANISM_QUOTED_PRINTABLE; } - return get_text_part(mime_type, charset, content_id, description, text, length, mechanism); + return get_text_part(mime_type, charset, content_id, description, text, length, mechanism, contentTypeParameters); } static struct mailmime * get_other_text_part(const char * mime_type, const char * charset, const char * content_id, const char * description, - const char * text, size_t length) + const char * text, size_t length, clist * contentTypeParameters) { - return get_text_part(mime_type, charset, content_id, description, text, length, MAILMIME_MECHANISM_QUOTED_PRINTABLE); + return get_text_part(mime_type, charset, content_id, description, text, length, MAILMIME_MECHANISM_QUOTED_PRINTABLE, contentTypeParameters); } static struct mailmime * get_file_part(const char * filename, const char * mime_type, int is_inline, const char * content_id, const char * content_description, - const char * text, size_t length) + const char * text, size_t length, clist * contentTypeParameters) { char * disposition_name; int encoding_type; @@ -238,6 +242,11 @@ static struct mailmime * get_file_part(const char * filename, const char * mime_ dup_content_description = strdup(content_description); mime_fields = mailmime_fields_new_with_data(encoding, dup_content_id, dup_content_description, disposition, NULL); + + if (contentTypeParameters != NULL) { + clist_concat(content->ct_parameters, contentTypeParameters); + } + mime = part_new_empty(content, mime_fields, NULL, 1); mailmime_set_body_text(mime, (char *) text, length); @@ -246,6 +255,23 @@ static struct mailmime * get_file_part(const char * filename, const char * mime_ #define MIME_ENCODED_STR(str) (str != NULL ? str->encodedMIMEHeaderValue()->bytes() : NULL) +static clist * content_type_parameters_from_attachment(Attachment * att) +{ + clist * contentTypeParameters = NULL; + struct mailmime_parameter * param; + + mc_foreacharray(String, name, att->allContentTypeParametersNames()) { + if (contentTypeParameters == NULL) { + contentTypeParameters = clist_new(); + } + String * value = att->contentTypeParameterValueForName(name); + param = mailmime_param_new_with_data((char *)name->UTF8Characters(), (char *)value->UTF8Characters()); + clist_append(contentTypeParameters, param); + } + + return contentTypeParameters; +} + static struct mailmime * mime_from_attachment(Attachment * att) { struct mailmime * mime; @@ -262,24 +288,33 @@ static struct mailmime * mime_from_attachment(Attachment * att) if (r != MAILIMF_NO_ERROR) return NULL; } - else if (att->isInlineAttachment() && att->mimeType()->lowercaseString()->isEqual(MCSTR("text/plain"))) { - mime = get_plain_text_part(MCUTF8(att->mimeType()), MCUTF8(att->charset()), - MCUTF8(att->contentID()), - MIME_ENCODED_STR(att->contentDescription()), - data->bytes(), data->length()); - } - else if (att->isInlineAttachment() && att->mimeType()->lowercaseString()->hasPrefix(MCSTR("text/"))) { - mime = get_other_text_part(MCUTF8(att->mimeType()), MCUTF8(att->charset()), - MCUTF8(att->contentID()), - MIME_ENCODED_STR(att->contentDescription()), - data->bytes(), data->length()); - } else { - mime = get_file_part(MIME_ENCODED_STR(att->filename()), - MCUTF8(att->mimeType()), att->isInlineAttachment(), - MCUTF8(att->contentID()), - MIME_ENCODED_STR(att->contentDescription()), - data->bytes(), data->length()); + clist * contentTypeParameters = content_type_parameters_from_attachment(att); + if (att->isInlineAttachment() && att->mimeType()->lowercaseString()->isEqual(MCSTR("text/plain"))) { + mime = get_plain_text_part(MCUTF8(att->mimeType()), MCUTF8(att->charset()), + MCUTF8(att->contentID()), + MIME_ENCODED_STR(att->contentDescription()), + data->bytes(), data->length(), + contentTypeParameters); + } + else if (att->isInlineAttachment() && att->mimeType()->lowercaseString()->hasPrefix(MCSTR("text/"))) { + mime = get_other_text_part(MCUTF8(att->mimeType()), MCUTF8(att->charset()), + MCUTF8(att->contentID()), + MIME_ENCODED_STR(att->contentDescription()), + data->bytes(), data->length(), + contentTypeParameters); + } + else { + mime = get_file_part(MIME_ENCODED_STR(att->filename()), + MCUTF8(att->mimeType()), att->isInlineAttachment(), + MCUTF8(att->contentID()), + MIME_ENCODED_STR(att->contentDescription()), + data->bytes(), data->length(), + contentTypeParameters); + } + if (contentTypeParameters != NULL) { + clist_free(contentTypeParameters); + } } return mime; } |