<commit_before>/*
 * $Id$
 *
 * Copyright(C) 1998-2004 <NAME>
 * All rights reserved.
 *
 */

#include <qmaccount.h>
#include <qmapplication.h>
#include <qmdocument.h>
#include <qmfolder.h>
#include <qmmacro.h>
#include <qmmessage.h>
#include <qmsecurity.h>

#include <qscrypto.h>

#include "messagecomposer.h"
#include "../model/addressbook.h"
#include "../ui/foldermodel.h"
#include "../ui/securitymodel.h"

using namespace qm;
using namespace qs;


/****************************************************************************
 *
 * MessageComposer
 *
 */

qm::MessageComposer::MessageComposer(bool bDraft,
									 Document* pDocument,
									 Profile* pProfile,
									 HWND hwnd,
									 FolderModel* pFolderModel,
									 SecurityModel* pSecurityModel) :
	bDraft_(bDraft),
	pDocument_(pDocument),
	pProfile_(pProfile),
	hwnd_(hwnd),
	pFolderModel_(pFolderModel),
	pSecurityModel_(pSecurityModel)
{
}

qm::MessageComposer::~MessageComposer()
{
}

bool qm::MessageComposer::compose(Account* pAccount,
								  SubAccount* pSubAccount,
								  Message* pMessage,
								  unsigned int nFlags) const
{
	assert(pAccount || pFolderModel_);
	assert((!pAccount && !pSubAccount) ||
		(pAccount && !pSubAccount) || (pAccount && pSubAccount));
	assert(pMessage);
	
	if (!pAccount) {
		assert(pFolderModel_);
		
		UnstructuredParser account;
		Part::Field f = pMessage->getField(L"X-QMAIL-Account", &account);
		if (f == Part::FIELD_EXIST) {
			pAccount = pDocument_->getAccount(account.getValue());
		}
		else {
			pAccount = pFolderModel_->getCurrentAccount();
			if (!pAccount) {
				Folder* pFolder = pFolderModel_->getCurrentFolder();
				if (pFolder)
					pAccount = pFolder->getAccount();
			}
		}
	}
	if (!pAccount)
		return false;
	if (!pSubAccount) {
		UnstructuredParser subaccount;
		Part::Field f = pMessage->getField(L"X-QMAIL-SubAccount", &subaccount);
		if (f == Part::FIELD_EXIST)
			pSubAccount = pAccount->getSubAccount(subaccount.getValue());
		else
			pSubAccount = pAccount->getCurrentSubAccount();
	}
	
	Folder* pFolder = pAccount->getFolderByFlag(
		bDraft_ ? Folder::FLAG_DRAFTBOX : Folder::FLAG_OUTBOX);
	if (!pFolder || pFolder->getType() != Folder::TYPE_NORMAL)
		return false;
	
	bool bResent = PartUtil(*pMessage).isResent();
	
	AddressParser from(pSubAccount->getSenderName(),
		pSubAccount->getSenderAddress());
	if (!pMessage->setField(bResent ? L"Resent-From" : L"From", from))
		return false;
	
	Time time(Time::getCurrentTime());
	DateParser date(time);
	if (!pMessage->setField(bResent ? L"Resent-Date" : L"Date", date))
		return false;
	
	if (pSubAccount->isAddMessageId()) {
		WCHAR wsz[256];
		swprintf(wsz, L"%u%04d%02d%02d%02d%02d%02d",
			::GetCurrentProcessId(), time.wYear, time.wMonth,
			time.wDay, time.wHour, time.wMinute, time.wSecond);
		
		wstring_ptr wstrMessageId(concat(wsz, pSubAccount->getSenderAddress()));
		
		MessageIdParser messageId(wstrMessageId.get());
		if (!pMessage->setField(bResent ? L"Resent-Message-Id" : L"Message-Id", messageId))
			return false;
	}
	
	const WCHAR* pwszMacro = 0;
	UnstructuredParser macro;
	Part::Field f = pMessage->getField(L"X-QMAIL-Macro", &macro);
	if (f == Part::FIELD_EXIST)
		pwszMacro = macro.getValue();
	pMessage->removeField(L"X-QMAIL-Macro");
	
	bool bWithOSVersion = pProfile_->getInt(L"Global", L"XMailerWithOSVersion", 1) != 0;
	wstring_ptr wstrVersion(Application::getApplication().getVersion(L' ', bWithOSVersion));
	UnstructuredParser mailer(wstrVersion.get(), L"utf-8");
	if (!pMessage->replaceField(L"X-Mailer", mailer))
		return false;
	
	if (!pMessage->sortHeader())
		return false;
	
	const Security* pSecurity = pDocument_->getSecurity();
	const SMIMEUtility* pSMIMEUtility = pSecurity->getSMIMEUtility();
	if (pSMIMEUtility && nFlags != 0) {
		const Certificate* pSelfCertificate = 0;
		if (pProfile_->getInt(L"Security", L"EncryptForSelf", 0))
			pSelfCertificate = pSubAccount->getCertificate();
		SMIMECallbackImpl callback(pSecurity,
			pDocument_->getAddressBook(), pSelfCertificate);
		
		if (nFlags & FLAG_SIGN) {
			bool bMultipart = pProfile_->getInt(L"Security", L"MultipartSigned", 1) != 0;
			Certificate* pCertificate = pSubAccount->getCertificate();
			PrivateKey* pPrivateKey = pSubAccount->getPrivateKey();
			if (pCertificate && pPrivateKey) {
				xstring_ptr strMessage(pSMIMEUtility->sign(pMessage,
					bMultipart, pPrivateKey, pCertificate));
				if (!strMessage.get())
					return false;
				if (!pMessage->create(strMessage.get(), -1, Message::FLAG_NONE))
					return false;<commit_msg>When sign and encrypt, don't use multipart/signed.<commit_after>/*
 * $Id$
 *
 * Copyright(C) 1998-2004 <NAME>
 * All rights reserved.
 *
 */

#include <qmaccount.h>
#include <qmapplication.h>
#include <qmdocument.h>
#include <qmfolder.h>
#include <qmmacro.h>
#include <qmmessage.h>
#include <qmsecurity.h>

#include <qscrypto.h>

#include "messagecomposer.h"
#include "../model/addressbook.h"
#include "../ui/foldermodel.h"
#include "../ui/securitymodel.h"

using namespace qm;
using namespace qs;


/****************************************************************************
 *
 * MessageComposer
 *
 */

qm::MessageComposer::MessageComposer(bool bDraft,
									 Document* pDocument,
									 Profile* pProfile,
									 HWND hwnd,
									 FolderModel* pFolderModel,
									 SecurityModel* pSecurityModel) :
	bDraft_(bDraft),
	pDocument_(pDocument),
	pProfile_(pProfile),
	hwnd_(hwnd),
	pFolderModel_(pFolderModel),
	pSecurityModel_(pSecurityModel)
{
}

qm::MessageComposer::~MessageComposer()
{
}

bool qm::MessageComposer::compose(Account* pAccount,
								  SubAccount* pSubAccount,
								  Message* pMessage,
								  unsigned int nFlags) const
{
	assert(pAccount || pFolderModel_);
	assert((!pAccount && !pSubAccount) ||
		(pAccount && !pSubAccount) || (pAccount && pSubAccount));
	assert(pMessage);
	
	if (!pAccount) {
		assert(pFolderModel_);
		
		UnstructuredParser account;
		Part::Field f = pMessage->getField(L"X-QMAIL-Account", &account);
		if (f == Part::FIELD_EXIST) {
			pAccount = pDocument_->getAccount(account.getValue());
		}
		else {
			pAccount = pFolderModel_->getCurrentAccount();
			if (!pAccount) {
				Folder* pFolder = pFolderModel_->getCurrentFolder();
				if (pFolder)
					pAccount = pFolder->getAccount();
			}
		}
	}
	if (!pAccount)
		return false;
	if (!pSubAccount) {
		UnstructuredParser subaccount;
		Part::Field f = pMessage->getField(L"X-QMAIL-SubAccount", &subaccount);
		if (f == Part::FIELD_EXIST)
			pSubAccount = pAccount->getSubAccount(subaccount.getValue());
		else
			pSubAccount = pAccount->getCurrentSubAccount();
	}
	
	Folder* pFolder = pAccount->getFolderByFlag(
		bDraft_ ? Folder::FLAG_DRAFTBOX : Folder::FLAG_OUTBOX);
	if (!pFolder || pFolder->getType() != Folder::TYPE_NORMAL)
		return false;
	
	bool bResent = PartUtil(*pMessage).isResent();
	
	AddressParser from(pSubAccount->getSenderName(),
		pSubAccount->getSenderAddress());
	if (!pMessage->setField(bResent ? L"Resent-From" : L"From", from))
		return false;
	
	Time time(Time::getCurrentTime());
	DateParser date(time);
	if (!pMessage->setField(bResent ? L"Resent-Date" : L"Date", date))
		return false;
	
	if (pSubAccount->isAddMessageId()) {
		WCHAR wsz[256];
		swprintf(wsz, L"%u%04d%02d%02d%02d%02d%02d",
			::GetCurrentProcessId(), time.wYear, time.wMonth,
			time.wDay, time.wHour, time.wMinute, time.wSecond);
		
		wstring_ptr wstrMessageId(concat(wsz, pSubAccount->getSenderAddress()));
		
		MessageIdParser messageId(wstrMessageId.get());
		if (!pMessage->setField(bResent ? L"Resent-Message-Id" : L"Message-Id", messageId))
			return false;
	}
	
	const WCHAR* pwszMacro = 0;
	UnstructuredParser macro;
	Part::Field f = pMessage->getField(L"X-QMAIL-Macro", &macro);
	if (f == Part::FIELD_EXIST)
		pwszMacro = macro.getValue();
	pMessage->removeField(L"X-QMAIL-Macro");
	
	bool bWithOSVersion = pProfile_->getInt(L"Global", L"XMailerWithOSVersion", 1) != 0;
	wstring_ptr wstrVersion(Application::getApplication().getVersion(L' ', bWithOSVersion));
	UnstructuredParser mailer(wstrVersion.get(), L"utf-8");
	if (!pMessage->replaceField(L"X-Mailer", mailer))
		return false;
	
	if (!pMessage->sortHeader())
		return false;
	
	const Security* pSecurity = pDocument_->getSecurity();
	const SMIMEUtility* pSMIMEUtility = pSecurity->getSMIMEUtility();
	if (pSMIMEUtility && nFlags != 0) {
		const Certificate* pSelfCertificate = 0;
		if (pProfile_->getInt(L"Security", L"EncryptForSelf", 0))
			pSelfCertificate = pSubAccount->getCertificate();
		SMIMECallbackImpl callback(pSecurity,
			pDocument_->getAddressBook(), pSelfCertificate);
		
		if (nFlags & FLAG_SIGN) {
			bool bMultipart = (nFlags & FLAG_ENCRYPT) == 0 &&
				pProfile_->getInt(L"Security", L"MultipartSigned", 1) != 0;
			Certificate* pCertificate = pSubAccount->getCertificate();
			PrivateKey* pPrivateKey = pSubAccount->getPrivateKey();
			if (pCertificate && pPrivateKey) {
				xstring_ptr strMessage(pSMIMEUtility->sign(pMessage,
					bMultipart, pPrivateKey, pCertificate));
				if (!strMessage.get())
					return false;
				if (!pMessage->create(strMessage.get(), -1, Message::FLAG_NONE))
					return false;
{'fraction_non_alphanumeric': 0.16395056327244886, 'fraction_numerical': 0.00732801049983594, 'mean_word_length': 4.903163331181408, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 85, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3846026', 'n_tokens_mistral': 3539, 'n_tokens_neox': 3114, 'n_words': 570}