зеркало из https://github.com/mozilla/pjs.git
work on offline msg support r=sspitzer, sr=mscott 15865
This commit is contained in:
Родитель
db887022c7
Коммит
4a47015644
|
@ -44,6 +44,7 @@ interface nsIMsgFilterList;
|
|||
|
||||
interface nsIMsgFolderCacheElement;
|
||||
interface nsAutoString;
|
||||
interface nsIFileChannel;
|
||||
|
||||
typedef long nsMsgBiffState;
|
||||
// enumerated type for determining if a message has been replied to, forwarded, etc.
|
||||
|
@ -335,6 +336,9 @@ const nsMsgBiffState nsMsgBiffState_Unknown = 2; // We dunno whether there is ne
|
|||
nsIMsgDatabase getMsgDatabase(in nsIMsgWindow msgWindow);
|
||||
nsIMsgDatabase getDBFolderInfoAndDB(out nsIDBFolderInfo folderInfo);
|
||||
|
||||
boolean shouldStoreMsgOffline(in nsMsgKey msgKey);
|
||||
readonly attribute nsIFileChannel offlineFileChannel;
|
||||
|
||||
nsIMsgFolder getChildWithURI(in string uri, in boolean deep);
|
||||
|
||||
/**
|
||||
|
|
|
@ -68,7 +68,7 @@ interface nsIMsgHdr : nsISupports
|
|||
attribute unsigned long messageSize;
|
||||
attribute unsigned long lineCount;
|
||||
attribute unsigned long statusOffset;
|
||||
readonly attribute unsigned long messageOffset;
|
||||
attribute unsigned long messageOffset;
|
||||
|
||||
/* common headers */
|
||||
attribute PRTime date;
|
||||
|
|
|
@ -69,6 +69,8 @@ interface nsIMsgMailNewsUrl : nsIURL {
|
|||
attribute nsIMsgSearchSession searchSession;
|
||||
attribute boolean updatingFolder;
|
||||
attribute boolean addToMemoryCache;
|
||||
attribute boolean msgIsInLocalCache;
|
||||
|
||||
readonly attribute nsICachedNetData memCacheEntry;
|
||||
|
||||
const unsigned long eCopy = 0;
|
||||
|
|
|
@ -449,6 +449,15 @@ NS_IMETHODIMP nsMessage::GetMessageOffset(PRUint32 *result)
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetMessageOffset(PRUint32 offset)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetMessageOffset(offset);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetStatusOffset(PRUint32 *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
|
|
|
@ -33,7 +33,8 @@
|
|||
#include "nsIMsgAccountManager.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsLocalFolderSummarySpec.h"
|
||||
|
||||
#include "nsIFileStream.h"
|
||||
#include "nsIChannel.h"
|
||||
#if defined(XP_OS2)
|
||||
#define MAX_FILE_LENGTH_WITHOUT_EXTENSION 8
|
||||
#elif defined(XP_MAC)
|
||||
|
@ -510,6 +511,88 @@ nsresult nsMsgDBFolder::SendFlagNotifications(nsISupports *item, PRUint32 oldFla
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMsgDBFolder::GetOfflineStoreInputStream(nsIInputStream **stream)
|
||||
{
|
||||
nsresult rv = NS_ERROR_NULL_POINTER;
|
||||
if (mPath)
|
||||
{
|
||||
nsFileSpec pathFileSpec;
|
||||
mPath->GetFileSpec(&pathFileSpec);
|
||||
nsCOMPtr<nsISupports> supports;
|
||||
rv = NS_NewIOFileStream(getter_AddRefs(supports), pathFileSpec, PR_CREATE_FILE, 00700);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = supports->QueryInterface(NS_GET_IID(nsIInputStream), (void**)stream);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::GetOfflineFileChannel(nsIFileChannel **aFileChannel)
|
||||
{
|
||||
NS_ENSURE_ARG(aFileChannel);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
rv = nsComponentManager::CreateInstance(NS_LOCALFILECHANNEL_CONTRACTID, nsnull,
|
||||
NS_GET_IID(nsIFileChannel), (void **) aFileChannel);
|
||||
if (*aFileChannel)
|
||||
{
|
||||
nsXPIDLCString nativePath;
|
||||
mPath->GetNativePath(getter_Copies(nativePath));
|
||||
|
||||
nsCOMPtr <nsILocalFile> localStore;
|
||||
rv = NS_NewLocalFile(nativePath, PR_TRUE, getter_AddRefs(localStore));
|
||||
if (NS_SUCCEEDED(rv) && localStore)
|
||||
{
|
||||
rv = (*aFileChannel)->Init(localStore, PR_CREATE_FILE | PR_RDWR, 0);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMsgDBFolder::GetOfflineStoreOutputStream(nsIOutputStream **outputStream)
|
||||
{
|
||||
nsresult rv = NS_ERROR_NULL_POINTER;
|
||||
if (mPath)
|
||||
{
|
||||
// the following code doesn't work for a host of reasons - the transfer offset
|
||||
// is ignored for output streams. The buffering used by file channels does not work
|
||||
// if transfer offsets are coerced to work, etc.
|
||||
#if 0
|
||||
nsCOMPtr<nsIFileChannel> fileChannel = do_CreateInstance(NS_LOCALFILECHANNEL_CONTRACTID);
|
||||
if (fileChannel)
|
||||
{
|
||||
PRUint32 fileSize = 0;
|
||||
nsXPIDLCString nativePath;
|
||||
mPath->GetNativePath(getter_Copies(nativePath));
|
||||
|
||||
mPath->GetFileSize(&fileSize);
|
||||
nsCOMPtr <nsILocalFile> localStore;
|
||||
rv = NS_NewLocalFile(nativePath, PR_TRUE, getter_AddRefs(localStore));
|
||||
if (NS_SUCCEEDED(rv) && localStore)
|
||||
{
|
||||
rv = fileChannel->Init(localStore, PR_CREATE_FILE | PR_RDWR, 0);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
fileChannel->SetTransferOffset(fileSize);
|
||||
rv = fileChannel->OpenOutputStream(outputStream);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
nsCOMPtr<nsISupports> supports;
|
||||
nsFileSpec fileSpec;
|
||||
mPath->GetFileSpec(&fileSpec);
|
||||
rv = NS_NewIOFileStream(getter_AddRefs(supports), fileSpec, PR_WRONLY | PR_CREATE_FILE, 00700);
|
||||
supports->QueryInterface(NS_GET_IID(nsIOutputStream), (void **) outputStream);
|
||||
|
||||
nsCOMPtr <nsIRandomAccessStore> randomStore = do_QueryInterface(supports);
|
||||
if (randomStore)
|
||||
randomStore->Seek(PR_SEEK_END, 0);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
// path coming in is the root path without the leaf name,
|
||||
// on the way out, it's the whole path.
|
||||
nsresult nsMsgDBFolder::CreatePlatformLeafNameForDisk(const char *userLeafName, nsFileSpec &path, char **resultName)
|
||||
|
@ -789,6 +872,38 @@ NS_IMETHODIMP nsMsgDBFolder::ManyHeadersToDownload(PRBool *retval)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::ShouldStoreMsgOffline(nsMsgKey msgKey, PRBool *result)
|
||||
{
|
||||
NS_ENSURE_ARG(result);
|
||||
PRUint32 flags = 0;
|
||||
*result = PR_FALSE;
|
||||
GetFlags(&flags);
|
||||
|
||||
if (flags & MSG_FOLDER_FLAG_OFFLINE)
|
||||
{
|
||||
if(!mDatabase)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIMsgDBHdr> hdr;
|
||||
rv = mDatabase->GetMsgHdrForKey(msgKey, getter_AddRefs(hdr));
|
||||
if(NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if (hdr)
|
||||
{
|
||||
PRUint32 msgFlags = 0;
|
||||
|
||||
hdr->GetFlags(&msgFlags);
|
||||
// check if we already have this message body offline
|
||||
// should also check against size limit when we have that.
|
||||
if (! (msgFlags & MSG_FLAG_OFFLINE))
|
||||
*result = PR_TRUE;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::GetFlags(PRUint32 *_retval)
|
||||
{
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "nsCOMPtr.h"
|
||||
#include "nsIDBChangeListener.h"
|
||||
#include "nsIUrlListener.h"
|
||||
#include "nsIMsgHdr.h"
|
||||
|
||||
class nsIMsgFolderCacheElement;
|
||||
|
||||
|
@ -86,6 +87,9 @@ public:
|
|||
NS_IMETHOD GetGettingNewMessages(PRBool *gettingNewMessages);
|
||||
NS_IMETHOD SetGettingNewMessages(PRBool gettingNewMessages);
|
||||
|
||||
NS_IMETHOD ShouldStoreMsgOffline(nsMsgKey msgKey, PRBool *result);
|
||||
NS_IMETHOD GetOfflineFileChannel(nsIFileChannel **aFileChannel);
|
||||
|
||||
protected:
|
||||
virtual nsresult ReadDBFolderInfo(PRBool force);
|
||||
virtual nsresult FlushToFolderCache();
|
||||
|
@ -99,6 +103,10 @@ protected:
|
|||
nsresult GetFolderCacheKey(nsIFileSpec **aFileSpec);
|
||||
nsresult GetFolderCacheElemFromFileSpec(nsIFileSpec *fileSpec, nsIMsgFolderCacheElement **cacheElement);
|
||||
nsresult NotifyStoreClosedAllHeaders();
|
||||
|
||||
virtual nsresult GetOfflineStoreInputStream(nsIInputStream **inputStream);
|
||||
virtual nsresult GetOfflineStoreOutputStream(nsIOutputStream **outputStream);
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIMsgDatabase> mDatabase;
|
||||
nsString mCharset;
|
||||
|
@ -106,6 +114,8 @@ protected:
|
|||
PRBool mNewMessages;
|
||||
PRBool mGettingNewMessages;
|
||||
|
||||
nsCOMPtr <nsIMsgDBHdr> m_offlineHeader;
|
||||
|
||||
static nsIAtom* mFolderLoadedAtom;
|
||||
static nsIAtom* mDeleteOrMoveMsgCompletedAtom;
|
||||
static nsIAtom* mDeleteOrMoveMsgFailedAtom;
|
||||
|
|
|
@ -50,6 +50,7 @@ nsMsgMailNewsUrl::nsMsgMailNewsUrl()
|
|||
m_runningUrl = PR_FALSE;
|
||||
m_updatingFolder = PR_FALSE;
|
||||
m_addContentToCache = PR_FALSE;
|
||||
m_msgIsInLocalCache = PR_FALSE;
|
||||
|
||||
nsComponentManager::CreateInstance(kUrlListenerManagerCID, nsnull, NS_GET_IID(nsIUrlListenerManager), (void **) getter_AddRefs(m_urlListeners));
|
||||
nsComponentManager::CreateInstance(kStandardUrlCID, nsnull, NS_GET_IID(nsIURL), (void **) getter_AddRefs(m_baseURL));
|
||||
|
@ -320,6 +321,19 @@ NS_IMETHODIMP nsMsgMailNewsUrl::SetAddToMemoryCache(PRBool aAddToCache)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetMsgIsInLocalCache(PRBool *aMsgIsInLocalCache)
|
||||
{
|
||||
NS_ENSURE_ARG(aMsgIsInLocalCache);
|
||||
*aMsgIsInLocalCache = m_msgIsInLocalCache;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetMsgIsInLocalCache(PRBool aMsgIsInLocalCache)
|
||||
{
|
||||
m_msgIsInLocalCache = aMsgIsInLocalCache;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::IsUrlType(PRUint32 type, PRBool *isType)
|
||||
{
|
||||
//base class doesn't know about any specific types
|
||||
|
|
|
@ -69,6 +69,7 @@ protected:
|
|||
PRBool m_runningUrl;
|
||||
PRBool m_updatingFolder;
|
||||
PRBool m_addContentToCache;
|
||||
PRBool m_msgIsInLocalCache;
|
||||
|
||||
// the following field is really a bit of a hack to make
|
||||
// open attachments work. The external applications code sometimes trys to figure out the right
|
||||
|
|
|
@ -345,6 +345,7 @@ protected:
|
|||
mdb_token m_messageCharSetColumnToken;
|
||||
mdb_token m_threadParentColumnToken;
|
||||
mdb_token m_threadRootKeyColumnToken;
|
||||
mdb_token m_offlineMsgOffsetColumnToken;
|
||||
nsIMsgHeaderParser *m_HeaderParser;
|
||||
|
||||
// header caching stuff - MRU headers, keeps them around in memory
|
||||
|
|
|
@ -620,6 +620,7 @@ nsMsgDatabase::nsMsgDatabase()
|
|||
m_messageCharSetColumnToken(0),
|
||||
m_threadParentColumnToken(0),
|
||||
m_threadRootKeyColumnToken(0),
|
||||
m_offlineMsgOffsetColumnToken(0),
|
||||
m_HeaderParser(nsnull),
|
||||
m_cachedHeaders(nsnull),
|
||||
m_headersInUse(nsnull),
|
||||
|
@ -1100,6 +1101,8 @@ const char *kThreadSubjectColumnName = "threadSubject";
|
|||
const char *kMessageCharSetColumnName = "msgCharSet";
|
||||
const char *kThreadParentColumnName = "threadParent";
|
||||
const char *kThreadRootColumnName = "threadRoot";
|
||||
const char *kOfflineMsgOffsetColumnName = "msgOffset";
|
||||
|
||||
struct mdbOid gAllMsgHdrsTableOID;
|
||||
struct mdbOid gAllThreadsTableOID;
|
||||
|
||||
|
@ -1213,6 +1216,7 @@ nsresult nsMsgDatabase::InitMDBInfo()
|
|||
err = GetStore()->StringToToken(GetEnv(), kThreadHdrsScope, &m_threadRowScopeToken);
|
||||
err = GetStore()->StringToToken(GetEnv(), kThreadParentColumnName, &m_threadParentColumnToken);
|
||||
err = GetStore()->StringToToken(GetEnv(), kThreadRootColumnName, &m_threadRootKeyColumnToken);
|
||||
err = GetStore()->StringToToken(GetEnv(), kOfflineMsgOffsetColumnName, &m_offlineMsgOffsetColumnToken);
|
||||
if (err == NS_OK)
|
||||
{
|
||||
// The table of all message hdrs will have table id 1.
|
||||
|
|
|
@ -532,10 +532,31 @@ NS_IMETHODIMP nsMsgHdr::GetPriority(nsMsgPriorityValue *result)
|
|||
|
||||
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)
|
||||
{
|
||||
|
||||
nsresult rv = SetUInt32Column(m_mdb->m_offlineMsgOffsetColumnToken, offset);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMsgHdr::GetMessageSize(PRUint32 *result)
|
||||
{
|
||||
PRUint32 size;
|
||||
|
@ -547,10 +568,10 @@ NS_IMETHODIMP nsMsgHdr::GetMessageSize(PRUint32 *result)
|
|||
|
||||
NS_IMETHODIMP nsMsgHdr::GetLineCount(PRUint32 *result)
|
||||
{
|
||||
PRUint32 linecount;
|
||||
nsresult res = GetUInt32Column(m_mdb->m_numLinesColumnToken, &linecount);
|
||||
*result = linecount;
|
||||
return res;
|
||||
PRUint32 linecount;
|
||||
nsresult res = GetUInt32Column(m_mdb->m_numLinesColumnToken, &linecount);
|
||||
*result = linecount;
|
||||
return res;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgHdr::SetPriorityString(const char *priority)
|
||||
|
|
|
@ -38,7 +38,10 @@ interface nsIImapMessageSink : nsISupports {
|
|||
void NormalEndMsgWriteStream(in nsMsgKey uidOfMessage, in boolean markMsgRead);
|
||||
|
||||
void AbortMsgWriteStream();
|
||||
|
||||
|
||||
attribute boolean notifyDownloadedLines; // imap protocol doesn't notify message sink of downloaded
|
||||
// lines when it has a channelListener. This forces it to,
|
||||
// even if there is a channel listener.
|
||||
// message move/copy related methods
|
||||
// void OnlineCopyReport(in ImapOnlineCopyState aCopyState);
|
||||
void BeginMessageUpload();
|
||||
|
|
|
@ -98,7 +98,8 @@ nsImapMailFolder::nsImapMailFolder() :
|
|||
m_explicitlyVerify(PR_FALSE),
|
||||
m_folderNeedsSubscribing(PR_FALSE),
|
||||
m_folderNeedsAdded(PR_FALSE),
|
||||
m_folderNeedsACLListed(PR_TRUE)
|
||||
m_folderNeedsACLListed(PR_TRUE),
|
||||
m_downloadMessageForOfflineUse(PR_FALSE)
|
||||
{
|
||||
m_appendMsgMonitor = nsnull; // since we're not using this (yet?) make it null.
|
||||
// if we do start using it, it should be created lazily
|
||||
|
@ -2939,17 +2940,92 @@ nsImapMailFolder::SetupMsgWriteStream(const char * aNativeString, PRBool addDumm
|
|||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImapMailFolder::GetNotifyDownloadedLines(PRBool *notifyDownloadedLines)
|
||||
{
|
||||
NS_ENSURE_ARG(notifyDownloadedLines);
|
||||
*notifyDownloadedLines = m_downloadMessageForOfflineUse;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImapMailFolder::SetNotifyDownloadedLines(PRBool notifyDownloadedLines)
|
||||
{
|
||||
m_downloadMessageForOfflineUse = notifyDownloadedLines;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsImapMailFolder::StartNewOfflineMessage()
|
||||
{
|
||||
nsresult rv = GetOfflineStoreOutputStream(getter_AddRefs(m_tempMessageStream));
|
||||
PRUint32 statusOffset;
|
||||
WriteStartOfNewLocalMessage();
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsImapMailFolder::WriteStartOfNewLocalMessage()
|
||||
{
|
||||
nsCAutoString result;
|
||||
char *ct;
|
||||
PRUint32 writeCount;
|
||||
time_t now = time ((time_t*) 0);
|
||||
ct = ctime(&now);
|
||||
ct[24] = 0;
|
||||
result = "From - ";
|
||||
result += ct;
|
||||
result += MSG_LINEBREAK;
|
||||
|
||||
nsCOMPtr <nsIRandomAccessStore> randomStore;
|
||||
PRInt32 curStorePos;
|
||||
|
||||
if (m_offlineHeader)
|
||||
randomStore = do_QueryInterface(m_tempMessageStream);
|
||||
|
||||
if (randomStore)
|
||||
{
|
||||
randomStore->Tell(&curStorePos);
|
||||
m_offlineHeader->SetMessageOffset(curStorePos);
|
||||
}
|
||||
m_tempMessageStream->Write(result.GetBuffer(), result.Length(),
|
||||
&writeCount);
|
||||
if (randomStore)
|
||||
{
|
||||
randomStore->Tell(&curStorePos);
|
||||
m_offlineHeader->SetStatusOffset(curStorePos);
|
||||
}
|
||||
|
||||
result = "X-Mozilla-Status: 0001";
|
||||
result += MSG_LINEBREAK;
|
||||
m_tempMessageStream->Write(result.GetBuffer(), result.Length(),
|
||||
&writeCount);
|
||||
result = "X-Mozilla-Status2: 00000000";
|
||||
result += MSG_LINEBREAK;
|
||||
nsresult rv = m_tempMessageStream->Write(result.GetBuffer(), result.Length(),
|
||||
&writeCount);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImapMailFolder::ParseAdoptedMsgLine(const char *adoptedMessageLine, nsMsgKey uidOfMessage)
|
||||
{
|
||||
PRUint32 count = 0;
|
||||
nsresult rv = NS_OK;
|
||||
// remember the uid of the message we're downloading.
|
||||
m_curMsgUid = uidOfMessage;
|
||||
if (m_downloadMessageForOfflineUse && !m_tempMessageStream)
|
||||
{
|
||||
GetMessageHeader(uidOfMessage, getter_AddRefs(m_offlineHeader));
|
||||
rv = StartNewOfflineMessage();
|
||||
}
|
||||
|
||||
if (m_tempMessageStream)
|
||||
m_tempMessageStream->Write(adoptedMessageLine,
|
||||
{
|
||||
rv = m_tempMessageStream->Write(adoptedMessageLine,
|
||||
PL_strlen(adoptedMessageLine), &count);
|
||||
|
||||
return NS_OK;
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to write to stream");
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -2957,8 +3033,18 @@ nsImapMailFolder::NormalEndMsgWriteStream(nsMsgKey uidOfMessage, PRBool markRead
|
|||
{
|
||||
nsresult res = NS_OK;
|
||||
if (m_tempMessageStream)
|
||||
{
|
||||
m_tempMessageStream->Close();
|
||||
m_tempMessageStream = nsnull;
|
||||
}
|
||||
|
||||
if (m_offlineHeader)
|
||||
{
|
||||
PRUint32 newFlags;
|
||||
|
||||
m_offlineHeader->OrFlags(MSG_FLAG_OFFLINE, &newFlags);
|
||||
m_offlineHeader = nsnull;
|
||||
}
|
||||
if (markRead)
|
||||
{
|
||||
nsCOMPtr<nsIMsgDBHdr> msgHdr;
|
||||
|
@ -3863,15 +3949,16 @@ NS_IMETHODIMP nsImapMailFolder::GetPath(nsIFileSpec ** aPathName)
|
|||
|
||||
NS_IMETHODIMP nsImapMailFolder::SetPath(nsIFileSpec * aPathName)
|
||||
{
|
||||
if (!aPathName)
|
||||
nsMsgFolder::SetPath(aPathName); // call base class so mPath will get set too
|
||||
if (!aPathName)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// not sure why imap has m_pathName and doesn't just use mPath.
|
||||
if (!m_pathName)
|
||||
{
|
||||
m_pathName = new nsFileSpec("");
|
||||
m_pathName = new nsFileSpec("");
|
||||
if (! m_pathName)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
return aPathName->GetFileSpec(m_pathName);
|
||||
}
|
||||
|
|
|
@ -319,6 +319,9 @@ protected:
|
|||
|
||||
virtual nsresult CreateBaseMessageURI(const char *aURI);
|
||||
|
||||
// offline support methods.
|
||||
nsresult StartNewOfflineMessage();
|
||||
nsresult WriteStartOfNewLocalMessage();
|
||||
|
||||
PRBool m_initialized;
|
||||
PRBool m_haveDiscoveredAllFolders;
|
||||
|
@ -332,8 +335,7 @@ protected:
|
|||
nsCOMPtr<nsIEventQueue> m_eventQueue;
|
||||
PRBool m_urlRunning;
|
||||
|
||||
// part of temporary libmime converstion trick......these should go away once MIME uses a new stream
|
||||
// converter interface...
|
||||
// this is currently used when we do a save as of an imap message..
|
||||
nsCOMPtr<nsIOutputStream> m_tempMessageStream;
|
||||
|
||||
// *** jt - undo move/copy trasaction support
|
||||
|
@ -353,6 +355,9 @@ protected:
|
|||
PRBool m_folderNeedsACLListed;
|
||||
|
||||
nsCOMPtr<nsIMsgMailNewsUrl> mUrlToRelease;
|
||||
|
||||
// offline imap support
|
||||
PRBool m_downloadMessageForOfflineUse;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -852,9 +852,7 @@ nsImapProtocol::PseudoInterruptMsgLoad(nsIImapUrl *aImapUrl, PRBool *interrupted
|
|||
if (imapAction == nsIImapUrl::nsImapMsgFetch)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIMsgFolder> folder;
|
||||
nsCOMPtr<nsIImapUrl> runningImapURL;
|
||||
nsXPIDLCString msgKey;
|
||||
|
||||
rv = GetRunningImapURL(getter_AddRefs(runningImapURL));
|
||||
if (NS_SUCCEEDED(rv) && runningImapURL)
|
||||
|
@ -2769,23 +2767,30 @@ nsImapProtocol::PostLineDownLoadEvent(msg_line_info *downloadLineDontDelete)
|
|||
}
|
||||
}
|
||||
|
||||
// if we have a channel listener, then just spool the message
|
||||
// directory to the listener
|
||||
else if (m_channelListener)
|
||||
else
|
||||
{
|
||||
PRUint32 count = 0;
|
||||
char * line = downloadLineDontDelete->adoptedMessageLine;
|
||||
if (m_channelOutputStream)
|
||||
PRBool echoLineToMessageSink = PR_TRUE;
|
||||
// if we have a channel listener, then just spool the message
|
||||
// directory to the listener
|
||||
if (m_channelListener)
|
||||
{
|
||||
nsresult rv = m_channelOutputStream->Write(line, PL_strlen(line), &count);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
m_channelListener->OnDataAvailable(m_mockChannel, m_channelContext, m_channelInputStream, 0, count);
|
||||
PRUint32 count = 0;
|
||||
char * line = downloadLineDontDelete->adoptedMessageLine;
|
||||
if (m_channelOutputStream)
|
||||
{
|
||||
nsresult rv = m_channelOutputStream->Write(line, PL_strlen(line), &count);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
m_channelListener->OnDataAvailable(m_mockChannel, m_channelContext, m_channelInputStream, 0, count);
|
||||
// here is where we should echo the line to the local folder copy of an online message
|
||||
}
|
||||
if (m_imapMessageSink)
|
||||
m_imapMessageSink->GetNotifyDownloadedLines(&echoLineToMessageSink);
|
||||
}
|
||||
if (m_imapMessageSink && downloadLineDontDelete && echoLineToMessageSink)
|
||||
{
|
||||
m_imapMessageSink->ParseAdoptedMsgLine(downloadLineDontDelete->adoptedMessageLine,
|
||||
downloadLineDontDelete->uidOfMessage);
|
||||
}
|
||||
}
|
||||
else if (m_imapMessageSink && downloadLineDontDelete)
|
||||
{
|
||||
m_imapMessageSink->ParseAdoptedMsgLine(downloadLineDontDelete->adoptedMessageLine,
|
||||
downloadLineDontDelete->uidOfMessage);
|
||||
}
|
||||
// ***** We need to handle the psuedo interrupt here *****
|
||||
}
|
||||
|
@ -4312,28 +4317,39 @@ void nsImapProtocol::Language()
|
|||
}
|
||||
}
|
||||
|
||||
void nsImapProtocol::EscapeUserNamePasswordString(const char *strToEscape, nsCString *resultStr)
|
||||
{
|
||||
if (strToEscape)
|
||||
{
|
||||
PRUint32 i = 0;
|
||||
PRUint32 escapeStrlen = nsCRT::strlen(strToEscape);
|
||||
for (i=0; i<escapeStrlen; i++)
|
||||
{
|
||||
if (strToEscape[i] == '\\' || strToEscape[i] == '\"')
|
||||
{
|
||||
resultStr->Append('\\');
|
||||
}
|
||||
resultStr->Append(strToEscape[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nsImapProtocol::InsecureLogin(const char *userName, const char *password)
|
||||
{
|
||||
|
||||
ProgressEventFunctionUsingId (IMAP_STATUS_SENDING_LOGIN);
|
||||
IncrementCommandTagNumber();
|
||||
nsCString command (GetServerCommandTag());
|
||||
nsCAutoString escapedUserName;
|
||||
command.Append(" login \"");
|
||||
command.Append(userName);
|
||||
EscapeUserNamePasswordString(userName, &escapedUserName);
|
||||
command.Append((const char *) escapedUserName);
|
||||
command.Append("\" \"");
|
||||
|
||||
// if the password contains a \, login will fail
|
||||
// turn foo\bar into foo\\bar
|
||||
nsCString correctedPassword;
|
||||
if (password) {
|
||||
PRUint32 i = 0;
|
||||
for (i=0;i<nsCRT::strlen(password);i++) {
|
||||
if (password[i] == '\\') {
|
||||
correctedPassword += '\\';
|
||||
}
|
||||
correctedPassword += password[i];
|
||||
}
|
||||
}
|
||||
nsCAutoString correctedPassword;
|
||||
EscapeUserNamePasswordString(password, &correctedPassword);
|
||||
command.Append((const char *)correctedPassword);
|
||||
command.Append("\""CRLF);
|
||||
|
||||
|
@ -6892,6 +6908,42 @@ NS_IMETHODIMP nsImapMockChannel::AsyncRead(nsIStreamListener *listener, nsISuppo
|
|||
}
|
||||
}
|
||||
|
||||
// check if msg is in local cache.
|
||||
PRBool useLocalCache = PR_FALSE;
|
||||
mailnewsUrl->GetMsgIsInLocalCache(&useLocalCache);
|
||||
if (useLocalCache)
|
||||
{
|
||||
// we want to create a file channel and read the msg from there.
|
||||
nsCOMPtr<nsIChannel> fileChannel;
|
||||
// get the file channel from the folder, somehow (through the message or
|
||||
// folder sync?
|
||||
if (fileChannel && NS_SUCCEEDED(rv))
|
||||
{
|
||||
fileChannel->SetLoadGroup(m_loadGroup);
|
||||
// turn around and make our ref on m_url an owning ref...and force the url to remove
|
||||
// its reference on the mock channel...this is a complicated texas two step to solve
|
||||
// a nasty reference counting problem...
|
||||
NS_IF_ADDREF(m_url);
|
||||
mOwningRefToUrl = PR_TRUE;
|
||||
imapUrl->SetMockChannel(nsnull);
|
||||
|
||||
// if we are going to read from the cache, then create a mock stream listener class and use it
|
||||
nsImapCacheStreamListener * cacheListener = new nsImapCacheStreamListener();
|
||||
NS_ADDREF(cacheListener);
|
||||
cacheListener->Init(m_channelListener, NS_STATIC_CAST(nsIChannel *, this));
|
||||
rv = fileChannel->AsyncRead(cacheListener, m_channelContext);
|
||||
NS_RELEASE(cacheListener);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) // ONLY if we succeeded in actually starting the read should we return
|
||||
{
|
||||
// if the msg is unread, we should mark it read on the server. This lets
|
||||
// the code running this url we're loading from the cache, if it cares.
|
||||
imapUrl->SetMsgLoadingFromCache(PR_TRUE);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// okay, add the mock channel to the load group..
|
||||
imapUrl->AddChannelToLoadGroup();
|
||||
// loading the url consists of asking the server to add the url to it's imap event queue....
|
||||
|
|
|
@ -152,6 +152,9 @@ public:
|
|||
PRUint32 CountMessagesInIdString(const char *idString);
|
||||
static PRBool HandlingMultipleMessages(const char *messageIdString);
|
||||
|
||||
// escape slashes and double quotes in username/passwords for insecure login.
|
||||
static void EscapeUserNamePasswordString(const char *strToEscape, nsCString *resultStr);
|
||||
|
||||
// used to start fetching a message.
|
||||
PRBool GetShouldDownloadArbitraryHeaders();
|
||||
char *GetArbitraryHeadersToDownload();
|
||||
|
|
|
@ -437,6 +437,14 @@ NS_IMETHODIMP nsImapService::DisplayMessage(const char* aMessageURI,
|
|||
|
||||
PRUint32 messageSize;
|
||||
PRBool useMimePartsOnDemand = gMIMEOnDemand;
|
||||
PRBool shouldStoreMsgOffline = PR_FALSE;
|
||||
|
||||
if (folder)
|
||||
folder->ShouldStoreMsgOffline(key, &shouldStoreMsgOffline);
|
||||
|
||||
if (imapMessageSink)
|
||||
imapMessageSink->SetNotifyDownloadedLines(shouldStoreMsgOffline);
|
||||
|
||||
nsCOMPtr<nsIMsgIncomingServer> aMsgIncomingServer;
|
||||
|
||||
if (imapMessageSink)
|
||||
|
|
Загрузка…
Ссылка в новой задаче