mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-02 20:20:00 +00:00
fix 169271 when displaying an imap message with parts, and falling back to fetching the whole msg because the parts are inline, store the msg for offline use if we would have stored it for offline use but for the parts, sr=mscott
This commit is contained in:
parent
aa21b1c3e4
commit
688a4e589c
@ -105,7 +105,6 @@ interface nsIImapIncomingServer : nsISupports {
|
||||
in boolean forceAllFolders,
|
||||
in boolean performingBiff);
|
||||
attribute boolean doingLsub;
|
||||
|
||||
void allowFolderConversion(out boolean allowConversion);
|
||||
void convertFolderName(in string originalName, out wstring convertedName);
|
||||
void hideFolderName(in string originalName, out boolean hideFolder);
|
||||
|
@ -113,7 +113,8 @@ interface nsIImapUrl : nsISupports
|
||||
attribute nsISupports copyState;
|
||||
attribute nsIFileSpec msgFileSpec;
|
||||
attribute nsIImapMockChannel mockChannel;
|
||||
|
||||
attribute boolean shouldStoreMsgOffline; // set to true if we should store the msg for offline use if we can,
|
||||
// i.e., we're not doing mime parts on demand.
|
||||
void addChannelToLoadGroup();
|
||||
void removeChannel(in nsresult aStatus);
|
||||
|
||||
|
@ -274,7 +274,7 @@ PRInt32 nsIMAPBodyShell::Generate(char *partNum)
|
||||
PRUint32 messageSize = m_protocolConnection->GetMessageSize(GetUID().get(), PR_TRUE);
|
||||
m_protocolConnection->SetContentModified(IMAP_CONTENT_NOT_MODIFIED); // So that when we cache it, we know we have the whole message
|
||||
if (!DeathSignalReceived())
|
||||
m_protocolConnection->FetchTryChunking(GetUID().get(), kEveryThingRFC822, PR_TRUE, NULL, messageSize, PR_TRUE);
|
||||
m_protocolConnection->FallbackToFetchWholeMsg(GetUID().get(), messageSize);
|
||||
contentLength = (PRInt32) messageSize; // ugh
|
||||
}
|
||||
else
|
||||
|
@ -713,24 +713,24 @@ NS_IMETHODIMP nsIMAPHostSessionList::FlushUncommittedNamespacesForHost(const cha
|
||||
// Returns NULL if there is no personal namespace on the given host
|
||||
NS_IMETHODIMP nsIMAPHostSessionList::GetOnlineInboxPathForHost(const char *serverKey, nsString &result)
|
||||
{
|
||||
PR_EnterMonitor(gCachedHostInfoMonitor);
|
||||
nsIMAPHostInfo *host = FindHost(serverKey);
|
||||
if (host)
|
||||
{
|
||||
nsIMAPNamespace *ns = NULL;
|
||||
ns = host->fNamespaceList->GetDefaultNamespaceOfType(kPersonalNamespace);
|
||||
if (ns)
|
||||
{
|
||||
result.AssignWithConversion(ns->GetPrefix());
|
||||
result.Append(NS_LITERAL_STRING("INBOX"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.SetLength(0);
|
||||
}
|
||||
PR_ExitMonitor(gCachedHostInfoMonitor);
|
||||
return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
|
||||
PR_EnterMonitor(gCachedHostInfoMonitor);
|
||||
nsIMAPHostInfo *host = FindHost(serverKey);
|
||||
if (host)
|
||||
{
|
||||
nsIMAPNamespace *ns = NULL;
|
||||
ns = host->fNamespaceList->GetDefaultNamespaceOfType(kPersonalNamespace);
|
||||
if (ns)
|
||||
{
|
||||
result.AssignWithConversion(ns->GetPrefix());
|
||||
result.Append(NS_LITERAL_STRING("INBOX"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.SetLength(0);
|
||||
}
|
||||
PR_ExitMonitor(gCachedHostInfoMonitor);
|
||||
return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsIMAPHostSessionList::GetShouldAlwaysListInboxForHost(const char* /*serverKey*/, PRBool &result)
|
||||
|
@ -2751,6 +2751,18 @@ void nsImapProtocol::FetchMsgAttribute(const char * messageIds, const char *attr
|
||||
// this routine is used to fetch a message or messages, or headers for a
|
||||
// message...
|
||||
|
||||
void nsImapProtocol::FallbackToFetchWholeMsg(const char *messageId, PRUint32 messageSize)
|
||||
{
|
||||
if (m_imapMessageSink && m_runningUrl)
|
||||
{
|
||||
PRBool shouldStoreMsgOffline;
|
||||
m_runningUrl->GetShouldStoreMsgOffline(&shouldStoreMsgOffline);
|
||||
if (shouldStoreMsgOffline)
|
||||
m_imapMessageSink->SetNotifyDownloadedLines(PR_TRUE);
|
||||
}
|
||||
FetchTryChunking(messageId, kEveryThingRFC822, PR_TRUE, NULL, messageSize, PR_TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
nsImapProtocol::FetchMessage(const char * messageIds,
|
||||
nsIMAPeFetchFields whatToFetch,
|
||||
|
@ -231,6 +231,7 @@ public:
|
||||
PRUint32 downloadSize,
|
||||
PRBool tryChunking);
|
||||
virtual void PipelinedFetchMessageParts(nsCString &uid, nsIMAPMessagePartIDArray *parts);
|
||||
void FallbackToFetchWholeMsg(const char *messageId, PRUint32 messageSize);
|
||||
|
||||
// used when streaming a message fetch
|
||||
virtual nsresult BeginMessageDownLoad(PRUint32 totalSize, // for user, headers and body
|
||||
|
@ -182,7 +182,7 @@ void nsImapServerResponseParser::IncrementNumberOfTaggedResponsesExpected(const
|
||||
void nsImapServerResponseParser::InitializeState()
|
||||
{
|
||||
fProcessingTaggedResponse = PR_FALSE;
|
||||
fCurrentCommandFailed = PR_FALSE;
|
||||
fCurrentCommandFailed = PR_FALSE;
|
||||
}
|
||||
|
||||
void nsImapServerResponseParser::ParseIMAPServerResponse(const char *currentCommand, PRBool aIgnoreBadAndNOResponses)
|
||||
@ -2461,10 +2461,10 @@ void nsImapServerResponseParser::acl_data()
|
||||
|
||||
void nsImapServerResponseParser::mime_data()
|
||||
{
|
||||
if (PL_strstr(fNextToken, "MIME"))
|
||||
mime_header_data();
|
||||
else
|
||||
mime_part_data();
|
||||
if (PL_strstr(fNextToken, "MIME"))
|
||||
mime_header_data();
|
||||
else
|
||||
mime_part_data();
|
||||
}
|
||||
|
||||
// mime_header_data should not be streamed out; rather, it should be
|
||||
@ -2474,103 +2474,103 @@ void nsImapServerResponseParser::mime_data()
|
||||
// we can construct the final output stream.
|
||||
void nsImapServerResponseParser::mime_header_data()
|
||||
{
|
||||
char *partNumber = PL_strdup(fNextToken);
|
||||
if (partNumber)
|
||||
{
|
||||
char *start = partNumber+5, *end = partNumber+5; // 5 == nsCRT::strlen("BODY[")
|
||||
while (ContinueParse() && end && *end != 'M' && *end != 'm')
|
||||
{
|
||||
end++;
|
||||
}
|
||||
if (end && (*end == 'M' || *end == 'm'))
|
||||
{
|
||||
*(end-1) = 0;
|
||||
fNextToken = GetNextToken();
|
||||
char *mimeHeaderData = CreateAstring(); // is it really this simple?
|
||||
fNextToken = GetNextToken();
|
||||
if (m_shell)
|
||||
{
|
||||
m_shell->AdoptMimeHeader(start, mimeHeaderData);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetSyntaxError(PR_TRUE);
|
||||
}
|
||||
PR_Free(partNumber); // partNumber is not adopted by the body shell.
|
||||
}
|
||||
else
|
||||
{
|
||||
HandleMemoryFailure();
|
||||
}
|
||||
char *partNumber = PL_strdup(fNextToken);
|
||||
if (partNumber)
|
||||
{
|
||||
char *start = partNumber+5, *end = partNumber+5; // 5 == nsCRT::strlen("BODY[")
|
||||
while (ContinueParse() && end && *end != 'M' && *end != 'm')
|
||||
{
|
||||
end++;
|
||||
}
|
||||
if (end && (*end == 'M' || *end == 'm'))
|
||||
{
|
||||
*(end-1) = 0;
|
||||
fNextToken = GetNextToken();
|
||||
char *mimeHeaderData = CreateAstring(); // is it really this simple?
|
||||
fNextToken = GetNextToken();
|
||||
if (m_shell)
|
||||
{
|
||||
m_shell->AdoptMimeHeader(start, mimeHeaderData);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetSyntaxError(PR_TRUE);
|
||||
}
|
||||
PR_Free(partNumber); // partNumber is not adopted by the body shell.
|
||||
}
|
||||
else
|
||||
{
|
||||
HandleMemoryFailure();
|
||||
}
|
||||
}
|
||||
|
||||
// Actual mime parts are filled in on demand (either from shell generation
|
||||
// or from explicit user download), so we need to stream these out.
|
||||
void nsImapServerResponseParser::mime_part_data()
|
||||
{
|
||||
char *checkOriginToken = PL_strdup(fNextToken);
|
||||
if (checkOriginToken)
|
||||
{
|
||||
PRUint32 origin = 0;
|
||||
PRBool originFound = PR_FALSE;
|
||||
char *whereStart = PL_strchr(checkOriginToken, '<');
|
||||
if (whereStart)
|
||||
{
|
||||
char *whereEnd = PL_strchr(whereStart, '>');
|
||||
if (whereEnd)
|
||||
{
|
||||
*whereEnd = 0;
|
||||
whereStart++;
|
||||
origin = atoi(whereStart);
|
||||
originFound = PR_TRUE;
|
||||
}
|
||||
}
|
||||
PR_Free(checkOriginToken);
|
||||
fNextToken = GetNextToken();
|
||||
msg_fetch_content(originFound, origin, MESSAGE_RFC822); // keep content type as message/rfc822, even though the
|
||||
// MIME part might not be, because then libmime will
|
||||
// still handle and decode it.
|
||||
}
|
||||
else
|
||||
HandleMemoryFailure();
|
||||
char *checkOriginToken = PL_strdup(fNextToken);
|
||||
if (checkOriginToken)
|
||||
{
|
||||
PRUint32 origin = 0;
|
||||
PRBool originFound = PR_FALSE;
|
||||
char *whereStart = PL_strchr(checkOriginToken, '<');
|
||||
if (whereStart)
|
||||
{
|
||||
char *whereEnd = PL_strchr(whereStart, '>');
|
||||
if (whereEnd)
|
||||
{
|
||||
*whereEnd = 0;
|
||||
whereStart++;
|
||||
origin = atoi(whereStart);
|
||||
originFound = PR_TRUE;
|
||||
}
|
||||
}
|
||||
PR_Free(checkOriginToken);
|
||||
fNextToken = GetNextToken();
|
||||
msg_fetch_content(originFound, origin, MESSAGE_RFC822); // keep content type as message/rfc822, even though the
|
||||
// MIME part might not be, because then libmime will
|
||||
// still handle and decode it.
|
||||
}
|
||||
else
|
||||
HandleMemoryFailure();
|
||||
}
|
||||
|
||||
// FETCH BODYSTRUCTURE parser
|
||||
// After exit, set fNextToken and fCurrentLine to the right things
|
||||
void nsImapServerResponseParser::bodystructure_data()
|
||||
{
|
||||
fNextToken = GetNextToken();
|
||||
|
||||
// separate it out first
|
||||
if (fNextToken && *fNextToken == '(') // It has to start with an open paren.
|
||||
{
|
||||
char *buf = CreateParenGroup();
|
||||
|
||||
if (ContinueParse())
|
||||
{
|
||||
if (!buf)
|
||||
HandleMemoryFailure();
|
||||
else
|
||||
{
|
||||
// Looks like we have what might be a valid BODYSTRUCTURE response.
|
||||
// Try building the shell from it here.
|
||||
m_shell = new nsIMAPBodyShell(&fServerConnection, buf, CurrentResponseUID(), GetSelectedMailboxName());
|
||||
/*
|
||||
if (m_shell)
|
||||
{
|
||||
if (!m_shell->GetIsValid())
|
||||
{
|
||||
SetSyntaxError(PR_TRUE);
|
||||
}
|
||||
}
|
||||
*/
|
||||
PR_Free(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
SetSyntaxError(PR_TRUE);
|
||||
fNextToken = GetNextToken();
|
||||
|
||||
// separate it out first
|
||||
if (fNextToken && *fNextToken == '(') // It has to start with an open paren.
|
||||
{
|
||||
char *buf = CreateParenGroup();
|
||||
|
||||
if (ContinueParse())
|
||||
{
|
||||
if (!buf)
|
||||
HandleMemoryFailure();
|
||||
else
|
||||
{
|
||||
// Looks like we have what might be a valid BODYSTRUCTURE response.
|
||||
// Try building the shell from it here.
|
||||
m_shell = new nsIMAPBodyShell(&fServerConnection, buf, CurrentResponseUID(), GetSelectedMailboxName());
|
||||
/*
|
||||
if (m_shell)
|
||||
{
|
||||
if (!m_shell->GetIsValid())
|
||||
{
|
||||
SetSyntaxError(PR_TRUE);
|
||||
}
|
||||
}
|
||||
*/
|
||||
PR_Free(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
SetSyntaxError(PR_TRUE);
|
||||
}
|
||||
|
||||
void nsImapServerResponseParser::quota_data()
|
||||
|
@ -560,6 +560,9 @@ NS_IMETHODIMP nsImapService::DisplayMessage(const char* aMessageURI,
|
||||
{
|
||||
// whenever we are displaying a message, we want to add it to the memory cache..
|
||||
imapUrl->SetFetchPartsOnDemand(PR_TRUE);
|
||||
// if we happen to fetch the whole message, note in the url
|
||||
// whether we want to store this message offline.
|
||||
imapUrl->SetShouldStoreMsgOffline(shouldStoreMsgOffline);
|
||||
shouldStoreMsgOffline = PR_FALSE; // if we're fetching by parts, don't store offline
|
||||
msgurl->SetAddToMemoryCache(PR_FALSE);
|
||||
}
|
||||
@ -833,6 +836,9 @@ NS_IMETHODIMP nsImapService::Search(nsIMsgSearchSession *aSearchSession, nsIMsgW
|
||||
GetFolderName(aMsgFolder, getter_Copies(folderName));
|
||||
|
||||
nsCOMPtr <nsIMsgMailNewsUrl> mailNewsUrl = do_QueryInterface(imapUrl);
|
||||
if (!aMsgWindow)
|
||||
mailNewsUrl->SetSuppressErrorMsgs(PR_TRUE);
|
||||
|
||||
urlSpec.Append("/search>UID>");
|
||||
urlSpec.Append(char(hierarchySeparator));
|
||||
urlSpec.Append((const char *) folderName);
|
||||
|
@ -88,6 +88,7 @@ nsImapUrl::nsImapUrl()
|
||||
m_allowContentChange = PR_TRUE; // assume we can do MPOD.
|
||||
m_fetchPartsOnDemand = PR_FALSE; // but assume we're not doing it :-)
|
||||
m_msgLoadingFromCache = PR_FALSE;
|
||||
m_shouldStoreMsgOffline = PR_FALSE;
|
||||
m_externalLinkUrl = PR_TRUE; // we'll start this at true, and set it false in nsImapService::CreateStartOfImapUrl
|
||||
m_contentModified = IMAP_CONTENT_NOT_MODIFIED;
|
||||
m_validUrl = PR_TRUE; // assume the best.
|
||||
@ -346,10 +347,10 @@ NS_IMETHODIMP nsImapUrl::CreateSearchCriteriaString(char ** aResult)
|
||||
{
|
||||
// this method should only be called from the imap thread...
|
||||
// o.t. add lock protection..
|
||||
if (nsnull == aResult || !m_searchCriteriaString)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
if (nsnull == aResult || !m_searchCriteriaString)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
*aResult = nsCRT::strdup(m_searchCriteriaString);
|
||||
return NS_OK;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// this method gets called from the UI thread and the imap thread
|
||||
@ -357,30 +358,30 @@ NS_IMETHODIMP nsImapUrl::CreateListOfMessageIdsString(char ** aResult)
|
||||
{
|
||||
nsAutoCMonitor mon(this);
|
||||
nsCAutoString newStr;
|
||||
if (nsnull == aResult || !m_listOfMessageIds)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (nsnull == aResult || !m_listOfMessageIds)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
PRInt32 bytesToCopy = strlen(m_listOfMessageIds);
|
||||
|
||||
// mime may have glommed a "&part=" for a part download
|
||||
// we return the entire message and let mime extract
|
||||
// the part. Pop and news work this way also.
|
||||
// this algorithm truncates the "&part" string.
|
||||
char *currentChar = m_listOfMessageIds;
|
||||
while (*currentChar && (*currentChar != '?'))
|
||||
currentChar++;
|
||||
if (*currentChar == '?')
|
||||
bytesToCopy = currentChar - m_listOfMessageIds;
|
||||
|
||||
// we should also strip off anything after "/;section="
|
||||
// since that can specify an IMAP MIME part
|
||||
char *wherePart = PL_strstr(m_listOfMessageIds, "/;section=");
|
||||
if (wherePart)
|
||||
bytesToCopy = PR_MIN(bytesToCopy, wherePart - m_listOfMessageIds);
|
||||
|
||||
newStr.Assign(m_listOfMessageIds, bytesToCopy);
|
||||
|
||||
// mime may have glommed a "&part=" for a part download
|
||||
// we return the entire message and let mime extract
|
||||
// the part. Pop and news work this way also.
|
||||
// this algorithm truncates the "&part" string.
|
||||
char *currentChar = m_listOfMessageIds;
|
||||
while (*currentChar && (*currentChar != '?'))
|
||||
currentChar++;
|
||||
if (*currentChar == '?')
|
||||
bytesToCopy = currentChar - m_listOfMessageIds;
|
||||
|
||||
// we should also strip off anything after "/;section="
|
||||
// since that can specify an IMAP MIME part
|
||||
char *wherePart = PL_strstr(m_listOfMessageIds, "/;section=");
|
||||
if (wherePart)
|
||||
bytesToCopy = PR_MIN(bytesToCopy, wherePart - m_listOfMessageIds);
|
||||
|
||||
newStr.Assign(m_listOfMessageIds, bytesToCopy);
|
||||
*aResult = ToNewCString(newStr);
|
||||
return NS_OK;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsImapUrl::GetCommand(char **result)
|
||||
@ -1132,7 +1133,7 @@ NS_IMETHODIMP nsImapUrl::SetAllowContentChange(PRBool allowContentChange)
|
||||
|
||||
NS_IMETHODIMP nsImapUrl::SetContentModified(nsImapContentModifiedType contentModified)
|
||||
{
|
||||
m_contentModified = contentModified;
|
||||
m_contentModified = contentModified;
|
||||
nsCOMPtr<nsICacheEntryDescriptor> cacheEntry;
|
||||
nsresult res = GetMemCacheEntry(getter_AddRefs(cacheEntry));
|
||||
if (NS_SUCCEEDED(res) && cacheEntry)
|
||||
@ -1612,3 +1613,15 @@ NS_IMETHODIMP nsImapUrl::SetCharsetOverRide(const char * aCharacterSet)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsImapUrl::GetShouldStoreMsgOffline(PRBool *aShouldStoreMsgOffline)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aShouldStoreMsgOffline);
|
||||
*aShouldStoreMsgOffline = m_shouldStoreMsgOffline;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsImapUrl::SetShouldStoreMsgOffline(PRBool aShouldStoreMsgOffline)
|
||||
{
|
||||
m_shouldStoreMsgOffline = aShouldStoreMsgOffline;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -125,6 +125,7 @@ protected:
|
||||
PRPackedBool m_fetchPartsOnDemand; // if PR_TRUE, we should fetch leave parts on server.
|
||||
PRPackedBool m_msgLoadingFromCache; // if PR_TRUE, we might need to mark read on server
|
||||
PRPackedBool m_externalLinkUrl; // if PR_TRUE, we're running this url because the user
|
||||
PRPackedBool m_shouldStoreMsgOffline;
|
||||
nsImapContentModifiedType m_contentModified;
|
||||
PRInt32 m_discoveryDepth;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user