work on offline msg support r=sspitzer, sr=mscott 15865

This commit is contained in:
bienvenu%netscape.com 2000-12-06 19:35:43 +00:00
Родитель db887022c7
Коммит 4a47015644
17 изменённых файлов: 383 добавлений и 44 удалений

Просмотреть файл

@ -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)