Back to index

lightning-sunbird  0.9+nobinonly
nsMsgHdr.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Pierre Phaneuf <pp@ludusdesign.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "msgCore.h"
00040 #include "nsMsgHdr.h"
00041 #include "nsMsgDatabase.h"
00042 #include "nsMsgUtils.h"
00043 #include "nsIMsgHeaderParser.h"
00044 #include "nsMsgMimeCID.h"
00045 #include "nsIMimeConverter.h"
00046 #include "nsXPIDLString.h"
00047 
00048 NS_IMPL_ISUPPORTS1(nsMsgHdr, nsIMsgDBHdr)
00049 
00050 #define FLAGS_INITED 0x1
00051 #define CACHED_VALUES_INITED 0x2
00052 #define REFERENCES_INITED 0x4
00053 #define THREAD_PARENT_INITED 0x8
00054 
00055 nsMsgHdr::nsMsgHdr(nsMsgDatabase *db, nsIMdbRow *dbRow)
00056 {
00057   m_mdb = db;
00058   Init();
00059   m_mdbRow = dbRow;
00060   if(m_mdb)
00061   {
00062     m_mdb->AddRef();
00063     mdbOid outOid;
00064     if (dbRow && dbRow->GetOid(m_mdb->GetEnv(), &outOid) == NS_OK)
00065     {
00066       m_messageKey = outOid.mOid_Id;
00067       m_mdb->AddHdrToUseCache((nsIMsgDBHdr *) this, m_messageKey);
00068     }
00069   }
00070 }
00071 
00072 
00073 void nsMsgHdr::Init()
00074 {
00075   m_initedValues = 0;
00076   m_statusOffset = 0xffffffff;
00077   m_messageKey = nsMsgKey_None;
00078   m_messageSize = 0;
00079   m_date = LL_ZERO;
00080   m_flags = 0;
00081   m_mdbRow = NULL;
00082   m_numReferences = 0;
00083   m_threadId = nsMsgKey_None;
00084   m_threadParent = nsMsgKey_None;
00085 }
00086 
00087 nsresult nsMsgHdr::InitCachedValues()
00088 {
00089   nsresult err = NS_OK;
00090   
00091   if (!m_mdb || !m_mdbRow)
00092     return NS_ERROR_NULL_POINTER;
00093   
00094   if (!(m_initedValues & CACHED_VALUES_INITED))
00095   {
00096     PRUint32 uint32Value;
00097     mdbOid outOid;
00098     if (m_mdbRow->GetOid(m_mdb->GetEnv(), &outOid) == NS_OK)
00099       m_messageKey = outOid.mOid_Id;
00100     
00101     err = GetUInt32Column(m_mdb->m_messageSizeColumnToken, &m_messageSize);
00102     
00103     err = GetUInt32Column(m_mdb->m_dateColumnToken, &uint32Value);
00104     Seconds2PRTime(uint32Value, &m_date);
00105     
00106     err = GetUInt32Column(m_mdb->m_messageThreadIdColumnToken, &m_threadId);
00107     err = GetUInt32Column(m_mdb->m_numReferencesColumnToken, &uint32Value);
00108     if (NS_SUCCEEDED(err))
00109       m_numReferences = (PRUint16) uint32Value;
00110     
00111     if (NS_SUCCEEDED(err))
00112       m_initedValues |= CACHED_VALUES_INITED;
00113   }
00114   return err;
00115 }
00116 
00117 nsresult nsMsgHdr::InitFlags()
00118 {
00119   
00120   nsresult err = NS_OK;
00121   
00122   if (!m_mdb)
00123     return NS_ERROR_NULL_POINTER;
00124   
00125   if(!(m_initedValues & FLAGS_INITED))
00126   {
00127     err = GetUInt32Column(m_mdb->m_flagsColumnToken, &m_flags);
00128     m_flags &= ~MSG_FLAG_NEW; // don't get new flag from MDB
00129     
00130     if(NS_SUCCEEDED(err))
00131       m_initedValues |= FLAGS_INITED;
00132   }
00133   
00134   return err;
00135   
00136 }
00137 
00138 nsMsgHdr::~nsMsgHdr()
00139 {
00140   if (m_mdbRow)
00141   {
00142     if (m_mdb)
00143     {  
00144       NS_RELEASE(m_mdbRow);
00145       m_mdb->RemoveHdrFromUseCache((nsIMsgDBHdr *) this, m_messageKey);
00146       m_mdb->Release();
00147     }
00148   }
00149 }
00150 
00151 NS_IMETHODIMP nsMsgHdr::GetMessageKey(nsMsgKey *result)
00152 {
00153   if (m_messageKey == nsMsgKey_None && m_mdbRow != NULL)
00154   {
00155     mdbOid outOid;
00156     if (m_mdbRow->GetOid(m_mdb->GetEnv(), &outOid) == NS_OK)
00157       m_messageKey = outOid.mOid_Id;
00158     
00159   }
00160   *result = m_messageKey;
00161   return NS_OK;
00162 }
00163 
00164 NS_IMETHODIMP nsMsgHdr::GetThreadId(nsMsgKey *result)
00165 {
00166   
00167   if (!(m_initedValues & CACHED_VALUES_INITED))
00168     InitCachedValues();
00169   
00170   if (result)
00171   {
00172     *result = m_threadId;
00173     return NS_OK;
00174   }
00175   return NS_ERROR_NULL_POINTER;
00176 }
00177 
00178 NS_IMETHODIMP nsMsgHdr::SetThreadId(nsMsgKey inKey)
00179 {
00180   m_threadId = inKey;
00181   return SetUInt32Column(m_threadId, m_mdb->m_messageThreadIdColumnToken);
00182 }
00183 
00184 NS_IMETHODIMP nsMsgHdr::SetMessageKey(nsMsgKey value)
00185 {
00186   m_messageKey = value;
00187   return NS_OK;
00188 }
00189 
00190 nsresult nsMsgHdr::GetRawFlags(PRUint32 *result)
00191 {
00192   if (!(m_initedValues & FLAGS_INITED))
00193     InitFlags();
00194   *result = m_flags;
00195   return NS_OK;
00196 }
00197 
00198 NS_IMETHODIMP nsMsgHdr::GetFlags(PRUint32 *result)
00199 {
00200   if (!(m_initedValues & FLAGS_INITED))
00201     InitFlags();
00202   if (m_mdb)
00203     *result = m_mdb->GetStatusFlags(this, m_flags);
00204   else
00205     *result = m_flags;
00206 #ifdef DEBUG_bienvenu
00207   NS_ASSERTION(! (*result & (MSG_FLAG_ELIDED | MSG_FLAG_IGNORED)), "shouldn't be set in db");
00208 #endif
00209   return NS_OK;
00210 }
00211 
00212 NS_IMETHODIMP nsMsgHdr::SetFlags(PRUint32 flags)
00213 {
00214 #ifdef DEBUG_bienvenu
00215   NS_ASSERTION(! (flags & (MSG_FLAG_ELIDED | MSG_FLAG_IGNORED)), "shouldn't set this flag on db");
00216 #endif
00217   m_initedValues |= FLAGS_INITED;
00218   m_flags = flags;
00219   // don't write out MSG_FLAG_NEW to MDB.
00220   return SetUInt32Column(m_flags & ~MSG_FLAG_NEW, m_mdb->m_flagsColumnToken);
00221 }
00222 
00223 NS_IMETHODIMP nsMsgHdr::OrFlags(PRUint32 flags, PRUint32 *result)
00224 {
00225   if (!(m_initedValues & FLAGS_INITED))
00226     InitFlags();
00227   if ((m_flags & flags) != flags)
00228     SetFlags (m_flags | flags);
00229   *result = m_flags;
00230   return NS_OK;
00231 }
00232 
00233 NS_IMETHODIMP nsMsgHdr::AndFlags(PRUint32 flags, PRUint32 *result)
00234 {
00235   if (!(m_initedValues & FLAGS_INITED))
00236     InitFlags();
00237   if ((m_flags & flags) != m_flags)
00238     SetFlags (m_flags & flags);
00239   *result = m_flags;
00240   return NS_OK;
00241 }
00242 
00243 NS_IMETHODIMP nsMsgHdr::MarkHasAttachments(PRBool bHasAttachments)
00244 {
00245   nsresult rv = NS_OK;
00246   
00247   if(m_mdb)
00248   {
00249     nsMsgKey key;
00250     rv = GetMessageKey(&key);
00251     if(NS_SUCCEEDED(rv))
00252       rv = m_mdb->MarkHasAttachments(key, bHasAttachments, nsnull);
00253   }
00254   return rv;
00255 }
00256 
00257 NS_IMETHODIMP nsMsgHdr::MarkRead(PRBool bRead)
00258 {
00259   nsresult rv = NS_OK;
00260   
00261   if(m_mdb)
00262   {
00263     nsMsgKey key;
00264     rv = GetMessageKey(&key);
00265     if(NS_SUCCEEDED(rv))
00266       rv = m_mdb->MarkRead(key, bRead, nsnull);
00267   }
00268   return rv;
00269 }
00270 
00271 NS_IMETHODIMP nsMsgHdr::MarkFlagged(PRBool bFlagged)
00272 {
00273   nsresult rv = NS_OK;
00274   
00275   if(m_mdb)
00276   {
00277     nsMsgKey key;
00278     rv = GetMessageKey(&key);
00279     if(NS_SUCCEEDED(rv))
00280       rv = m_mdb->MarkMarked(key, bFlagged, nsnull);
00281   }
00282   return rv;
00283 }
00284 
00285 NS_IMETHODIMP nsMsgHdr::GetProperty(const char *propertyName, nsAString &resultProperty)
00286 {
00287   return m_mdb->GetPropertyAsNSString(GetMDBRow(), propertyName, resultProperty);
00288 }
00289 
00290 NS_IMETHODIMP nsMsgHdr::SetProperty(const char *propertyName, const nsAString &propertyStr)
00291 {
00292   return m_mdb->SetPropertyFromNSString(m_mdbRow, propertyName, propertyStr);
00293 }
00294 
00295 NS_IMETHODIMP nsMsgHdr::SetStringProperty(const char *propertyName, const char *propertyValue)
00296 {
00297   return m_mdb->SetProperty(m_mdbRow, propertyName, propertyValue);
00298 }
00299 
00300 NS_IMETHODIMP nsMsgHdr::GetStringProperty(const char *propertyName, char **aPropertyValue)
00301 {
00302   return m_mdb->GetProperty(m_mdbRow, propertyName, aPropertyValue);
00303 }
00304 
00305 NS_IMETHODIMP nsMsgHdr::GetUint32Property(const char *propertyName, PRUint32 *pResult)
00306 {
00307   return m_mdb->GetUint32Property(GetMDBRow(), propertyName, pResult);
00308 }
00309 
00310 NS_IMETHODIMP nsMsgHdr::SetUint32Property(const char *propertyName, PRUint32 value)
00311 {
00312   return m_mdb->SetUint32Property(GetMDBRow(), propertyName, value);
00313 }
00314 
00315 
00316 NS_IMETHODIMP nsMsgHdr::GetNumReferences(PRUint16 *result)
00317 {
00318        if (!(m_initedValues & CACHED_VALUES_INITED))
00319               InitCachedValues();
00320 
00321   *result = m_numReferences;
00322        return NS_OK;
00323 }
00324 
00325 nsresult nsMsgHdr::ParseReferences(const char *references)
00326 {
00327        const char *startNextRef = references;
00328        nsCAutoString resultReference;
00329 
00330        while (startNextRef && *startNextRef)
00331        {
00332               startNextRef = GetNextReference(startNextRef, resultReference);
00333               m_references.AppendCString(resultReference);
00334        }
00335   m_numReferences = m_references.Count();
00336        return NS_OK;
00337 }
00338 
00339 NS_IMETHODIMP nsMsgHdr::GetStringReference(PRInt32 refNum, nsACString& resultReference)
00340 {
00341   nsresult err = NS_OK;
00342   
00343   if(!(m_initedValues & REFERENCES_INITED))
00344   {
00345     const char *references;
00346     err = m_mdb->RowCellColumnToConstCharPtr(GetMDBRow(), m_mdb->m_referencesColumnToken, &references);
00347     
00348     if(NS_SUCCEEDED(err))
00349     {
00350       ParseReferences(references);
00351       m_initedValues |= REFERENCES_INITED;
00352     }
00353   }
00354   
00355   if (refNum < m_numReferences)
00356     m_references.CStringAt(refNum, resultReference);
00357   return err;
00358 }
00359 
00360 NS_IMETHODIMP nsMsgHdr::GetDate(PRTime *result) 
00361 {
00362   if (!(m_initedValues & CACHED_VALUES_INITED))
00363     InitCachedValues();
00364   
00365   *result = m_date;
00366   return NS_OK;
00367 }
00368 
00369 NS_IMETHODIMP nsMsgHdr::GetDateInSeconds(PRUint32 *aResult)
00370 {
00371   return GetUInt32Column(m_mdb->m_dateColumnToken, aResult);
00372 }
00373 
00374 NS_IMETHODIMP nsMsgHdr::SetMessageId(const char *messageId)
00375 {
00376   if (messageId && *messageId == '<')
00377   {
00378     nsCAutoString tempMessageID(messageId + 1);
00379     if (tempMessageID.Last() == '>')
00380       tempMessageID.SetLength(tempMessageID.Length() - 1);
00381     return SetStringColumn(tempMessageID.get(), m_mdb->m_messageIdColumnToken);
00382   }
00383   return SetStringColumn(messageId, m_mdb->m_messageIdColumnToken);
00384 }
00385 
00386 NS_IMETHODIMP nsMsgHdr::SetSubject(const char *subject)
00387 {
00388        return SetStringColumn(subject, m_mdb->m_subjectColumnToken);
00389 }
00390 
00391 NS_IMETHODIMP nsMsgHdr::SetAuthor(const char *author)
00392 {
00393        return SetStringColumn(author, m_mdb->m_senderColumnToken);
00394 }
00395 
00396 NS_IMETHODIMP nsMsgHdr::SetReferences(const char *references)
00397 {
00398   if (*references == '\0') {
00399     m_numReferences = 0;
00400   }
00401   else {
00402     ParseReferences(references);
00403   }
00404        
00405   SetUInt32Column(m_numReferences, m_mdb->m_numReferencesColumnToken);
00406   m_initedValues |= REFERENCES_INITED;
00407        
00408   return SetStringColumn(references, m_mdb->m_referencesColumnToken);
00409 }
00410 
00411 NS_IMETHODIMP nsMsgHdr::SetRecipients(const char *recipients)
00412 {
00413        // need to put in rfc822 address parsing code here (or make caller do it...)
00414        return SetStringColumn(recipients, m_mdb->m_recipientsColumnToken);
00415 }
00416 
00417 nsresult nsMsgHdr::BuildRecipientsFromArray(const char *names, const char *addresses, PRUint32 numAddresses, nsCAutoString& allRecipients)
00418 {
00419        nsresult ret = NS_OK;
00420        const char *curName = names;
00421        const char *curAddress = addresses;
00422        nsIMsgHeaderParser *headerParser = m_mdb->GetHeaderParser();
00423 
00424        for (PRUint32 i = 0; i < numAddresses; i++, curName += strlen(curName) + 1, curAddress += strlen(curAddress) + 1)
00425        {
00426               if (i > 0)
00427                      allRecipients += ", ";
00428 
00429               if (headerParser)
00430               {
00431                  char * fullAddress;
00432                  ret = headerParser->MakeFullAddress(nsnull, curName, curAddress, &fullAddress);
00433                  if (NS_SUCCEEDED(ret) && fullAddress)
00434                  {
00435                     allRecipients += fullAddress;
00436                     nsCRT::free(fullAddress);
00437                     continue;
00438                  }
00439               }
00440 
00441         // Just in case the parser failed...
00442               if (strlen(curName))
00443               {
00444                      allRecipients += curName;
00445                      allRecipients += ' ';
00446               }
00447 
00448               if (strlen(curAddress))
00449               {
00450                      allRecipients += '<';
00451                      allRecipients += curAddress;
00452                      allRecipients += '>';
00453               }
00454        }
00455        
00456        return ret;
00457 }
00458 
00459 NS_IMETHODIMP nsMsgHdr::SetRecipientsArray(const char *names, const char *addresses, PRUint32 numAddresses)
00460 {
00461        nsresult ret;
00462        nsCAutoString allRecipients;
00463        
00464     ret = BuildRecipientsFromArray(names, addresses, numAddresses, allRecipients);
00465     if (NS_FAILED(ret))
00466         return ret;
00467 
00468        ret = SetRecipients(allRecipients.get());
00469        return ret;
00470 }
00471 
00472 NS_IMETHODIMP nsMsgHdr::SetCcList(const char *ccList)
00473 {
00474        return SetStringColumn(ccList, m_mdb->m_ccListColumnToken);
00475 }
00476 
00477 // ###should make helper routine that takes column token!
00478 NS_IMETHODIMP nsMsgHdr::SetCCListArray(const char *names, const char *addresses, PRUint32 numAddresses)
00479 {
00480        nsresult ret;
00481        nsCAutoString allRecipients;
00482        
00483     ret = BuildRecipientsFromArray(names, addresses, numAddresses, allRecipients);
00484     if (NS_FAILED(ret))
00485         return ret;
00486 
00487        ret = SetCcList(allRecipients.get());
00488        return ret;
00489 }
00490 
00491 
00492 NS_IMETHODIMP nsMsgHdr::SetMessageSize(PRUint32 messageSize)
00493 {
00494   SetUInt32Column(messageSize, m_mdb->m_messageSizeColumnToken);
00495   m_messageSize = messageSize;
00496   return NS_OK;
00497 }
00498 
00499 NS_IMETHODIMP nsMsgHdr::GetOfflineMessageSize(PRUint32 *result)
00500 {
00501   PRUint32 size;
00502   nsresult res = GetUInt32Column(m_mdb->m_offlineMessageSizeColumnToken, &size);
00503 
00504   *result = size;
00505   return res;
00506 }
00507 
00508 NS_IMETHODIMP nsMsgHdr::SetOfflineMessageSize(PRUint32 messageSize)
00509 {
00510   return SetUInt32Column(messageSize, m_mdb->m_offlineMessageSizeColumnToken);
00511 }
00512 
00513 
00514 NS_IMETHODIMP nsMsgHdr::SetLineCount(PRUint32 lineCount)
00515 {
00516   SetUInt32Column(lineCount, m_mdb->m_numLinesColumnToken);
00517   return NS_OK;
00518 }
00519 
00520 NS_IMETHODIMP nsMsgHdr::SetStatusOffset(PRUint32 statusOffset)
00521 {
00522   return SetUInt32Column(statusOffset, m_mdb->m_statusOffsetColumnToken);
00523 }
00524 
00525 NS_IMETHODIMP nsMsgHdr::SetDate(PRTime date)
00526 {
00527   m_date = date;
00528   PRUint32 seconds;
00529   PRTime2Seconds(date, &seconds);
00530   return SetUInt32Column((PRUint32) seconds, m_mdb->m_dateColumnToken);
00531 }
00532 
00533 NS_IMETHODIMP nsMsgHdr::GetStatusOffset(PRUint32 *result)
00534 {
00535   PRUint32 offset = 0;
00536   nsresult res = GetUInt32Column(m_mdb->m_statusOffsetColumnToken, &offset);
00537 
00538   *result = offset;
00539   return res;
00540 }
00541 
00542 NS_IMETHODIMP nsMsgHdr::SetPriority(nsMsgPriorityValue priority)
00543 {
00544   SetUInt32Column((PRUint32) priority, m_mdb->m_priorityColumnToken);
00545   return NS_OK;
00546 }
00547 
00548 NS_IMETHODIMP nsMsgHdr::GetPriority(nsMsgPriorityValue *result)
00549 {
00550   if (!result)
00551     return NS_ERROR_NULL_POINTER;
00552   
00553   PRUint32 priority = 0;
00554   nsresult rv = GetUInt32Column(m_mdb->m_priorityColumnToken, &priority);
00555   if (NS_FAILED(rv)) return rv;
00556   
00557   *result = (nsMsgPriorityValue) priority;
00558   return NS_OK;
00559 }
00560 
00561 NS_IMETHODIMP nsMsgHdr::SetLabel(nsMsgLabelValue label)
00562 {
00563   SetUInt32Column((PRUint32) label, m_mdb->m_labelColumnToken);
00564   return NS_OK;
00565 }
00566 
00567 NS_IMETHODIMP nsMsgHdr::GetLabel(nsMsgLabelValue *result)
00568 {
00569   NS_ENSURE_ARG_POINTER(result);
00570 
00571   return GetUInt32Column(m_mdb->m_labelColumnToken, result);
00572 }
00573 
00574 // I'd like to not store the account key, if the msg is in
00575 // the same account as it was received in, to save disk space and memory.
00576 // This might be problematic when a message gets moved...
00577 // And I'm not sure if we should short circuit it here,
00578 // or at a higher level where it might be more efficient.
00579 NS_IMETHODIMP nsMsgHdr::SetAccountKey(const char *aAccountKey)
00580 {
00581   return SetStringProperty("account", aAccountKey);
00582 }
00583 
00584 NS_IMETHODIMP nsMsgHdr::GetAccountKey(char **aResult)
00585 {
00586   NS_ENSURE_ARG_POINTER(aResult);
00587 
00588   return GetStringProperty("account", aResult);
00589 }
00590 
00591 
00592 NS_IMETHODIMP nsMsgHdr::GetMessageOffset(PRUint32 *result)
00593 {
00594   NS_ENSURE_ARG(result);
00595 
00596   // if we have the message body offline, then return the message offset column
00597   // (this will only be true for news and imap messages).
00598   PRUint32 rawFlags;
00599   GetRawFlags(&rawFlags);
00600   if (rawFlags & MSG_FLAG_OFFLINE)
00601   {
00602     return GetUInt32Column(m_mdb->m_offlineMsgOffsetColumnToken, result);
00603   }
00604   else
00605   {
00606     *result = m_messageKey;
00607     return NS_OK;
00608   }
00609 }
00610 
00611 NS_IMETHODIMP nsMsgHdr::SetMessageOffset(PRUint32 offset)
00612 {
00613   SetUInt32Column(offset, m_mdb->m_offlineMsgOffsetColumnToken);
00614   return NS_OK;
00615 }
00616 
00617 
00618 NS_IMETHODIMP nsMsgHdr::GetMessageSize(PRUint32 *result)
00619 {
00620   PRUint32 size;
00621   nsresult res = GetUInt32Column(m_mdb->m_messageSizeColumnToken, &size);
00622 
00623   *result = size;
00624   return res;
00625 }
00626 
00627 NS_IMETHODIMP nsMsgHdr::GetLineCount(PRUint32 *result)
00628 {
00629   PRUint32 linecount;
00630   nsresult res = GetUInt32Column(m_mdb->m_numLinesColumnToken, &linecount);
00631   *result = linecount;
00632   return res;
00633 }
00634 
00635 NS_IMETHODIMP nsMsgHdr::SetPriorityString(const char *priority)
00636 {
00637   nsMsgPriorityValue priorityVal = nsMsgPriority::Default;
00638   
00639   // We can ignore |NS_MsgGetPriorityFromString()| return value,
00640   // since we set a default value for |priorityVal|.
00641   NS_MsgGetPriorityFromString(priority, priorityVal);
00642 
00643   return SetPriority(priorityVal);
00644 }
00645 
00646 NS_IMETHODIMP nsMsgHdr::GetAuthor(char* *resultAuthor)
00647 {
00648   return m_mdb->RowCellColumnToCharPtr(GetMDBRow(), m_mdb->m_senderColumnToken, resultAuthor);
00649 }
00650 
00651 NS_IMETHODIMP nsMsgHdr::GetSubject(char* *resultSubject)
00652 {
00653   return m_mdb->RowCellColumnToCharPtr(GetMDBRow(), m_mdb->m_subjectColumnToken, resultSubject);
00654 }
00655 
00656 NS_IMETHODIMP nsMsgHdr::GetRecipients(char* *resultRecipients)
00657 {
00658   return m_mdb->RowCellColumnToCharPtr(GetMDBRow(), m_mdb->m_recipientsColumnToken, resultRecipients);
00659 }
00660 
00661 NS_IMETHODIMP nsMsgHdr::GetCcList(char * *resultCCList)
00662 {
00663   return m_mdb->RowCellColumnToCharPtr(GetMDBRow(), m_mdb->m_ccListColumnToken, resultCCList);
00664 }
00665 
00666 NS_IMETHODIMP nsMsgHdr::GetMessageId(char * *resultMessageId)
00667 {
00668   return m_mdb->RowCellColumnToCharPtr(GetMDBRow(), m_mdb->m_messageIdColumnToken, resultMessageId);
00669 }
00670 
00671 NS_IMETHODIMP nsMsgHdr::GetMime2DecodedAuthor(PRUnichar* *resultAuthor)
00672 {
00673   return m_mdb->RowCellColumnToMime2DecodedString(GetMDBRow(), m_mdb->m_senderColumnToken, resultAuthor);
00674 }
00675 
00676 NS_IMETHODIMP nsMsgHdr::GetMime2DecodedSubject(PRUnichar* *resultSubject)
00677 {
00678   return m_mdb->RowCellColumnToMime2DecodedString(GetMDBRow(), m_mdb->m_subjectColumnToken, resultSubject);
00679 }
00680 
00681 NS_IMETHODIMP nsMsgHdr::GetMime2DecodedRecipients(PRUnichar* *resultRecipients)
00682 {
00683   return m_mdb->RowCellColumnToMime2DecodedString(GetMDBRow(), m_mdb->m_recipientsColumnToken, resultRecipients);
00684 }
00685 
00686 
00687 NS_IMETHODIMP nsMsgHdr::GetAuthorCollationKey(PRUint8 **resultAuthor, PRUint32 *len)
00688 {
00689   return m_mdb->RowCellColumnToAddressCollationKey(GetMDBRow(), m_mdb->m_senderColumnToken, resultAuthor, len);
00690 }
00691 
00692 NS_IMETHODIMP nsMsgHdr::GetSubjectCollationKey(PRUint8 **resultSubject, PRUint32 *len)
00693 {
00694   return m_mdb->RowCellColumnToCollationKey(GetMDBRow(), m_mdb->m_subjectColumnToken, resultSubject, len);
00695 }
00696 
00697 NS_IMETHODIMP nsMsgHdr::GetRecipientsCollationKey(PRUint8 **resultRecipients, PRUint32 *len)
00698 {
00699   return m_mdb->RowCellColumnToCollationKey(GetMDBRow(), m_mdb->m_recipientsColumnToken, resultRecipients, len);
00700 }
00701 
00702 NS_IMETHODIMP nsMsgHdr::GetCharset(char **aCharset)
00703 {
00704   return m_mdb->RowCellColumnToCharPtr(GetMDBRow(), m_mdb->m_messageCharSetColumnToken, aCharset);
00705 }
00706 
00707 NS_IMETHODIMP nsMsgHdr::SetCharset(const char *aCharset)
00708 {
00709   return SetStringColumn(aCharset, m_mdb->m_messageCharSetColumnToken);
00710 }
00711 
00712 NS_IMETHODIMP nsMsgHdr::SetThreadParent(nsMsgKey inKey)
00713 {
00714   m_threadParent = inKey;
00715   SetUInt32Column(m_threadParent, m_mdb->m_threadParentColumnToken);
00716   m_initedValues |= THREAD_PARENT_INITED;
00717   return NS_OK;
00718 }
00719 
00720 NS_IMETHODIMP nsMsgHdr::GetThreadParent(nsMsgKey *result)
00721 {
00722   nsresult res;
00723   if(!(m_initedValues & THREAD_PARENT_INITED))
00724   {
00725     res = GetUInt32Column(m_mdb->m_threadParentColumnToken, &m_threadParent, nsMsgKey_None);
00726     if (NS_SUCCEEDED(res))
00727       m_initedValues |= THREAD_PARENT_INITED;
00728   }
00729   *result = m_threadParent;
00730   return NS_OK;
00731 }
00732 
00733 NS_IMETHODIMP nsMsgHdr::GetFolder(nsIMsgFolder **result)
00734 {
00735   NS_ENSURE_ARG(result);
00736 
00737   if (m_mdb && m_mdb->m_folder)
00738   {
00739     *result = m_mdb->m_folder;
00740     NS_ADDREF(*result);
00741   }
00742   else
00743     *result = nsnull;
00744   return NS_OK;
00745 }
00746 
00747 nsresult nsMsgHdr::SetStringColumn(const char *str, mdb_token token)
00748 {
00749   return m_mdb->CharPtrToRowCellColumn(m_mdbRow, token, str);
00750 }
00751 
00752 nsresult nsMsgHdr::SetUInt32Column(PRUint32 value, mdb_token token)
00753 {
00754   return m_mdb->UInt32ToRowCellColumn(m_mdbRow, token, value);
00755 }
00756 
00757 nsresult nsMsgHdr::GetUInt32Column(mdb_token token, PRUint32 *pvalue, PRUint32 defaultValue)
00758 {
00759   return m_mdb->RowCellColumnToUInt32(GetMDBRow(), token, pvalue, defaultValue);
00760 }
00761 
00762 // get the next <> delimited reference from nextRef and copy it into reference,
00763 const char *nsMsgHdr::GetNextReference(const char *startNextRef, nsCString &reference)
00764 {
00765   const char *ptr = startNextRef;
00766   
00767   reference.Truncate(0);
00768   while ((*ptr == '<' || *ptr == ' ' || *ptr == nsCRT::CR || *ptr == nsCRT::LF || *ptr == '\t') && *ptr)
00769     ptr++;
00770   
00771   for (int i = 0; *ptr && *ptr != '>'; i++)
00772     reference += *ptr++;
00773   
00774   if (*ptr == '>')
00775     ptr++;
00776   return ptr;
00777 }
00778 // Get previous <> delimited reference - used to go backwards through the
00779 // reference string. Caller will need to make sure that prevRef is not before
00780 // the start of the reference string when we return.
00781 const char *nsMsgHdr::GetPrevReference(const char *prevRef, nsCString &reference)
00782 {
00783   const char *ptr = prevRef;
00784   
00785   while ((*ptr == '>' || *ptr == ' ') && *ptr)
00786     ptr--;
00787   
00788   // scan back to '<'
00789   for (int i = 0; *ptr && *ptr != '<' ; i++)
00790     ptr--;
00791   
00792   GetNextReference(ptr, reference);
00793   if (*ptr == '<')
00794     ptr--;
00795   return ptr;
00796 }
00797 
00798 PRBool nsMsgHdr::IsParentOf(nsIMsgDBHdr *possibleChild)
00799 {
00800   PRUint16 referenceToCheck = 0;
00801   possibleChild->GetNumReferences(&referenceToCheck);
00802   nsCAutoString reference;
00803   nsXPIDLCString messageId;
00804   
00805   GetMessageId(getter_Copies(messageId));
00806   while (referenceToCheck > 0)
00807   {
00808     possibleChild->GetStringReference(referenceToCheck - 1, reference);
00809     
00810     if (reference.Equals(messageId))
00811       return PR_TRUE;
00812     // if reference didn't match, check if this ref is for a non-existent
00813     // header. If it is, continue looking at ancestors.
00814     nsCOMPtr <nsIMsgDBHdr> refHdr;
00815     if (!m_mdb)
00816       break;
00817     (void) m_mdb->GetMsgHdrForMessageID(reference.get(), getter_AddRefs(refHdr));
00818     if (refHdr)
00819       break;
00820     referenceToCheck--;
00821   }
00822   return PR_FALSE;
00823 }
00824 
00825 PRBool nsMsgHdr::IsAncestorOf(nsIMsgDBHdr *possibleChild)
00826 {
00827   const char *references;
00828   nsMsgHdr* curHdr = NS_STATIC_CAST(nsMsgHdr*, possibleChild);      // closed system, cast ok
00829   m_mdb->RowCellColumnToConstCharPtr(curHdr->GetMDBRow(), m_mdb->m_referencesColumnToken, &references);
00830   if (!references)
00831     return PR_FALSE;
00832   nsXPIDLCString messageId;
00833   
00834   // should put < > around message id to make strstr strictly match
00835   GetMessageId(getter_Copies(messageId));
00836   return (strstr(references, messageId.get()) != nsnull);
00837 }
00838 
00839 NS_IMETHODIMP nsMsgHdr::GetIsRead(PRBool *isRead)
00840 {
00841     NS_ENSURE_ARG_POINTER(isRead);
00842     if (!(m_initedValues & FLAGS_INITED))
00843       InitFlags();
00844     *isRead = m_flags & MSG_FLAG_READ;
00845     return NS_OK;
00846 }
00847 
00848 NS_IMETHODIMP nsMsgHdr::GetIsFlagged(PRBool *isFlagged)
00849 {
00850     NS_ENSURE_ARG_POINTER(isFlagged);
00851     if (!(m_initedValues & FLAGS_INITED))
00852       InitFlags();
00853     *isFlagged = m_flags & MSG_FLAG_MARKED;
00854     return NS_OK;
00855 }