aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/abstract/MCAbstractMultipart.cc3
-rw-r--r--src/core/abstract/MCAbstractPart.cc7
-rw-r--r--src/core/abstract/MCMessageConstants.h1
-rw-r--r--src/core/basetypes/MCString.cc16
-rw-r--r--src/core/basetypes/MCUtils.h2
-rw-r--r--src/core/imap/MCIMAPMessage.cc1
-rw-r--r--src/core/renderer/MCHTMLRenderer.cc21
-rw-r--r--src/core/rfc822/MCAttachment.cc81
-rw-r--r--src/core/rfc822/MCAttachment.h8
-rw-r--r--src/core/rfc822/MCMessageBuilder.cc81
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;
}