download news messages for offline sr=sspitzer for mscott 15865

This commit is contained in:
bienvenu%netscape.com 2000-12-22 02:05:48 +00:00
Родитель 887b904e59
Коммит dc38eb455f
14 изменённых файлов: 232 добавлений и 133 удалений

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

@ -335,7 +335,7 @@ const nsMsgBiffState nsMsgBiffState_Unknown = 2; // We dunno whether there is ne
void markThreadRead(in nsIMsgThread thread);
nsIMsgDatabase getMsgDatabase(in nsIMsgWindow msgWindow);
nsIMsgDatabase getDBFolderInfoAndDB(out nsIDBFolderInfo folderInfo);
nsIMsgDBHdr GetMessageHeader(in nsMsgKey msgKey);
boolean shouldStoreMsgOffline(in nsMsgKey msgKey);
boolean hasMsgOffline(in nsMsgKey msgKey);
nsIFileChannel getOfflineFileChannel(in nsMsgKey msgKey);

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

@ -1232,3 +1232,79 @@ nsresult nsMsgDBFolder::NotifyStoreClosedAllHeaders()
}
return NS_OK;
}
nsresult nsMsgDBFolder::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)
{
m_tempMessageStream->Flush();
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;
}
nsresult nsMsgDBFolder::StartNewOfflineMessage()
{
nsresult rv = GetOfflineStoreOutputStream(getter_AddRefs(m_tempMessageStream));
WriteStartOfNewLocalMessage();
return rv;
}
nsresult nsMsgDBFolder::EndNewOfflineMessage()
{
nsCOMPtr <nsIRandomAccessStore> randomStore;
PRInt32 curStorePos;
PRUint32 messageOffset;
nsMsgKey messageKey;
m_offlineHeader->GetMessageKey(&messageKey);
if (m_tempMessageStream)
randomStore = do_QueryInterface(m_tempMessageStream);
mDatabase->MarkOffline(messageKey, PR_TRUE, nsnull);
if (randomStore)
{
m_tempMessageStream->Flush();
randomStore->Tell(&curStorePos);
m_offlineHeader->GetMessageOffset(&messageOffset);
m_offlineHeader->SetOfflineMessageSize(curStorePos - messageOffset);
}
m_offlineHeader = nsnull;
return NS_OK;
}

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

@ -32,6 +32,7 @@
#include "nsIDBChangeListener.h"
#include "nsIUrlListener.h"
#include "nsIMsgHdr.h"
#include "nsIOutputStream.h"
class nsIMsgFolderCacheElement;
@ -108,6 +109,11 @@ protected:
virtual nsresult GetOfflineStoreInputStream(nsIInputStream **inputStream);
virtual nsresult GetOfflineStoreOutputStream(nsIOutputStream **outputStream);
// offline support methods.
nsresult StartNewOfflineMessage();
nsresult WriteStartOfNewLocalMessage();
nsresult EndNewOfflineMessage();
protected:
nsCOMPtr<nsIMsgDatabase> mDatabase;
@ -117,6 +123,8 @@ protected:
PRBool mGettingNewMessages;
nsCOMPtr <nsIMsgDBHdr> m_offlineHeader;
// this is currently used when we do a save as of an imap or news message..
nsCOMPtr<nsIOutputStream> m_tempMessageStream;
static nsIAtom* mFolderLoadedAtom;
static nsIAtom* mDeleteOrMoveMsgCompletedAtom;

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

@ -2427,3 +2427,20 @@ NS_IMETHODIMP nsMsgFolder::EnableNotifications(PRInt32 notificationType, PRBool
}
NS_IMETHODIMP nsMsgFolder::GetMessageHeader(nsMsgKey msgKey, nsIMsgDBHdr **aMsgHdr)
{
nsresult rv = NS_OK;
if (aMsgHdr)
{
nsCOMPtr <nsIMsgDatabase> database;
rv = GetMsgDatabase(nsnull, getter_AddRefs(database));
if (NS_SUCCEEDED(rv) && database) // did we get a db back?
rv = database->GetMsgHdrForKey(msgKey, aMsgHdr);
}
else
rv = NS_ERROR_NULL_POINTER;
return rv;
}

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

@ -156,6 +156,7 @@ public:
NS_IMETHOD GetRootFolder(nsIMsgFolder * *aRootFolder);
NS_IMETHOD GetMsgDatabase(nsIMsgWindow *aMsgWindow,
nsIMsgDatabase * *aMsgDatabase);
NS_IMETHOD GetMessageHeader(nsMsgKey msgKey, nsIMsgDBHdr **aMsgHdr);
NS_IMETHOD GetDBFolderInfoAndDB(nsIDBFolderInfo **folderInfo,
nsIMsgDatabase **db) = 0;

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

@ -2978,56 +2978,6 @@ nsImapMailFolder::SetNotifyDownloadedLines(PRBool notifyDownloadedLines)
return NS_OK;
}
nsresult nsImapMailFolder::StartNewOfflineMessage()
{
nsresult rv = GetOfflineStoreOutputStream(getter_AddRefs(m_tempMessageStream));
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)
{
m_tempMessageStream->Flush();
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)
{
@ -3059,25 +3009,7 @@ nsImapMailFolder::NormalEndMsgWriteStream(nsMsgKey uidOfMessage, PRBool markRead
if (m_offlineHeader)
{
nsCOMPtr <nsIRandomAccessStore> randomStore;
PRInt32 curStorePos;
PRUint32 messageOffset;
nsMsgKey messageKey;
m_offlineHeader->GetMessageKey(&messageKey);
if (m_tempMessageStream)
randomStore = do_QueryInterface(m_tempMessageStream);
mDatabase->MarkOffline(messageKey, PR_TRUE, nsnull);
if (randomStore)
{
m_tempMessageStream->Flush();
randomStore->Tell(&curStorePos);
m_offlineHeader->GetMessageOffset(&messageOffset);
m_offlineHeader->SetOfflineMessageSize(curStorePos - messageOffset);
}
m_offlineHeader = nsnull;
EndNewOfflineMessage();
commit = PR_TRUE;
}
if (m_tempMessageStream)
@ -3109,26 +3041,6 @@ nsImapMailFolder::AbortMsgWriteStream()
return NS_ERROR_FAILURE;
}
nsresult nsImapMailFolder::GetMessageHeader(nsMsgKey key, nsIMsgDBHdr ** aMsgHdr)
{
nsresult rv = NS_OK;
if (aMsgHdr)
{
rv = GetDatabase(nsnull);
// In theory, there shouldn't be contention over
// m_curMsgUid, but it currently describes both the most
// recent header we downloaded, and most recent message we've
// downloaded. We may want to break this up.
if (NS_SUCCEEDED(rv) && mDatabase) // did we get a db back?
rv = mDatabase->GetMsgHdrForKey(key, aMsgHdr);
}
else
rv = NS_ERROR_NULL_POINTER;
return rv;
}
// message move/copy related methods
NS_IMETHODIMP
nsImapMailFolder::OnlineCopyCompleted(nsIImapProtocol *aProtocol, ImapOnlineCopyState aCopyState)

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

@ -261,8 +261,6 @@ public:
NS_IMETHOD ApplyFilterHit(nsIMsgFilter *filter, PRBool *applyMore);
nsresult GetMessageHeader(nsMsgKey key, nsIMsgDBHdr ** aMsgHdr);
nsresult MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
nsIMsgDatabase *sourceDB,
const char *destFolder,
@ -326,10 +324,6 @@ protected:
virtual nsresult CreateBaseMessageURI(const char *aURI);
// offline support methods.
nsresult StartNewOfflineMessage();
nsresult WriteStartOfNewLocalMessage();
PRBool m_initialized;
PRBool m_haveDiscoveredAllFolders;
PRBool m_haveReadNameFromDB;
@ -342,9 +336,6 @@ protected:
nsCOMPtr<nsIEventQueue> m_eventQueue;
PRBool m_urlRunning;
// this is currently used when we do a save as of an imap message..
nsCOMPtr<nsIOutputStream> m_tempMessageStream;
// *** jt - undo move/copy trasaction support
nsCOMPtr<nsITransactionManager> m_transactionManager;
nsCOMPtr<nsMsgTxn> m_pendingUndoTxn;

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

@ -33,6 +33,7 @@ interface nsIMsgNewsFolder : nsISupports {
readonly attribute string asciiName;
readonly attribute nsINntpIncomingServer nntpServer;
attribute boolean saveArticleOffline;
string getGroupPasswordWithUI(in wstring aPromptString, in wstring aPromptTitle, in nsIMsgWindow aMsgWindow);
string getGroupUsernameWithUI(in wstring aPromptString, in wstring aPromptTitle, in nsIMsgWindow aMsgWindow);
@ -54,4 +55,5 @@ interface nsIMsgNewsFolder : nsISupports {
void cancelComplete();
void cancelFailed();
void getNextNMessages(in nsIMsgWindow aMsgWindow);
void notifyDownloadedLine(in string line, in nsMsgKey key);
};

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

@ -77,10 +77,6 @@
#include "nsIMsgFolder.h"
#include "nsIMsgNewsFolder.h"
#include "nsIRDFService.h"
#include "nsIRDFResource.h"
#include "nsRDFCID.h"
#include "nsIPref.h"
#include "nsIMsgWindow.h"
@ -157,7 +153,8 @@ static NS_DEFINE_CID(kNNTPHostCID, NS_NNTPHOST_CID);
static NS_DEFINE_CID(kCMsgMailSessionCID, NS_MSGMAILSESSION_CID);
static NS_DEFINE_CID(kCNetSupportDialogCID, NS_NETSUPPORTDIALOG_CID);
static NS_DEFINE_CID(kCMsgAccountManagerCID, NS_MSGACCOUNTMANAGER_CID);
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
static NS_DEFINE_CID(kPrefServiceCID,NS_PREF_CID);
static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
typedef struct _cancelInfoEntry {
char *from;
@ -633,26 +630,8 @@ NS_IMETHODIMP nsNNTPProtocol::Initialize(nsIURI * aURL, nsIMsgWindow *aMsgWindow
nsresult
nsNNTPProtocol::InitializeNewsFolderFromUri(const char *uri)
{
nsresult rv;
NS_ENSURE_ARG_POINTER(uri);
PR_LOG(NNTP,PR_LOG_ALWAYS,("InitializeNewsFolderFromUri(%s)",uri));
NS_WITH_SERVICE(nsIRDFService, rdf, kRDFServiceCID, &rv);
if (NS_FAILED(rv)) return(rv);
nsCOMPtr<nsIRDFResource> resource;
rv = rdf->GetResource(uri, getter_AddRefs(resource));
if (NS_FAILED(rv)) return(rv);
m_newsFolder = do_QueryInterface(resource, &rv);
NS_ASSERTION(NS_SUCCEEDED(rv), "uri is not for a news folder!");
if (NS_FAILED(rv)) return rv;
if (!m_newsFolder) return NS_ERROR_FAILURE;
return NS_OK;
PR_LOG(NNTP,PR_LOG_ALWAYS,("InitializeNewsFolderFromUri(%s)",uri));
return nsGetNewsGroupFromUri(uri, getter_AddRefs(m_newsFolder));
}
/* void IsBusy (out boolean aIsConnectionBusy); */
@ -2248,6 +2227,9 @@ PRInt32 nsNNTPProtocol::DisplayArticle(nsIInputStream * inputStream, PRUint32 le
return status;
}
if (m_newsFolder)
m_newsFolder->NotifyDownloadedLine(line, m_articleNumber);
if (line[0] == '.' && line[1] == 0)
{
m_nextState = NEWS_DONE;
@ -5320,13 +5302,8 @@ nsNNTPProtocol::AlertError(PRInt32 errorCode, const char *text)
NS_ENSURE_SUCCESS(rv,rv);
alertText.Append(str);
rv = GetNewsStringByID(errorCode, getter_Copies(str));
NS_ENSURE_SUCCESS(rv, rv);
alertText.Append(str);
if (text) {
alertText.AppendWithConversion(text);
}
if (text)
alertText.AppendWithConversion(text);
rv = dialog->Alert(nsnull, alertText.GetUnicode());
NS_ENSURE_SUCCESS(rv, rv);

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

@ -101,7 +101,8 @@ static NS_DEFINE_CID(kNetSupportDialogCID, NS_NETSUPPORTDIALOG_CID);
nsMsgNewsFolder::nsMsgNewsFolder(void) : nsMsgLineBuffer(nsnull, PR_FALSE),
mExpungedBytes(0), mGettingNews(PR_FALSE),
mInitialized(PR_FALSE), mOptionLines(""), mUnsubscribedNewsgroupLines(""), mCachedNewsrcLine(nsnull), mGroupUsername(nsnull), mGroupPassword(nsnull)
mInitialized(PR_FALSE), mOptionLines(""), mUnsubscribedNewsgroupLines(""),
m_downloadMessageForOfflineUse(PR_FALSE), mCachedNewsrcLine(nsnull), mGroupUsername(nsnull), mGroupPassword(nsnull)
{
MOZ_COUNT_CTOR(nsNewsFolder); // double count these for now.
/* we're parsing the newsrc file, and the line breaks are platform specific.
@ -1704,3 +1705,60 @@ NS_IMETHODIMP nsMsgNewsFolder::CancelFailed()
NotifyFolderEvent(mDeleteOrMoveMsgFailedAtom);
return NS_OK;
}
NS_IMETHODIMP nsMsgNewsFolder::GetSaveArticleOffline(PRBool *aBool)
{
NS_ENSURE_ARG(aBool);
*aBool = m_downloadMessageForOfflineUse;
return NS_OK;
}
NS_IMETHODIMP nsMsgNewsFolder::SetSaveArticleOffline(PRBool aBool)
{
m_downloadMessageForOfflineUse = aBool;
return NS_OK;
}
// line does not have a line terminator (e.g., CR or CRLF)
NS_IMETHODIMP nsMsgNewsFolder::NotifyDownloadedLine(const char *line, nsMsgKey keyOfArticle)
{
nsresult rv = NS_OK;
PRBool commit = PR_FALSE;
if (m_downloadMessageForOfflineUse && !m_tempMessageStream)
{
GetMessageHeader(keyOfArticle, getter_AddRefs(m_offlineHeader));
rv = StartNewOfflineMessage();
}
if (m_tempMessageStream)
{
if (line[0] == '.' && line[1] == 0)
{
// end of article.
if (m_offlineHeader)
{
EndNewOfflineMessage();
commit = PR_TRUE;
}
if (m_tempMessageStream)
{
m_tempMessageStream->Close();
m_tempMessageStream = nsnull;
}
}
else
{
PRUint32 count = 0;
rv = m_tempMessageStream->Write(line,
nsCRT::strlen(line), &count);
if (NS_SUCCEEDED(rv))
rv = m_tempMessageStream->Write(MSG_LINEBREAK, MSG_LINEBREAK_LEN, &count);
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to write to stream");
}
}
if (commit && mDatabase)
mDatabase->Commit(nsMsgDBCommitType::kLargeCommit);
return rv;
}

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

@ -123,7 +123,7 @@ protected:
nsISupportsArray *mMessages;
nsCAutoString mOptionLines;
nsCAutoString mUnsubscribedNewsgroupLines;
PRBool m_downloadMessageForOfflineUse;
// cache this until we open the db.
char *mCachedNewsrcLine;

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

@ -31,6 +31,12 @@
#include "nsINntpIncomingServer.h"
#include "nsMsgBaseCID.h"
#include "nsMsgUtils.h"
#include "nsIRDFService.h"
#include "nsIRDFResource.h"
#include "nsRDFCID.h"
#include "nsIMsgNewsFolder.h"
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
static nsresult
nsGetNewsServer(const char* username, const char *hostname,
@ -192,6 +198,28 @@ nsParseNewsMessageURI(const char* uri, nsCString& messageUriWithoutKey, PRUint32
}
nsresult nsGetNewsGroupFromUri(const char *uri, nsIMsgNewsFolder **aFolder)
{
NS_ENSURE_ARG(aFolder);
NS_ENSURE_ARG(uri);
nsresult rv;
NS_WITH_SERVICE(nsIRDFService, rdf, kRDFServiceCID, &rv);
if (NS_FAILED(rv)) return(rv);
nsCOMPtr<nsIRDFResource> resource;
rv = rdf->GetResource(uri, getter_AddRefs(resource));
if (NS_FAILED(rv)) return(rv);
rv = resource->QueryInterface(NS_GET_IID(nsIMsgNewsFolder), (void **) aFolder);
NS_ASSERTION(NS_SUCCEEDED(rv), "uri is not for a news folder!");
if (NS_FAILED(rv)) return rv;
if (!*aFolder) return NS_ERROR_FAILURE;
return NS_OK;
}
nsresult nsBuildNewsMessageURI(const char *baseURI, PRUint32 key, nsCString& uri)
{
uri.Append(baseURI);

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

@ -27,6 +27,8 @@
#include "nsString.h"
#include "nsIMsgIncomingServer.h"
class nsIMsgNewsFolder;
static const char kNewsRootURI[] = "news:/";
static const char kNewsMessageRootURI[] = "news_message:/";
@ -45,5 +47,7 @@ nsBuildNewsMessageURI(const char *baseURI, PRUint32 key, nsCString& uri);
extern nsresult
nsCreateNewsBaseMessageURI(const char *baseURI, char **baseMessageURI);
extern nsresult nsGetNewsGroupFromUri(const char *uri, nsIMsgNewsFolder **aFolder);
#endif //NS_NEWSUTILS_H

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

@ -172,6 +172,7 @@ nsNntpService::DisplayMessage(const char* aMessageURI, nsISupports * aDisplayCon
#endif
nsCAutoString uri(aMessageURI);
nsCAutoString newsGroupNameUri(aMessageURI);
nsCAutoString newsgroupName;
nsMsgKey key = nsMsgKey_None;
@ -183,6 +184,14 @@ nsNntpService::DisplayMessage(const char* aMessageURI, nsISupports * aDisplayCon
// todo: if we get here, make sure uri really a news article url (example: "news://host/aa@bb")
}
newsGroupNameUri.ReplaceSubstring("news_message:", "news:");
PRInt32 poundPos = newsGroupNameUri.RFindChar('#', PR_FALSE);
nsCOMPtr <nsIMsgNewsFolder> newsFolder;
if (poundPos != -1)
{
newsGroupNameUri.Truncate(poundPos);
nsGetNewsGroupFromUri(newsGroupNameUri, getter_AddRefs(newsFolder));
}
// now create a url with this uri spec
nsCOMPtr<nsIURI> myuri;
@ -199,8 +208,24 @@ nsNntpService::DisplayMessage(const char* aMessageURI, nsISupports * aDisplayCon
msgUrl->SetMsgWindow(aMsgWindow);
nntpUrl->SetNewsAction(nsINntpUrl::ActionDisplayArticle);
nsCOMPtr<nsIMsgI18NUrl> i18nurl (do_QueryInterface(msgUrl));
nsCOMPtr <nsIMsgFolder> folder;
i18nurl->SetCharsetOverRide(aCharsetOverride);
PRBool shouldStoreMsgOffline = PR_FALSE;
PRBool hasMsgOffline = PR_FALSE;
if (newsFolder)
{
nsCOMPtr <nsIMsgFolder> folder = do_QueryInterface(newsFolder);
if (folder)
{
folder->ShouldStoreMsgOffline(key, &shouldStoreMsgOffline);
folder->HasMsgOffline(key, &hasMsgOffline);
}
newsFolder->SetSaveArticleOffline(shouldStoreMsgOffline);
}
// now is where our behavior differs....if the consumer is the docshell then we want to
// run the url in the webshell in order to display it. If it isn't a docshell then just
// run the news url like we would any other news url.