857 lines
22 KiB
C++
857 lines
22 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Netscape Communications Corporation.
|
|
* Portions created by the Initial Developer are Copyright (C) 1999
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
#include "msgCore.h"
|
|
#include "nsMsgHdr.h"
|
|
#include "nsMsgDatabase.h"
|
|
#include "nsMsgUtils.h"
|
|
#include "nsIMsgHeaderParser.h"
|
|
#include "nsMsgMimeCID.h"
|
|
#include "nsIMimeConverter.h"
|
|
|
|
NS_IMPL_ISUPPORTS1(nsMsgHdr, nsIMsgDBHdr)
|
|
|
|
#define FLAGS_INITED 0x1
|
|
#define CACHED_VALUES_INITED 0x2
|
|
#define REFERENCES_INITED 0x4
|
|
#define THREAD_PARENT_INITED 0x8
|
|
|
|
nsMsgHdr::nsMsgHdr(nsMsgDatabase *db, nsIMdbRow *dbRow)
|
|
{
|
|
m_mdb = db;
|
|
Init();
|
|
m_mdbRow = dbRow;
|
|
if(m_mdb)
|
|
{
|
|
m_mdb->AddRef();
|
|
mdbOid outOid;
|
|
if (dbRow && dbRow->GetOid(m_mdb->GetEnv(), &outOid) == NS_OK)
|
|
{
|
|
m_messageKey = outOid.mOid_Id;
|
|
m_mdb->AddHdrToUseCache((nsIMsgDBHdr *) this, m_messageKey);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void nsMsgHdr::Init()
|
|
{
|
|
m_initedValues = 0;
|
|
m_statusOffset = 0xffffffff;
|
|
m_messageKey = nsMsgKey_None;
|
|
m_messageSize = 0;
|
|
m_date = LL_ZERO;
|
|
m_flags = 0;
|
|
m_mdbRow = NULL;
|
|
m_numReferences = 0;
|
|
m_threadId = nsMsgKey_None;
|
|
m_threadParent = nsMsgKey_None;
|
|
}
|
|
|
|
nsresult nsMsgHdr::InitCachedValues()
|
|
{
|
|
nsresult err = NS_OK;
|
|
|
|
if (!m_mdb || !m_mdbRow)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
if (!(m_initedValues & CACHED_VALUES_INITED))
|
|
{
|
|
PRUint32 uint32Value;
|
|
mdbOid outOid;
|
|
if (m_mdbRow->GetOid(m_mdb->GetEnv(), &outOid) == NS_OK)
|
|
m_messageKey = outOid.mOid_Id;
|
|
|
|
err = GetUInt32Column(m_mdb->m_messageSizeColumnToken, &m_messageSize);
|
|
|
|
err = GetUInt32Column(m_mdb->m_dateColumnToken, &uint32Value);
|
|
Seconds2PRTime(uint32Value, &m_date);
|
|
|
|
err = GetUInt32Column(m_mdb->m_messageThreadIdColumnToken, &m_threadId);
|
|
err = GetUInt32Column(m_mdb->m_numReferencesColumnToken, &uint32Value);
|
|
if (NS_SUCCEEDED(err))
|
|
m_numReferences = (PRUint16) uint32Value;
|
|
|
|
if (NS_SUCCEEDED(err))
|
|
m_initedValues |= CACHED_VALUES_INITED;
|
|
}
|
|
return err;
|
|
}
|
|
|
|
nsresult nsMsgHdr::InitFlags()
|
|
{
|
|
|
|
nsresult err = NS_OK;
|
|
|
|
if (!m_mdb)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
if(!(m_initedValues & FLAGS_INITED))
|
|
{
|
|
err = GetUInt32Column(m_mdb->m_flagsColumnToken, &m_flags);
|
|
m_flags &= ~MSG_FLAG_NEW; // don't get new flag from MDB
|
|
|
|
if(NS_SUCCEEDED(err))
|
|
m_initedValues |= FLAGS_INITED;
|
|
}
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
nsMsgHdr::~nsMsgHdr()
|
|
{
|
|
if (m_mdbRow)
|
|
{
|
|
if (m_mdb)
|
|
{
|
|
NS_RELEASE(m_mdbRow);
|
|
m_mdb->RemoveHdrFromUseCache((nsIMsgDBHdr *) this, m_messageKey);
|
|
m_mdb->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetMessageKey(nsMsgKey *result)
|
|
{
|
|
if (m_messageKey == nsMsgKey_None && m_mdbRow != NULL)
|
|
{
|
|
mdbOid outOid;
|
|
if (m_mdbRow->GetOid(m_mdb->GetEnv(), &outOid) == NS_OK)
|
|
m_messageKey = outOid.mOid_Id;
|
|
|
|
}
|
|
*result = m_messageKey;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetThreadId(nsMsgKey *result)
|
|
{
|
|
|
|
if (!(m_initedValues & CACHED_VALUES_INITED))
|
|
InitCachedValues();
|
|
|
|
if (result)
|
|
{
|
|
*result = m_threadId;
|
|
return NS_OK;
|
|
}
|
|
return NS_ERROR_NULL_POINTER;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::SetThreadId(nsMsgKey inKey)
|
|
{
|
|
m_threadId = inKey;
|
|
return SetUInt32Column(m_threadId, m_mdb->m_messageThreadIdColumnToken);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::SetMessageKey(nsMsgKey value)
|
|
{
|
|
m_messageKey = value;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult nsMsgHdr::GetRawFlags(PRUint32 *result)
|
|
{
|
|
if (!(m_initedValues & FLAGS_INITED))
|
|
InitFlags();
|
|
*result = m_flags;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetFlags(PRUint32 *result)
|
|
{
|
|
if (!(m_initedValues & FLAGS_INITED))
|
|
InitFlags();
|
|
if (m_mdb)
|
|
*result = m_mdb->GetStatusFlags(this, m_flags);
|
|
else
|
|
*result = m_flags;
|
|
#ifdef DEBUG_bienvenu
|
|
NS_ASSERTION(! (*result & (MSG_FLAG_ELIDED | MSG_FLAG_IGNORED)), "shouldn't be set in db");
|
|
#endif
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::SetFlags(PRUint32 flags)
|
|
{
|
|
#ifdef DEBUG_bienvenu
|
|
NS_ASSERTION(! (flags & (MSG_FLAG_ELIDED | MSG_FLAG_IGNORED)), "shouldn't set this flag on db");
|
|
#endif
|
|
m_initedValues |= FLAGS_INITED;
|
|
m_flags = flags;
|
|
// don't write out MSG_FLAG_NEW to MDB.
|
|
return SetUInt32Column(m_flags & ~MSG_FLAG_NEW, m_mdb->m_flagsColumnToken);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::OrFlags(PRUint32 flags, PRUint32 *result)
|
|
{
|
|
if (!(m_initedValues & FLAGS_INITED))
|
|
InitFlags();
|
|
if ((m_flags & flags) != flags)
|
|
SetFlags (m_flags | flags);
|
|
*result = m_flags;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::AndFlags(PRUint32 flags, PRUint32 *result)
|
|
{
|
|
if (!(m_initedValues & FLAGS_INITED))
|
|
InitFlags();
|
|
if ((m_flags & flags) != m_flags)
|
|
SetFlags (m_flags & flags);
|
|
*result = m_flags;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::MarkHasAttachments(PRBool bHasAttachments)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
if(m_mdb)
|
|
{
|
|
nsMsgKey key;
|
|
rv = GetMessageKey(&key);
|
|
if(NS_SUCCEEDED(rv))
|
|
rv = m_mdb->MarkHasAttachments(key, bHasAttachments, nsnull);
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::MarkRead(PRBool bRead)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
if(m_mdb)
|
|
{
|
|
nsMsgKey key;
|
|
rv = GetMessageKey(&key);
|
|
if(NS_SUCCEEDED(rv))
|
|
rv = m_mdb->MarkRead(key, bRead, nsnull);
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::MarkFlagged(PRBool bFlagged)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
if(m_mdb)
|
|
{
|
|
nsMsgKey key;
|
|
rv = GetMessageKey(&key);
|
|
if(NS_SUCCEEDED(rv))
|
|
rv = m_mdb->MarkMarked(key, bFlagged, nsnull);
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetProperty(const char *propertyName, nsAString &resultProperty)
|
|
{
|
|
return m_mdb->GetPropertyAsNSString(GetMDBRow(), propertyName, resultProperty);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::SetProperty(const char *propertyName, const nsAString &propertyStr)
|
|
{
|
|
return m_mdb->SetPropertyFromNSString(m_mdbRow, propertyName, propertyStr);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::SetStringProperty(const char *propertyName, const char *propertyValue)
|
|
{
|
|
return m_mdb->SetProperty(m_mdbRow, propertyName, propertyValue);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetStringProperty(const char *propertyName, char **aPropertyValue)
|
|
{
|
|
return m_mdb->GetProperty(m_mdbRow, propertyName, aPropertyValue);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetUint32Property(const char *propertyName, PRUint32 *pResult)
|
|
{
|
|
return m_mdb->GetUint32Property(GetMDBRow(), propertyName, pResult);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::SetUint32Property(const char *propertyName, PRUint32 value)
|
|
{
|
|
return m_mdb->SetUint32Property(GetMDBRow(), propertyName, value);
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetNumReferences(PRUint16 *result)
|
|
{
|
|
if (!(m_initedValues & CACHED_VALUES_INITED))
|
|
InitCachedValues();
|
|
|
|
*result = m_numReferences;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult nsMsgHdr::ParseReferences(const char *references)
|
|
{
|
|
const char *startNextRef = references;
|
|
nsCAutoString resultReference;
|
|
|
|
while (startNextRef && *startNextRef)
|
|
{
|
|
startNextRef = GetNextReference(startNextRef, resultReference);
|
|
m_references.AppendCString(resultReference);
|
|
}
|
|
m_numReferences = m_references.Count();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetStringReference(PRInt32 refNum, nsACString& resultReference)
|
|
{
|
|
nsresult err = NS_OK;
|
|
|
|
if(!(m_initedValues & REFERENCES_INITED))
|
|
{
|
|
const char *references;
|
|
err = m_mdb->RowCellColumnToConstCharPtr(GetMDBRow(), m_mdb->m_referencesColumnToken, &references);
|
|
|
|
if(NS_SUCCEEDED(err))
|
|
{
|
|
ParseReferences(references);
|
|
m_initedValues |= REFERENCES_INITED;
|
|
}
|
|
}
|
|
|
|
if (refNum < m_numReferences)
|
|
m_references.CStringAt(refNum, resultReference);
|
|
return err;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetDate(PRTime *result)
|
|
{
|
|
if (!(m_initedValues & CACHED_VALUES_INITED))
|
|
InitCachedValues();
|
|
|
|
*result = m_date;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetDateInSeconds(PRUint32 *aResult)
|
|
{
|
|
return GetUInt32Column(m_mdb->m_dateColumnToken, aResult);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::SetMessageId(const char *messageId)
|
|
{
|
|
if (messageId && *messageId == '<')
|
|
{
|
|
nsCAutoString tempMessageID(messageId + 1);
|
|
if (tempMessageID.Last() == '>')
|
|
tempMessageID.SetLength(tempMessageID.Length() - 1);
|
|
return SetStringColumn(tempMessageID.get(), m_mdb->m_messageIdColumnToken);
|
|
}
|
|
return SetStringColumn(messageId, m_mdb->m_messageIdColumnToken);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::SetSubject(const char *subject)
|
|
{
|
|
return SetStringColumn(subject, m_mdb->m_subjectColumnToken);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::SetAuthor(const char *author)
|
|
{
|
|
return SetStringColumn(author, m_mdb->m_senderColumnToken);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::SetReferences(const char *references)
|
|
{
|
|
if (*references == '\0') {
|
|
m_numReferences = 0;
|
|
}
|
|
else {
|
|
ParseReferences(references);
|
|
}
|
|
|
|
SetUInt32Column(m_numReferences, m_mdb->m_numReferencesColumnToken);
|
|
m_initedValues |= REFERENCES_INITED;
|
|
|
|
return SetStringColumn(references, m_mdb->m_referencesColumnToken);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::SetRecipients(const char *recipients)
|
|
{
|
|
// need to put in rfc822 address parsing code here (or make caller do it...)
|
|
return SetStringColumn(recipients, m_mdb->m_recipientsColumnToken);
|
|
}
|
|
|
|
nsresult nsMsgHdr::BuildRecipientsFromArray(const char *names, const char *addresses, PRUint32 numAddresses, nsCAutoString& allRecipients)
|
|
{
|
|
nsresult ret = NS_OK;
|
|
const char *curName = names;
|
|
const char *curAddress = addresses;
|
|
nsIMsgHeaderParser *headerParser = m_mdb->GetHeaderParser();
|
|
|
|
for (PRUint32 i = 0; i < numAddresses; i++, curName += strlen(curName) + 1, curAddress += strlen(curAddress) + 1)
|
|
{
|
|
if (i > 0)
|
|
allRecipients += ", ";
|
|
|
|
if (headerParser)
|
|
{
|
|
nsCString fullAddress;
|
|
ret = headerParser->MakeFullAddress(nsnull, curName, curAddress, getter_Copies(fullAddress));
|
|
if (NS_SUCCEEDED(ret) && !fullAddress.IsEmpty())
|
|
{
|
|
allRecipients += fullAddress;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// Just in case the parser failed...
|
|
if (strlen(curName))
|
|
{
|
|
allRecipients += curName;
|
|
allRecipients += ' ';
|
|
}
|
|
|
|
if (strlen(curAddress))
|
|
{
|
|
allRecipients += '<';
|
|
allRecipients += curAddress;
|
|
allRecipients += '>';
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::SetRecipientsArray(const char *names, const char *addresses, PRUint32 numAddresses)
|
|
{
|
|
nsresult ret;
|
|
nsCAutoString allRecipients;
|
|
|
|
ret = BuildRecipientsFromArray(names, addresses, numAddresses, allRecipients);
|
|
if (NS_FAILED(ret))
|
|
return ret;
|
|
|
|
ret = SetRecipients(allRecipients.get());
|
|
return ret;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::SetCcList(const char *ccList)
|
|
{
|
|
return SetStringColumn(ccList, m_mdb->m_ccListColumnToken);
|
|
}
|
|
|
|
// ###should make helper routine that takes column token!
|
|
NS_IMETHODIMP nsMsgHdr::SetCCListArray(const char *names, const char *addresses, PRUint32 numAddresses)
|
|
{
|
|
nsresult ret;
|
|
nsCAutoString allRecipients;
|
|
|
|
ret = BuildRecipientsFromArray(names, addresses, numAddresses, allRecipients);
|
|
if (NS_FAILED(ret))
|
|
return ret;
|
|
|
|
ret = SetCcList(allRecipients.get());
|
|
return ret;
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP nsMsgHdr::SetMessageSize(PRUint32 messageSize)
|
|
{
|
|
SetUInt32Column(messageSize, m_mdb->m_messageSizeColumnToken);
|
|
m_messageSize = messageSize;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetOfflineMessageSize(PRUint32 *result)
|
|
{
|
|
PRUint32 size;
|
|
nsresult res = GetUInt32Column(m_mdb->m_offlineMessageSizeColumnToken, &size);
|
|
|
|
*result = size;
|
|
return res;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::SetOfflineMessageSize(PRUint32 messageSize)
|
|
{
|
|
return SetUInt32Column(messageSize, m_mdb->m_offlineMessageSizeColumnToken);
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP nsMsgHdr::SetLineCount(PRUint32 lineCount)
|
|
{
|
|
SetUInt32Column(lineCount, m_mdb->m_numLinesColumnToken);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::SetStatusOffset(PRUint32 statusOffset)
|
|
{
|
|
return SetUInt32Column(statusOffset, m_mdb->m_statusOffsetColumnToken);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::SetDate(PRTime date)
|
|
{
|
|
m_date = date;
|
|
PRUint32 seconds;
|
|
PRTime2Seconds(date, &seconds);
|
|
return SetUInt32Column((PRUint32) seconds, m_mdb->m_dateColumnToken);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetStatusOffset(PRUint32 *result)
|
|
{
|
|
PRUint32 offset = 0;
|
|
nsresult res = GetUInt32Column(m_mdb->m_statusOffsetColumnToken, &offset);
|
|
|
|
*result = offset;
|
|
return res;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::SetPriority(nsMsgPriorityValue priority)
|
|
{
|
|
SetUInt32Column((PRUint32) priority, m_mdb->m_priorityColumnToken);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetPriority(nsMsgPriorityValue *result)
|
|
{
|
|
if (!result)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
PRUint32 priority = 0;
|
|
nsresult rv = GetUInt32Column(m_mdb->m_priorityColumnToken, &priority);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
*result = (nsMsgPriorityValue) priority;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::SetLabel(nsMsgLabelValue label)
|
|
{
|
|
SetUInt32Column((PRUint32) label, m_mdb->m_labelColumnToken);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetLabel(nsMsgLabelValue *result)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(result);
|
|
|
|
return GetUInt32Column(m_mdb->m_labelColumnToken, result);
|
|
}
|
|
|
|
// I'd like to not store the account key, if the msg is in
|
|
// the same account as it was received in, to save disk space and memory.
|
|
// This might be problematic when a message gets moved...
|
|
// And I'm not sure if we should short circuit it here,
|
|
// or at a higher level where it might be more efficient.
|
|
NS_IMETHODIMP nsMsgHdr::SetAccountKey(const char *aAccountKey)
|
|
{
|
|
return SetStringProperty("account", aAccountKey);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetAccountKey(char **aResult)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aResult);
|
|
|
|
return GetStringProperty("account", aResult);
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetMessageOffset(PRUint32 *result)
|
|
{
|
|
NS_ENSURE_ARG(result);
|
|
|
|
// if we have the message body offline, then return the message offset column
|
|
// (this will only be true for news and imap messages).
|
|
PRUint32 rawFlags;
|
|
GetRawFlags(&rawFlags);
|
|
if (rawFlags & MSG_FLAG_OFFLINE)
|
|
{
|
|
return GetUInt32Column(m_mdb->m_offlineMsgOffsetColumnToken, result);
|
|
}
|
|
else
|
|
{
|
|
*result = m_messageKey;
|
|
return NS_OK;
|
|
}
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::SetMessageOffset(PRUint32 offset)
|
|
{
|
|
SetUInt32Column(offset, m_mdb->m_offlineMsgOffsetColumnToken);
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetMessageSize(PRUint32 *result)
|
|
{
|
|
PRUint32 size;
|
|
nsresult res = GetUInt32Column(m_mdb->m_messageSizeColumnToken, &size);
|
|
|
|
*result = size;
|
|
return res;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetLineCount(PRUint32 *result)
|
|
{
|
|
PRUint32 linecount;
|
|
nsresult res = GetUInt32Column(m_mdb->m_numLinesColumnToken, &linecount);
|
|
*result = linecount;
|
|
return res;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::SetPriorityString(const char *priority)
|
|
{
|
|
nsMsgPriorityValue priorityVal = nsMsgPriority::Default;
|
|
|
|
// We can ignore |NS_MsgGetPriorityFromString()| return value,
|
|
// since we set a default value for |priorityVal|.
|
|
NS_MsgGetPriorityFromString(priority, priorityVal);
|
|
|
|
return SetPriority(priorityVal);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetAuthor(char* *resultAuthor)
|
|
{
|
|
return m_mdb->RowCellColumnToCharPtr(GetMDBRow(), m_mdb->m_senderColumnToken, resultAuthor);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetSubject(char* *resultSubject)
|
|
{
|
|
return m_mdb->RowCellColumnToCharPtr(GetMDBRow(), m_mdb->m_subjectColumnToken, resultSubject);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetRecipients(char* *resultRecipients)
|
|
{
|
|
return m_mdb->RowCellColumnToCharPtr(GetMDBRow(), m_mdb->m_recipientsColumnToken, resultRecipients);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetCcList(char * *resultCCList)
|
|
{
|
|
return m_mdb->RowCellColumnToCharPtr(GetMDBRow(), m_mdb->m_ccListColumnToken, resultCCList);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetMessageId(char * *resultMessageId)
|
|
{
|
|
return m_mdb->RowCellColumnToCharPtr(GetMDBRow(), m_mdb->m_messageIdColumnToken, resultMessageId);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetMime2DecodedAuthor(PRUnichar* *resultAuthor)
|
|
{
|
|
return m_mdb->RowCellColumnToMime2DecodedString(GetMDBRow(), m_mdb->m_senderColumnToken, resultAuthor);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetMime2DecodedSubject(PRUnichar* *resultSubject)
|
|
{
|
|
return m_mdb->RowCellColumnToMime2DecodedString(GetMDBRow(), m_mdb->m_subjectColumnToken, resultSubject);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetMime2DecodedRecipients(PRUnichar* *resultRecipients)
|
|
{
|
|
return m_mdb->RowCellColumnToMime2DecodedString(GetMDBRow(), m_mdb->m_recipientsColumnToken, resultRecipients);
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetAuthorCollationKey(PRUint8 **resultAuthor, PRUint32 *len)
|
|
{
|
|
return m_mdb->RowCellColumnToAddressCollationKey(GetMDBRow(), m_mdb->m_senderColumnToken, resultAuthor, len);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetSubjectCollationKey(PRUint8 **resultSubject, PRUint32 *len)
|
|
{
|
|
return m_mdb->RowCellColumnToCollationKey(GetMDBRow(), m_mdb->m_subjectColumnToken, resultSubject, len);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetRecipientsCollationKey(PRUint8 **resultRecipients, PRUint32 *len)
|
|
{
|
|
return m_mdb->RowCellColumnToCollationKey(GetMDBRow(), m_mdb->m_recipientsColumnToken, resultRecipients, len);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetCharset(char **aCharset)
|
|
{
|
|
return m_mdb->RowCellColumnToCharPtr(GetMDBRow(), m_mdb->m_messageCharSetColumnToken, aCharset);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::SetCharset(const char *aCharset)
|
|
{
|
|
return SetStringColumn(aCharset, m_mdb->m_messageCharSetColumnToken);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::SetThreadParent(nsMsgKey inKey)
|
|
{
|
|
m_threadParent = inKey;
|
|
if (inKey == m_messageKey)
|
|
NS_ASSERTION(PR_FALSE, "can't be your own parent");
|
|
SetUInt32Column(m_threadParent, m_mdb->m_threadParentColumnToken);
|
|
m_initedValues |= THREAD_PARENT_INITED;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetThreadParent(nsMsgKey *result)
|
|
{
|
|
nsresult res;
|
|
if(!(m_initedValues & THREAD_PARENT_INITED))
|
|
{
|
|
res = GetUInt32Column(m_mdb->m_threadParentColumnToken, &m_threadParent, nsMsgKey_None);
|
|
if (NS_SUCCEEDED(res))
|
|
m_initedValues |= THREAD_PARENT_INITED;
|
|
}
|
|
*result = m_threadParent;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetFolder(nsIMsgFolder **result)
|
|
{
|
|
NS_ENSURE_ARG(result);
|
|
|
|
if (m_mdb && m_mdb->m_folder)
|
|
{
|
|
*result = m_mdb->m_folder;
|
|
NS_ADDREF(*result);
|
|
}
|
|
else
|
|
*result = nsnull;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult nsMsgHdr::SetStringColumn(const char *str, mdb_token token)
|
|
{
|
|
return m_mdb->CharPtrToRowCellColumn(m_mdbRow, token, str);
|
|
}
|
|
|
|
nsresult nsMsgHdr::SetUInt32Column(PRUint32 value, mdb_token token)
|
|
{
|
|
return m_mdb->UInt32ToRowCellColumn(m_mdbRow, token, value);
|
|
}
|
|
|
|
nsresult nsMsgHdr::GetUInt32Column(mdb_token token, PRUint32 *pvalue, PRUint32 defaultValue)
|
|
{
|
|
return m_mdb->RowCellColumnToUInt32(GetMDBRow(), token, pvalue, defaultValue);
|
|
}
|
|
|
|
// get the next <> delimited reference from nextRef and copy it into reference,
|
|
const char *nsMsgHdr::GetNextReference(const char *startNextRef, nsCString &reference)
|
|
{
|
|
const char *ptr = startNextRef;
|
|
|
|
reference.Truncate();
|
|
while ((*ptr == '<' || *ptr == ' ' || *ptr == '\r' || *ptr == '\n' || *ptr == '\t') && *ptr)
|
|
ptr++;
|
|
|
|
for (int i = 0; *ptr && *ptr != '>'; i++)
|
|
reference += *ptr++;
|
|
|
|
if (*ptr == '>')
|
|
ptr++;
|
|
return ptr;
|
|
}
|
|
// Get previous <> delimited reference - used to go backwards through the
|
|
// reference string. Caller will need to make sure that prevRef is not before
|
|
// the start of the reference string when we return.
|
|
const char *nsMsgHdr::GetPrevReference(const char *prevRef, nsCString &reference)
|
|
{
|
|
const char *ptr = prevRef;
|
|
|
|
while ((*ptr == '>' || *ptr == ' ') && *ptr)
|
|
ptr--;
|
|
|
|
// scan back to '<'
|
|
for (int i = 0; *ptr && *ptr != '<' ; i++)
|
|
ptr--;
|
|
|
|
GetNextReference(ptr, reference);
|
|
if (*ptr == '<')
|
|
ptr--;
|
|
return ptr;
|
|
}
|
|
|
|
PRBool nsMsgHdr::IsParentOf(nsIMsgDBHdr *possibleChild)
|
|
{
|
|
PRUint16 referenceToCheck = 0;
|
|
possibleChild->GetNumReferences(&referenceToCheck);
|
|
nsCAutoString reference;
|
|
|
|
nsCString messageId;
|
|
GetMessageId(getter_Copies(messageId));
|
|
|
|
while (referenceToCheck > 0)
|
|
{
|
|
possibleChild->GetStringReference(referenceToCheck - 1, reference);
|
|
|
|
if (reference.Equals(messageId))
|
|
return PR_TRUE;
|
|
// if reference didn't match, check if this ref is for a non-existent
|
|
// header. If it is, continue looking at ancestors.
|
|
nsCOMPtr <nsIMsgDBHdr> refHdr;
|
|
if (!m_mdb)
|
|
break;
|
|
(void) m_mdb->GetMsgHdrForMessageID(reference.get(), getter_AddRefs(refHdr));
|
|
if (refHdr)
|
|
break;
|
|
referenceToCheck--;
|
|
}
|
|
return PR_FALSE;
|
|
}
|
|
|
|
PRBool nsMsgHdr::IsAncestorOf(nsIMsgDBHdr *possibleChild)
|
|
{
|
|
const char *references;
|
|
nsMsgHdr* curHdr = static_cast<nsMsgHdr*>(possibleChild); // closed system, cast ok
|
|
m_mdb->RowCellColumnToConstCharPtr(curHdr->GetMDBRow(), m_mdb->m_referencesColumnToken, &references);
|
|
if (!references)
|
|
return PR_FALSE;
|
|
|
|
nsCString messageId;
|
|
// should put < > around message id to make strstr strictly match
|
|
GetMessageId(getter_Copies(messageId));
|
|
return (strstr(references, messageId.get()) != nsnull);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetIsRead(PRBool *isRead)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(isRead);
|
|
if (!(m_initedValues & FLAGS_INITED))
|
|
InitFlags();
|
|
*isRead = m_flags & MSG_FLAG_READ;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgHdr::GetIsFlagged(PRBool *isFlagged)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(isFlagged);
|
|
if (!(m_initedValues & FLAGS_INITED))
|
|
InitFlags();
|
|
*isFlagged = m_flags & MSG_FLAG_MARKED;
|
|
return NS_OK;
|
|
}
|