#include "MCWin32.h" // should be first include. #include "MCMessageHeader.h" #include "MCDefines.h" #include "MCAddress.h" #include "MCIterator.h" #include "MCLibetpan.h" #include "MCLock.h" #include #ifndef _MSC_VER #include #endif #include using namespace mailcore; static struct mailimf_address_list * lep_address_list_from_array(Array * addresses); static struct mailimf_mailbox_list * lep_mailbox_list_from_array(Array * addresses); static Array * lep_address_list_from_lep_addr(struct mailimf_address_list * addr_list); static Array * lep_address_list_from_lep_mailbox(struct mailimf_mailbox_list * mb_list); static Array * msg_id_to_string_array(clist * msgids); static clist * msg_id_from_string_array(Array * msgids); #define MAX_HOSTNAME 512 MessageHeader::MessageHeader() { init(true, true); } MessageHeader::MessageHeader(MessageHeader * other) { init(false, other->mMessageID == NULL); if (other->mMessageID != NULL) { setMessageID(other->mMessageID); mMessageIDAutoGenerated = other->isMessageIDAutoGenerated(); } setReferences(other->mReferences); setInReplyTo(other->mInReplyTo); setSender(other->mSender); setFrom(other->mFrom); setTo(other->mTo); setCc(other->mCc); setBcc(other->mBcc); setReplyTo(other->mReplyTo); setSubject(other->mSubject); setDate(other->date()); setReceivedDate(other->receivedDate()); setExtraHeaders(other->mExtraHeaders); } void MessageHeader::init(bool generateDate, bool generateMessageID) { mMessageID = NULL; mMessageIDAutoGenerated = false; mReferences = NULL; mInReplyTo = NULL; mSender = NULL; mFrom = NULL; mTo = NULL; mCc = NULL; mBcc = NULL; mReplyTo = NULL; mSubject = NULL; mDate = (time_t) -1; mReceivedDate = (time_t) -1; mExtraHeaders = NULL; if (generateDate) { time_t date; date = time(NULL); setDate(date); setReceivedDate(date); } if (generateMessageID) { static String * hostname = NULL; static MC_LOCK_TYPE lock = MC_LOCK_INITIAL_VALUE; MC_LOCK(&lock); if (hostname == NULL) { char name[MAX_HOSTNAME]; int r; r = gethostname(name, MAX_HOSTNAME); if (r < 0) { hostname = NULL; } else { hostname = new String(name); } if (hostname == NULL) { hostname = new String("localhost"); } } MC_UNLOCK(&lock); String * messageID = new String(); messageID->appendString(String::uuidString()); messageID->appendUTF8Characters("@"); messageID->appendString(hostname); setMessageID(messageID); messageID->release(); mMessageIDAutoGenerated = true; } } MessageHeader::~MessageHeader() { MC_SAFE_RELEASE(mMessageID); MC_SAFE_RELEASE(mReferences); MC_SAFE_RELEASE(mInReplyTo); MC_SAFE_RELEASE(mSender); MC_SAFE_RELEASE(mFrom); MC_SAFE_RELEASE(mTo); MC_SAFE_RELEASE(mCc); MC_SAFE_RELEASE(mBcc); MC_SAFE_RELEASE(mReplyTo); MC_SAFE_RELEASE(mSubject); MC_SAFE_RELEASE(mExtraHeaders); } String * MessageHeader::description() { String * result = String::string(); result->appendUTF8Format("<%s:%p\n", className()->UTF8Characters(), this); if (mMessageID != NULL) { result->appendUTF8Format("Message-ID: %s\n", mMessageID->UTF8Characters()); } if (mReferences != NULL) { result->appendUTF8Format("References: %s\n", mReferences->description()->UTF8Characters()); } if (mInReplyTo != NULL) { result->appendUTF8Format("In-Reply-To: %s\n", mInReplyTo->description()->UTF8Characters()); } if (mSender != NULL) { result->appendUTF8Format("Sender: %s\n", mSender->description()->UTF8Characters()); } if (mFrom != NULL) { result->appendUTF8Format("From: %s\n", mFrom->description()->UTF8Characters()); } if (mTo != NULL) { result->appendUTF8Format("To: %s\n", mTo->description()->UTF8Characters()); } if (mCc != NULL) { result->appendUTF8Format("Cc: %s\n", mCc->description()->UTF8Characters()); } if (mBcc != NULL) { result->appendUTF8Format("Bcc: %s\n", mBcc->description()->UTF8Characters()); } if (mReplyTo != NULL) { result->appendUTF8Format("Reply-To: %s\n", mReplyTo->description()->UTF8Characters()); } if (mSubject != NULL) { result->appendUTF8Format("Subject: %s\n", mSubject->UTF8Characters()); } if (mExtraHeaders != NULL) { mc_foreachhashmapKeyAndValue(String, header, String, value, mExtraHeaders) { result->appendUTF8Format("%s: %s\n", header->UTF8Characters(), value->UTF8Characters()); } } result->appendUTF8Format(">"); return result; } Object * MessageHeader::copy() { return new MessageHeader(this); } void MessageHeader::setMessageID(String * messageID) { MC_SAFE_REPLACE_COPY(String, mMessageID, messageID); mMessageIDAutoGenerated = false; } String * MessageHeader::messageID() { return mMessageID; } bool MessageHeader::isMessageIDAutoGenerated() { return mMessageIDAutoGenerated; } void MessageHeader::setReferences(Array * references) { MC_SAFE_REPLACE_COPY(Array, mReferences, references); } Array * MessageHeader::references() { return mReferences; } void MessageHeader::setInReplyTo(Array * inReplyTo) { MC_SAFE_REPLACE_COPY(Array, mInReplyTo, inReplyTo); } Array * MessageHeader::inReplyTo() { return mInReplyTo; } void MessageHeader::setDate(time_t date) { mDate = date; } time_t MessageHeader::date() { return mDate; } void MessageHeader::setReceivedDate(time_t date) { mReceivedDate = date; } time_t MessageHeader::receivedDate() { return mReceivedDate; } void MessageHeader::setSender(Address * sender) { MC_SAFE_REPLACE_RETAIN(Address, mSender, sender); } Address * MessageHeader::sender() { return mSender; } void MessageHeader::setFrom(Address * from) { MC_SAFE_REPLACE_RETAIN(Address, mFrom, from); } Address * MessageHeader::from() { return mFrom; } void MessageHeader::setTo(Array * to) { MC_SAFE_REPLACE_COPY(Array, mTo, to); } Array * MessageHeader::to() { return mTo; } void MessageHeader::setCc(Array * cc) { MC_SAFE_REPLACE_COPY(Array, mCc, cc); } Array * MessageHeader::cc() { return mCc; } void MessageHeader::setBcc(Array * bcc) { MC_SAFE_REPLACE_COPY(Array, mBcc, bcc); } Array * MessageHeader::bcc() { return mBcc; } void MessageHeader::setReplyTo(Array * replyTo) { MC_SAFE_REPLACE_COPY(Array, mReplyTo, replyTo); } Array * MessageHeader::replyTo() { return mReplyTo; } void MessageHeader::setSubject(String * subject) { MC_SAFE_REPLACE_COPY(String, mSubject, subject); } String * MessageHeader::subject() { return mSubject; } void MessageHeader::setUserAgent(String * userAgent) { setExtraHeader(MCSTR("X-Mailer"), userAgent); } String * MessageHeader::userAgent() { return extraHeaderValueForName(MCSTR("X-Mailer")); } void MessageHeader::setExtraHeaders(HashMap * headers) { MC_SAFE_REPLACE_COPY(HashMap, mExtraHeaders, headers); } Array * MessageHeader::allExtraHeadersNames() { if (mExtraHeaders == NULL) return Array::array(); return mExtraHeaders->allKeys(); } void MessageHeader::setExtraHeader(String * name, String * object) { if (mExtraHeaders == NULL) { mExtraHeaders = new HashMap(); } removeExtraHeader(name); if (object == NULL) { return; } mExtraHeaders->setObjectForKey(name, object); } void MessageHeader::removeExtraHeader(String * name) { if (mExtraHeaders == NULL) return; mc_foreachhashmapKey(String, key, mExtraHeaders) { if (key->isEqualCaseInsensitive(name)) { mExtraHeaders->removeObjectForKey(key); break; } } } String * MessageHeader::extraHeaderValueForName(String * name) { String * result = NULL; mc_foreachhashmapKey(String, key, mExtraHeaders) { if (key->isEqualCaseInsensitive(name)) { result = (String *) mExtraHeaders->objectForKey(key); } } return result; } String * MessageHeader::extractedSubject() { if (subject() == NULL) return NULL; return subject()->extractedSubject(); } String * MessageHeader::partialExtractedSubject() { if (subject() == NULL) return NULL; return subject()->extractedSubjectAndKeepBracket(true); } void MessageHeader::importHeadersData(Data * data) { size_t cur_token; struct mailimf_fields * fields; int r; cur_token = 0; r = mailimf_envelope_and_optional_fields_parse(data->bytes(), data->length(), &cur_token, &fields); if (r != MAILIMF_NO_ERROR) { return; } importIMFFields(fields); mailimf_fields_free(fields); } void MessageHeader::importIMFFields(struct mailimf_fields * fields) { struct mailimf_single_fields single_fields; mailimf_single_fields_init(&single_fields, fields); /* date */ if (single_fields.fld_orig_date != NULL) { time_t timestamp; timestamp = timestampFromDate(single_fields.fld_orig_date->dt_date_time); setDate(timestamp); setReceivedDate(timestamp); //MCLog("%lu %lu", (unsigned long) timestamp, date()); } /* subject */ if (single_fields.fld_subject != NULL) { char * subject; subject = single_fields.fld_subject->sbj_value; setSubject(String::stringByDecodingMIMEHeaderValue(subject)); } /* sender */ if (single_fields.fld_sender != NULL) { struct mailimf_mailbox * mb; Address * address; mb = single_fields.fld_sender->snd_mb; if (mb != NULL) { address = Address::addressWithIMFMailbox(mb); setSender(address); } } /* from */ if (single_fields.fld_from != NULL) { struct mailimf_mailbox_list * mb_list; Array * addresses; mb_list = single_fields.fld_from->frm_mb_list; addresses = lep_address_list_from_lep_mailbox(mb_list); if (addresses->count() > 0) { setFrom((Address *) (addresses->objectAtIndex(0))); } } /* replyto */ if (single_fields.fld_reply_to != NULL) { struct mailimf_address_list * addr_list; Array * addresses; addr_list = single_fields.fld_reply_to->rt_addr_list; addresses = lep_address_list_from_lep_addr(addr_list); setReplyTo(addresses); } /* to */ if (single_fields.fld_to != NULL) { struct mailimf_address_list * addr_list; Array * addresses; addr_list = single_fields.fld_to->to_addr_list; addresses = lep_address_list_from_lep_addr(addr_list); setTo(addresses); } /* cc */ if (single_fields.fld_cc != NULL) { struct mailimf_address_list * addr_list; Array * addresses; addr_list = single_fields.fld_cc->cc_addr_list; addresses = lep_address_list_from_lep_addr(addr_list); setCc(addresses); } /* bcc */ if (single_fields.fld_bcc != NULL) { struct mailimf_address_list * addr_list; Array * addresses; addr_list = single_fields.fld_bcc->bcc_addr_list; addresses = lep_address_list_from_lep_addr(addr_list); setBcc(addresses); } /* msgid */ if (single_fields.fld_message_id != NULL) { char * msgid; String * str; msgid = single_fields.fld_message_id->mid_value; str = String::stringWithUTF8Characters(msgid); setMessageID(str); } /* references */ if (single_fields.fld_references != NULL) { clist * msg_id_list; Array * msgids; msg_id_list = single_fields.fld_references->mid_list; msgids = msg_id_to_string_array(msg_id_list); setReferences(msgids); } /* inreplyto */ if (single_fields.fld_in_reply_to != NULL) { clist * msg_id_list; Array * msgids; msg_id_list = single_fields.fld_in_reply_to->mid_list; msgids = msg_id_to_string_array(msg_id_list); setInReplyTo(msgids); } // Take care of other headers. for(clistiter * cur = clist_begin(fields->fld_list) ; cur != NULL ; cur = clist_next(cur)) { struct mailimf_field * field; field = (mailimf_field *)clist_content(cur); if (field->fld_type != MAILIMF_FIELD_OPTIONAL_FIELD) { continue; } char * fieldName; String * fieldNameStr; fieldName = field->fld_data.fld_optional_field->fld_name; fieldNameStr = String::stringWithUTF8Characters(fieldName); if (fieldNameStr == NULL) { continue; } // Set only if this optional-field is not set if (extraHeaderValueForName(fieldNameStr) == NULL) { char * fieldValue; String * fieldValueStr; fieldValue = field->fld_data.fld_optional_field->fld_value; fieldValueStr = String::stringByDecodingMIMEHeaderValue(fieldValue); if (fieldValueStr != NULL) { setExtraHeader(fieldNameStr, fieldValueStr); } } } } #pragma mark RFC 2822 mailbox conversion static Array * lep_address_list_from_lep_mailbox(struct mailimf_mailbox_list * mb_list) { Array * result; clistiter * cur; result = Array::array(); for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; cur = clist_next(cur)) { struct mailimf_mailbox * mb; Address * address; mb = (struct mailimf_mailbox *) clist_content(cur); address = Address::addressWithIMFMailbox(mb); result->addObject(address); } return result; } static Array * lep_address_list_from_lep_addr(struct mailimf_address_list * addr_list) { Array * result; clistiter * cur; result = Array::array(); if (addr_list == NULL) { return result; } if (addr_list->ad_list == NULL) { return result; } for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; cur = clist_next(cur)) { struct mailimf_address * addr; addr = (struct mailimf_address *) clist_content(cur); switch (addr->ad_type) { case MAILIMF_ADDRESS_MAILBOX: { Address * address; address = Address::addressWithIMFMailbox(addr->ad_data.ad_mailbox); result->addObject(address); break; } case MAILIMF_ADDRESS_GROUP: { if (addr->ad_data.ad_group->grp_mb_list != NULL) { Array * subArray; subArray = lep_address_list_from_lep_mailbox(addr->ad_data.ad_group->grp_mb_list); result->addObjectsFromArray(subArray); } break; } } } return result; } static struct mailimf_mailbox_list * lep_mailbox_list_from_array(Array * addresses) { struct mailimf_mailbox_list * mb_list; if (addresses == NULL) return NULL; if (addresses->count() == 0) return NULL; mb_list = mailimf_mailbox_list_new_empty(); for(unsigned i = 0 ; i < addresses->count() ; i ++) { Address * address = (Address *) addresses->objectAtIndex(i); struct mailimf_mailbox * mailbox = address->createIMFMailbox(); mailimf_mailbox_list_add(mb_list, mailbox); } return mb_list; } static struct mailimf_address_list * lep_address_list_from_array(Array * addresses) { struct mailimf_address_list * addr_list; if (addresses == NULL) return NULL; if (addresses->count() == 0) return NULL; addr_list = mailimf_address_list_new_empty(); for(unsigned i = 0 ; i < addresses->count() ; i ++) { Address * address = (Address *) addresses->objectAtIndex(i); struct mailimf_address * addr = address->createIMFAddress(); mailimf_address_list_add(addr_list, addr); } return addr_list; } #pragma mark Message-ID conversion static Array * msg_id_to_string_array(clist * msgids) { clistiter * cur; Array * result; result = Array::array(); for(cur = clist_begin(msgids) ; cur != NULL ; cur = clist_next(cur)) { char * msgid; String * str; msgid = (char *) clist_content(cur); str = String::stringWithUTF8Characters(msgid); result->addObject(str); } return result; } static clist * msg_id_from_string_array(Array * msgids) { clist * result; if (msgids == NULL) return NULL; if (msgids->count() == 0) return NULL; result = clist_new(); for(unsigned int i = 0 ; i < msgids->count() ; i ++) { String * msgid = (String *) msgids->objectAtIndex(i); clist_append(result, strdup(msgid->UTF8Characters())); } return result; } struct mailimf_fields * MessageHeader::createIMFFieldsAndFilterBcc(bool filterBcc) { struct mailimf_date_time * imfDate; char * imfMsgid; char * imfSubject; struct mailimf_mailbox_list * imfFrom; struct mailimf_address_list * imfReplyTo; struct mailimf_address_list * imfTo; struct mailimf_address_list * imfCc; struct mailimf_address_list * imfBcc; clist * imfInReplyTo; clist * imfReferences; struct mailimf_fields * fields; imfDate = NULL; if (date() != (time_t) -1) { //MCLog("%lu", date()); imfDate = dateFromTimestamp(date()); } imfFrom = NULL; if (from() != NULL) { imfFrom = lep_mailbox_list_from_array(Array::arrayWithObject(from())); } imfReplyTo = lep_address_list_from_array(replyTo()); imfTo = lep_address_list_from_array(to()); imfCc = lep_address_list_from_array(cc()); imfBcc = NULL; if (!filterBcc) { imfBcc = lep_address_list_from_array(bcc()); } imfMsgid = NULL; if (messageID() != NULL) { imfMsgid = strdup(messageID()->UTF8Characters()); } imfInReplyTo = msg_id_from_string_array(inReplyTo()); imfReferences = msg_id_from_string_array(references()); imfSubject = NULL; if ((subject() != NULL) && (subject()->length() > 0)) { Data * data; data = subject()->encodedMIMEHeaderValueForSubject(); if (data->bytes() != NULL) { imfSubject = strdup(data->bytes()); } } fields = mailimf_fields_new_with_data_all(imfDate, imfFrom, NULL /* sender */, imfReplyTo, imfTo, imfCc, imfBcc, imfMsgid, imfInReplyTo, imfReferences, imfSubject); if (mExtraHeaders != NULL) { mc_foreachhashmapKeyAndValue(String, header, String, value, mExtraHeaders) { struct mailimf_field * field; field = mailimf_field_new_custom(strdup(header->UTF8Characters()), strdup(value->UTF8Characters())); mailimf_fields_add(fields, field); } } return fields; } extern "C" { extern int mailimap_hack_date_time_parse(char * str, struct mailimap_date_time ** result, size_t progr_rate, progress_function * progr_fun); } #pragma mark IMAP mailbox conversion static Array * imap_mailbox_list_to_address_array(clist * imap_mailbox_list) { clistiter * cur; Array * result; result = Array::array(); for(cur = clist_begin(imap_mailbox_list) ; cur != NULL ; cur = clist_next(cur)) { struct mailimap_address * imap_addr; Address * address; imap_addr = (struct mailimap_address *) clist_content(cur); address = Address::addressWithIMAPAddress(imap_addr); result->addObject(address); } return result; } void MessageHeader::importIMAPEnvelope(struct mailimap_envelope * env) { if (env->env_date != NULL) { size_t cur_token; struct mailimf_date_time * date_time; int r; cur_token = 0; r = mailimf_date_time_parse(env->env_date, strlen(env->env_date), &cur_token, &date_time); if (r == MAILIMF_NO_ERROR) { time_t timestamp; // date timestamp = timestampFromDate(date_time); setDate(timestamp); setReceivedDate(timestamp); mailimf_date_time_free(date_time); } else { struct mailimap_date_time * imap_date; r = mailimap_hack_date_time_parse(env->env_date, &imap_date, 0, NULL); if (r == MAILIMAP_NO_ERROR) { time_t timestamp; timestamp = timestampFromIMAPDate(imap_date); setDate(timestamp); setReceivedDate(timestamp); mailimap_date_time_free(imap_date); } } } if (env->env_subject != NULL) { char * subject; // subject subject = env->env_subject; setSubject(String::stringByDecodingMIMEHeaderValue(subject)); } if (env->env_sender != NULL) { if (env->env_sender->snd_list != NULL) { Array * addresses; addresses = imap_mailbox_list_to_address_array(env->env_sender->snd_list); if (addresses->count() > 0) { setSender((Address *) addresses->objectAtIndex(0)); } } } if (env->env_from != NULL) { if (env->env_from->frm_list != NULL) { Array * addresses; addresses = imap_mailbox_list_to_address_array(env->env_from->frm_list); if (addresses->count() > 0) { setFrom((Address *) addresses->objectAtIndex(0)); } } } // skip Sender header if (env->env_reply_to != NULL) { if (env->env_reply_to->rt_list != NULL) { Array * addresses; addresses = imap_mailbox_list_to_address_array(env->env_reply_to->rt_list); setReplyTo(addresses); } } if (env->env_to != NULL) { if (env->env_to->to_list != NULL) { Array * addresses; addresses = imap_mailbox_list_to_address_array(env->env_to->to_list); setTo(addresses); } } if (env->env_cc != NULL) { if (env->env_cc->cc_list != NULL) { Array * addresses; addresses = imap_mailbox_list_to_address_array(env->env_cc->cc_list); setCc(addresses); } } if (env->env_bcc != NULL) { if (env->env_bcc->bcc_list != NULL) { Array * addresses; addresses = imap_mailbox_list_to_address_array(env->env_bcc->bcc_list); setBcc(addresses); } } if (env->env_in_reply_to != NULL) { size_t cur_token; clist * msg_id_list; int r; cur_token = 0; r = mailimf_msg_id_list_parse(env->env_in_reply_to, strlen(env->env_in_reply_to), &cur_token, &msg_id_list); if (r == MAILIMF_NO_ERROR) { Array * msgids; msgids = msg_id_to_string_array(msg_id_list); setInReplyTo(msgids); // in-reply-to clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL); clist_free(msg_id_list); } } if (env->env_message_id != NULL) { char * msgid; size_t cur_token; int r; cur_token = 0; r = mailimf_msg_id_parse(env->env_message_id, strlen(env->env_message_id), &cur_token, &msgid); if (r == MAILIMF_NO_ERROR) { // msg id String * str; str = String::stringWithUTF8Characters(msgid); setMessageID(str); mailimf_msg_id_free(msgid); } } } void MessageHeader::importIMAPReferences(Data * data) { size_t cur_token; struct mailimf_fields * fields; int r; struct mailimf_single_fields single_fields; cur_token = 0; r = mailimf_fields_parse(data->bytes(), data->length(), &cur_token, &fields); if (r != MAILIMF_NO_ERROR) { return; } mailimf_single_fields_init(&single_fields, fields); if (single_fields.fld_references != NULL) { Array * msgids; msgids = msg_id_to_string_array(single_fields.fld_references->mid_list); setReferences(msgids); } if (single_fields.fld_subject != NULL) { if (single_fields.fld_subject->sbj_value != NULL) { bool broken; char * value; bool isASCII; broken = false; value = single_fields.fld_subject->sbj_value; isASCII = true; for(char * p = value ; * p != 0 ; p ++) { if ((unsigned char) * p >= 128) { isASCII = false; } } if (strstr(value, "windows-1251") == NULL) { if (isASCII) { broken = true; } } //MCLog("charset: %s %s", value, MCUTF8(charset)); if (!broken) { setSubject(String::stringByDecodingMIMEHeaderValue(single_fields.fld_subject->sbj_value)); } } } mailimf_fields_free(fields); } void MessageHeader::importIMAPInternalDate(struct mailimap_date_time * date) { setReceivedDate(timestampFromIMAPDate(date)); } Array * MessageHeader::recipientWithReplyAll(bool replyAll, bool includeTo, bool includeCc, Array * senderEmails) { bool hasCc; bool hasTo; Set * addedAddresses; Array * toField; Array * ccField; bool containsSender; Array * senderEmailsMailboxes; toField = NULL; ccField = NULL; hasTo = false; hasCc = false; addedAddresses = new Set(); senderEmailsMailboxes = Array::array(); containsSender = false; if (senderEmails != NULL) { mc_foreacharray(Address, address, senderEmails) { senderEmailsMailboxes->addObject(address->mailbox()->lowercaseString()); } if (from() != NULL) { if (senderEmailsMailboxes->containsObject(from()->mailbox()->lowercaseString())) { containsSender = true; } } if (sender() != NULL) { if (senderEmailsMailboxes->containsObject(sender()->mailbox()->lowercaseString())) { containsSender = true; } } } if (containsSender) { Array * recipient; recipient = new Array(); if (to() != NULL) { for(unsigned int i = 0 ; i < to()->count() ; i ++) { Address * address = (Address *) to()->objectAtIndex(i); if (addedAddresses->containsObject(address->mailbox()->lowercaseString())) { continue; } if ((from() != NULL) && address->mailbox()->isEqualCaseInsensitive(from()->mailbox())) { recipient->addObjectsFromArray(replyTo()); if (replyTo() != NULL) { for(unsigned int j = 0 ; j < replyTo()->count() ; j ++) { Address * rtAddress = (Address *) replyTo()->objectAtIndex(j); if (addedAddresses->containsObject(rtAddress->mailbox()->lowercaseString())) { continue; } addedAddresses->addObject(rtAddress->mailbox()->lowercaseString()); } } } else { if (address->mailbox() != NULL) { recipient->addObject(address); addedAddresses->addObject(address->mailbox()->lowercaseString()); } } hasTo = true; } } toField = recipient; toField->retain()->autorelease(); recipient->release(); if (replyAll) { recipient = new Array(); if (cc() != NULL) { for(unsigned int i = 0 ; i < cc()->count() ; i ++) { Address * address = (Address *) cc()->objectAtIndex(i); if (addedAddresses->containsObject(address->mailbox()->lowercaseString())) { continue; } if (address->mailbox() == NULL) continue; recipient->addObject(address); addedAddresses->addObject(address->mailbox()->lowercaseString()); hasCc = true; } } ccField = recipient; ccField->retain()->autorelease(); recipient->release(); } if (!hasTo && !hasCc) { hasTo = true; toField = Array::arrayWithObject(from()); } } else { addedAddresses->addObjectsFromArray(senderEmailsMailboxes); if (replyTo() != NULL && replyTo()->count() > 0) { hasTo = true; toField = replyTo(); for(unsigned int i = 0 ; i < replyTo()->count() ; i ++) { Address * address = (Address *) replyTo()->objectAtIndex(i); if (address->mailbox() == NULL) continue; addedAddresses->addObject(address->mailbox()->lowercaseString()); } } else { if (from() != NULL && from()->mailbox() != NULL) { hasTo = true; toField = Array::arrayWithObject(from()); addedAddresses->addObject(from()->mailbox()->lowercaseString()); } } if (replyAll) { Array * recipient; recipient = new Array(); if (to() != NULL) { for(unsigned int i = 0 ; i < to()->count() ; i ++) { Address * address = (Address *) to()->objectAtIndex(i); if (addedAddresses->containsObject(address->mailbox()->lowercaseString())) { continue; } if (address->mailbox() == NULL) continue; recipient->addObject(address); addedAddresses->addObject(address->mailbox()->lowercaseString()); } } if (cc() != NULL) { for(unsigned int i = 0 ; i < cc()->count() ; i ++) { Address * address = (Address *) cc()->objectAtIndex(i); if (addedAddresses->containsObject(address->mailbox()->lowercaseString())) { continue; } if (address->mailbox() == NULL) continue; recipient->addObject(address); addedAddresses->addObject(address->mailbox()->lowercaseString()); } } if (recipient->count() > 0) { hasCc = true; } ccField = recipient; ccField->retain()->autorelease(); recipient->release(); } } addedAddresses->release(); Array * result; result = Array::array(); if (hasTo && includeTo) result->addObjectsFromArray(toField); if (hasCc && includeCc) result->addObjectsFromArray(ccField); return result; } MessageHeader * MessageHeader::replyHeader(bool replyAll, Array * addressesExcludedFromRecipient) { MessageHeader * result; String * subjectValue; Array * referencesValue; Array * inReplyTo; Array * toValue; Array * ccValue; referencesValue = NULL; inReplyTo = NULL; result = new MessageHeader(); if (subject() == NULL) { subjectValue = MCSTR("Re: "); } else { if (!subject()->lowercaseString()->hasPrefix(MCSTR("re:"))) { subjectValue = MCSTR("Re: ")->stringByAppendingString(subject()); } else { subjectValue = (String *) subject()->copy()->autorelease(); } } 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);; result->setSubject(subjectValue); result->setReferences(referencesValue); result->setInReplyTo(inReplyTo); result->setTo(toValue); result->setCc(ccValue); result->autorelease(); return result; } MessageHeader * MessageHeader::forwardHeader() { MessageHeader * result; String * subjectValue; Array * referencesValue; Array * inReplyTo; referencesValue = NULL; inReplyTo = NULL; result = new MessageHeader(); if (subject() == NULL) { subjectValue = MCSTR("Fw: "); } else { subjectValue = MCSTR("Fw: ")->stringByAppendingString(subject()->extractedSubjectAndKeepBracket(true)); } if (references() != NULL) { referencesValue = (Array *) (references()->copy()); referencesValue->autorelease(); if (messageID() != NULL ) { referencesValue->addObject(messageID()); } } if (messageID() != NULL) { inReplyTo = Array::array(); inReplyTo->addObject(messageID()); } result->setSubject(subjectValue); result->setReferences(referencesValue); result->setInReplyTo(inReplyTo); result->autorelease(); return result; } HashMap * MessageHeader::serializable() { HashMap * result = Object::serializable(); if (messageID() != NULL) { result->setObjectForKey(MCSTR("messageID"), messageID()); } if (mMessageIDAutoGenerated) { result->setObjectForKey(MCSTR("messageIDAutoGenerated"), Value::valueWithBoolValue(true)); } if (references() != NULL) { result->setObjectForKey(MCSTR("references"), references()); } if (inReplyTo() != NULL) { result->setObjectForKey(MCSTR("inReplyTo"), inReplyTo()); } if (sender() != NULL) { result->setObjectForKey(MCSTR("sender"), sender()->serializable()); } if (from() != NULL) { result->setObjectForKey(MCSTR("from"), from()->serializable()); } if (to() != NULL) { result->setObjectForKey(MCSTR("to"), to()->serializable()); } if (cc() != NULL) { result->setObjectForKey(MCSTR("cc"), cc()->serializable()); } if (bcc() != NULL) { result->setObjectForKey(MCSTR("bcc"), bcc()->serializable()); } if (replyTo() != NULL) { result->setObjectForKey(MCSTR("replyTo"), replyTo()->serializable()); } if (subject() != NULL) { result->setObjectForKey(MCSTR("subject"), subject()); } result->setObjectForKey(MCSTR("date"), String::stringWithUTF8Format("%lld", (unsigned long long) date())); result->setObjectForKey(MCSTR("receivedDate"), String::stringWithUTF8Format("%lld", (unsigned long long) receivedDate())); if (mExtraHeaders != NULL) { result->setObjectForKey(MCSTR("extraHeaders"), mExtraHeaders); } return result; } void MessageHeader::importSerializable(HashMap * hashmap) { setMessageID((String *) hashmap->objectForKey(MCSTR("messageID"))); Value * value = (Value *)hashmap->objectForKey(MCSTR("messageIDAutoGenerated")); mMessageIDAutoGenerated = value != NULL && value->boolValue(); setReferences((Array *) hashmap->objectForKey(MCSTR("references"))); setInReplyTo((Array *) hashmap->objectForKey(MCSTR("inReplyTo"))); setSender((Address *) Object::objectWithSerializable((HashMap *) hashmap->objectForKey(MCSTR("sender")))); setFrom((Address *) Object::objectWithSerializable((HashMap *) hashmap->objectForKey(MCSTR("from")))); setTo((Array *) Object::objectWithSerializable((HashMap *) hashmap->objectForKey(MCSTR("to")))); setCc((Array *)Object::objectWithSerializable((HashMap *) hashmap->objectForKey(MCSTR("cc")))); setBcc((Array *)Object::objectWithSerializable((HashMap *) hashmap->objectForKey(MCSTR("bcc")))); setReplyTo((Array *)Object::objectWithSerializable((HashMap *) hashmap->objectForKey(MCSTR("replyTo")))); setSubject((String *) hashmap->objectForKey(MCSTR("subject"))); setDate((time_t) ((String *) hashmap->objectForKey(MCSTR("date")))->unsignedLongLongValue()); setReceivedDate((time_t) ((String *) hashmap->objectForKey(MCSTR("receivedDate")))->unsignedLongLongValue()); setExtraHeaders((HashMap *) hashmap->objectForKey(MCSTR("extraHeaders"))); } static void * createObject() { return new MessageHeader(); } INITIALIZE(MessageHeader) { Object::registerObjectConstructor("mailcore::MessageHeader", &createObject); }