fix for 185184, patch by hyc@symas.com, r=bienvenu, sr=mscott add option to only download pop3 headers initially, and download body on demand

This commit is contained in:
bienvenu%nventure.com 2004-06-10 15:58:10 +00:00
parent 5ce01e4ab2
commit 0367cfdae3
26 changed files with 301 additions and 77 deletions

View File

@ -150,6 +150,12 @@
accesskey="&downloadOnBiff.accesskey;"
prefstring="mail.server.%serverkey%.download_on_biff"/>
<checkbox wsm_persist="true" id="pop3.headersOnly"
label="&headersOnly.label;"
accesskey="&headersOnly.accesskey;"
prefattribute="value"
prefstring="mail.server.%serverkey%.headers_only"/>
<checkbox wsm_persist="true" id="pop3.leaveMessagesOnServer"
label="&leaveOnServer.label;" oncommand="setupMailOnServerUI();"
accesskey="&leaveOnServer.accesskey;"

View File

@ -31,6 +31,8 @@
<!ENTITY useSecAuth.accesskey "i">
<!ENTITY leaveOnServer.label "Leave messages on server">
<!ENTITY leaveOnServer.accesskey "g">
<!ENTITY headersOnly.label "Fetch headers only">
<!ENTITY headersOnly.accesskey "f">
<!ENTITY deleteByAgeFromServer.label "For at most">
<!ENTITY deleteByAgeFromServer.accesskey "o">
<!ENTITY daysEnd.label "days">

View File

@ -90,6 +90,11 @@
<!-- End command set merging -->
<commandset id="mailDownloadCommands">
<command id="cmd_downloadFlagged" oncommand="goDoCommand('cmd_downloadFlagged')"/>
<command id="cmd_downloadSelected" oncommand="goDoCommand('cmd_downloadSelected')"/>
</commandset>
<commandset id="mailFileMenuItems"
commandupdater="true"
events="create-menu-file"
@ -104,8 +109,7 @@
<command id="cmd_emptyTrash" oncommand="goDoCommand('cmd_emptyTrash')" disabled="true"/>
<command id="cmd_compactFolder" oncommand="goDoCommand('cmd_compactFolder')" disabled="true"/>
<command id="cmd_synchronizeOffline" oncommand="goDoCommand('cmd_synchronizeOffline')" disabled="true"/>
<command id="cmd_downloadFlagged" oncommand="goDoCommand('cmd_downloadFlagged')" disabled="true"/>
<command id="cmd_downloadSelected" oncommand="goDoCommand('cmd_downloadSelected')" disabled="true"/>
<commandset id="mailDownloadCommands"/>
<command id="cmd_settingsOffline" oncommand="goDoCommand('cmd_settingsOffline')" disabled="true"/>
<command id="cmd_openMessage" oncommand="goDoCommand('cmd_openMessage')" disabled="true"/>
@ -229,6 +233,7 @@
<command id="cmd_forwardInline" oncommand="goDoCommand('cmd_forwardInline')"/>
<command id="cmd_forwardAttachment" oncommand="goDoCommand('cmd_forwardAttachment')"/>
<command id="cmd_editAsNew" oncommand="goDoCommand('cmd_editAsNew')"/>
<commandset id="mailDownloadCommands"/>
<command id="cmd_createFilterFromMenu" oncommand="goDoCommand('cmd_createFilterFromMenu')"/>
<command id="cmd_killThread" oncommand="goDoCommand('cmd_killThread')"/>
<command id="cmd_watchThread" oncommand="goDoCommand('cmd_watchThread')"/>
@ -635,6 +640,9 @@
</menupopup>
</menu>
<menuseparator/>
<menuitem label="&downloadFlaggedCmd.label;" accesskey="&downloadFlaggedCmd.accesskey;" observes="cmd_downloadFlagged"/>
<menuitem label="&downloadSelectedCmd.label;" accesskey="&downloadSelectedCmd.accesskey;" observes="cmd_downloadSelected"/>
<menuseparator/>
<menuitem id="threadPaneContext-saveAs"
label="&contextSaveAs.label;"
accesskey="&contextSaveAs.accesskey;"

View File

@ -59,7 +59,7 @@ typedef long nsMsgFilterIndex;
typedef long nsMsgRuleActionType;
[scriptable, uuid(11ba0ed6-304f-11d3-9c16-00a0c900d445)]
[scriptable, uuid(3099cee1-eb76-4cd3-a40e-cfc8d2ef4437)]
interface nsMsgFilterAction {
/* these longs are all actually of type nsMsgFilterActionType */
@ -78,5 +78,6 @@ interface nsMsgFilterAction {
const long DeleteFromPop3Server=12;
const long LeaveOnPop3Server=13;
const long JunkScore=14;
const long FetchBodyFromPop3Server=15;
};

View File

@ -63,6 +63,7 @@ var gDeleteCheckbox;
var gKillCheckbox;
var gWatchCheckbox;
var gDeleteFromServerCheckbox;
var gFetchBodyFromServerCheckbox;
var gFilterActionList;
var nsMsgFilterAction = Components.interfaces.nsMsgFilterAction;
@ -290,6 +291,7 @@ function initializeFilterWidgets()
gKillCheckbox = document.getElementById("kill");
gWatchCheckbox = document.getElementById("watch");
gDeleteFromServerCheckbox = document.getElementById("deleteFromServer");
gFetchBodyFromServerCheckbox = document.getElementById("fetchBodyFromServer");
gFilterActionList = document.getElementById("filterActionList");
}
@ -354,6 +356,8 @@ function initializeDialog(filter)
gKillCheckbox.checked = true;
else if (filterAction.type == nsMsgFilterAction.DeleteFromPop3Server)
gDeleteFromServerCheckbox.checked = true;
else if (filterAction.type == nsMsgFilterAction.FetchBodyFromPop3Server)
gFetchBodyFromServerCheckbox.checked = true;
SetUpFilterActionList(getScope(filter));
}
@ -521,6 +525,13 @@ function saveFilter()
gFilter.appendAction(filterAction);
}
if (gFetchBodyFromServerCheckbox.checked)
{
filterAction = gFilter.createAction();
filterAction.type = nsMsgFilterAction.FetchBodyFromPop3Server;
gFilter.appendAction(filterAction);
}
if (gFilter.actionList.Count() <= 0)
{
str = gFilterBundle.getString("mustSelectAction");

View File

@ -188,6 +188,12 @@
</listcell>
</listitem>
<listitem allowevents="true">
<listcell>
<checkbox id="fetchBodyFromServer" enableforpop3="true" label="&fetchBodyFromServer.label;"/>
</listcell>
</listitem>
<listitem allowevents="true">
<listcell>
<checkbox id="kill" enablefornews="true" label="&killThread.label;"/>

View File

@ -24,6 +24,7 @@
<!ENTITY killThread.label "Ignore thread">
<!ENTITY watchThread.label "Watch thread">
<!ENTITY deleteFromServer.label "Delete from POP server">
<!ENTITY fetchBodyFromServer.label "Fetch body from POP server">
<!ENTITY setJunkScore.label "Set Junk Status to:">
<!ENTITY filterName.label "Filter name:">
<!ENTITY filterName.accesskey "i">

View File

@ -745,6 +745,7 @@ static struct RuleActionsTableEntry ruleActionsTable[] =
{ nsMsgFilterAction::DeleteFromPop3Server, nsMsgFilterType::All, 0, "Delete from Pop3 server"},
{ nsMsgFilterAction::LeaveOnPop3Server, nsMsgFilterType::All, 0, "Leave on Pop3 server"},
{ nsMsgFilterAction::JunkScore, nsMsgFilterType::All, 0, "JunkScore"},
{ nsMsgFilterAction::FetchBodyFromPop3Server, nsMsgFilterType::All, 0, "Fetch body from Pop3Server"},
};
const char *nsMsgFilter::GetActionStr(nsMsgRuleActionType action)

View File

@ -717,7 +717,14 @@ nsresult nsMsgDBView::FetchSize(nsIMsgHdr * aHdr, PRUnichar ** aSizeString)
}
else
{
aHdr->GetMessageSize(&msgSize);
PRUint32 flags = 0;
aHdr->GetFlags(&flags);
if (flags & MSG_FLAG_PARTIAL)
aHdr->GetUint32Property("onlineSize", &msgSize);
if (msgSize == 0)
aHdr->GetMessageSize(&msgSize);
if(msgSize < 1024)
msgSize = 1024;
@ -1229,7 +1236,9 @@ NS_IMETHODIMP nsMsgDBView::GetCellProperties(PRInt32 aRow, nsITreeColumn *col, n
if (flags & MSG_FLAG_NEW)
properties->AppendElement(kNewMsgAtom);
if (flags & MSG_FLAG_OFFLINE)
nsCOMPtr <nsIMsgLocalMailFolder> localFolder = do_QueryInterface(m_folder);
if ((flags & MSG_FLAG_OFFLINE) || (localFolder && !(flags & MSG_FLAG_PARTIAL)))
properties->AppendElement(kOfflineMsgAtom);
if (flags & MSG_FLAG_ATTACHMENT)

View File

@ -43,7 +43,15 @@ interface nsIMsgDatabase;
interface nsIMsgFolder;
interface nsIMsgCopyServiceListener;
[scriptable, uuid(27D2DE40-BAF1-11d2-9578-00805F8AC615)]
%{C++
/* flags for markMsgsOnPop3Server */
#define POP3_NONE 0
#define POP3_DELETE 1
#define POP3_FETCH_BODY 2
#define POP3_FORCE_DEL 3
%}
[scriptable, uuid(b8e26003-f2bb-4239-ba47-d597ab6e3671)]
interface nsIMsgLocalMailFolder : nsISupports {
/**
* set the default flags on the subfolders of this folder, such as
@ -59,6 +67,6 @@ interface nsIMsgLocalMailFolder : nsISupports {
void copyAllSubFolders(in nsIMsgFolder srcFolder, in nsIMsgWindow msgWindow, in nsIMsgCopyServiceListener listener );
void onCopyCompleted(in nsISupports aSrcSupport, in boolean aMoveCopySucceeded);
attribute boolean checkForNewMessagesAfterParsing;
[noscript] void markMsgsOnPop3Server(in nsISupportsArray aMessages, in boolean aDeleteMsgs);
[noscript] void markMsgsOnPop3Server(in nsISupportsArray aMessages, in PRInt32 aMark);
void refreshSizeOnDisk(); // file size on disk has possibly changed - update and notify
};

View File

@ -43,9 +43,10 @@ interface nsIMsgFolder;
interface nsIUrlListener;
interface nsIMsgWindow;
[scriptable, uuid(758a8970-e628-11d2-b7fc-00805f05ffa5)]
[scriptable, uuid(dcae2877-b7e7-47e1-80ca-5a67de03ec4c)]
interface nsIPop3IncomingServer : nsISupports {
attribute boolean leaveMessagesOnServer;
attribute boolean headersOnly;
attribute boolean deleteMailLeftOnServer;
attribute boolean authLogin;
attribute boolean dotFix;
@ -53,9 +54,9 @@ interface nsIPop3IncomingServer : nsISupports {
attribute boolean deleteByAgeFromServer;
attribute long numDaysToLeaveOnServer;
attribute nsIPop3Protocol runningProtocol;
// client adds uidls to mark one by one, then calls markMessagesDeleted
void addUidlToMarkDeleted(in string aUidl);
void markMessagesDeleted(in boolean aDeleteMsgs);
// client adds uidls to mark one by one, then calls markMessages
void addUidlToMark(in string aUidl, in PRInt32 newStatus);
void markMessages();
attribute boolean authenticated;
/* account to which this server defers storage, for global inbox */
attribute string deferredToAccount;

View File

@ -38,15 +38,19 @@
#include "nsISupports.idl"
[ptr] native nsCStringArray(nsCStringArray);
[ptr] native nsVoidArray(nsVoidArray);
%{C++
#include "nsVoidArray.h"
%}
[scriptable, uuid(853daefb-411a-41f5-97e0-2f93e79b7302)]
[scriptable, uuid(aebda729-c423-4113-ae36-2229fdc3b699)]
interface nsIPop3Protocol : nsISupports {
[noscript] void markMessagesDeleted(in nsCStringArray aUidlArray, in boolean aDeleteMsgs);
/* aUidl is an array of pointers to Pop3UidlEntry's. That structure is
* currently defined in nsPop3Protocol.h, perhaps it should be here
* instead...
*/
[noscript] void markMessages(in nsVoidArray aUidl);
};

View File

@ -61,7 +61,7 @@ interface nsIPop3Sink : nsISupports {
[noscript] void IncorporateWrite(in string block,
in long length);
[noscript] void IncorporateComplete(in nsIMsgWindow aMsgWindow);
[noscript] void IncorporateComplete(in nsIMsgWindow aMsgWindow, in PRInt32 aSize);
[noscript] void IncorporateAbort(in boolean uidlDownload);
void BiffGetNewMail();

View File

@ -1601,7 +1601,7 @@ nsMsgLocalMailFolder::DeleteMessages(nsISupportsArray *messages,
if(NS_SUCCEEDED(rv))
{
nsCOMPtr<nsISupports> msgSupport;
MarkMsgsOnPop3Server(messages, PR_TRUE);
MarkMsgsOnPop3Server(messages, POP3_DELETE);
rv = EnableNotifications(allMessageCountNotifications, PR_FALSE, PR_TRUE /*dbBatching*/);
if (NS_SUCCEEDED(rv))
@ -2938,12 +2938,11 @@ nsresult nsMsgLocalMailFolder::CopyMessageTo(nsISupports *message,
// The next time we look at mail the message will be deleted from the server.
NS_IMETHODIMP
nsMsgLocalMailFolder::MarkMsgsOnPop3Server(nsISupportsArray *aMessages, PRBool aDeleteMsgs)
nsMsgLocalMailFolder::MarkMsgsOnPop3Server(nsISupportsArray *aMessages, PRInt32 aMark)
{
const char *uidl, *accountKey;
char *header = nsnull;
PRUint32 size = 0, len = 0;
nsCOMPtr <nsIMsgDBHdr> hdr;
nsCOMPtr<nsIPop3IncomingServer> curFolderPop3MailServer;
nsCOMPtr<nsIFileSpec> mailboxSpec;
nsCOMArray<nsIPop3IncomingServer> pop3Servers; // servers with msgs deleted...
@ -2982,6 +2981,11 @@ nsMsgLocalMailFolder::MarkMsgsOnPop3Server(nsISupportsArray *aMessages, PRBool a
PRUint32 srcCount;
aMessages->Count(&srcCount);
// Filter delete requests are always honored, others are subject
// to the deleteMailLeftOnServer preference.
PRInt32 mark;
mark = (aMark == POP3_FORCE_DEL) ? POP3_DELETE : aMark;
for (PRInt32 i = 0; i < srcCount; i++)
{
/* get uidl for this message */
@ -2992,7 +2996,7 @@ nsMsgLocalMailFolder::MarkMsgsOnPop3Server(nsISupportsArray *aMessages, PRBool a
PRUint32 flags = 0;
if (msgDBHdr /* maybe check for partial flag || some server has leave on server */)
if (msgDBHdr)
{
msgDBHdr->GetFlags(&flags);
len = 0;
@ -3007,8 +3011,6 @@ nsMsgLocalMailFolder::MarkMsgsOnPop3Server(nsISupportsArray *aMessages, PRBool a
curFolderPop3MailServer->GetLeaveMessagesOnServer(&leaveOnServer);
}
if (!deleteMailLeftOnServer)
continue;
msgDBHdr->GetMessageOffset(&messageOffset);
rv = seekableStream->Seek(PR_SEEK_SET, messageOffset);
NS_ENSURE_SUCCESS(rv,rv);
@ -3048,20 +3050,22 @@ nsMsgLocalMailFolder::MarkMsgsOnPop3Server(nsISupportsArray *aMessages, PRBool a
msgPop3Server = curMsgPop3MailServer;
msgPop3Server->GetDeleteMailLeftOnServer(&deleteMailLeftOnServer);
msgPop3Server->GetLeaveMessagesOnServer(&leaveOnServer);
// stop looking at headers if leaveOnServer not set...
if (! (flags & MSG_FLAG_PARTIAL) && !leaveOnServer)
continue;
}
}
}
// ignore this header if not partial and leaveOnServer not set...
if (! (flags & MSG_FLAG_PARTIAL) && !leaveOnServer)
continue;
// if marking deleted, ignore header if we're not deleting from
// server when deleting locally.
if (aMark == POP3_DELETE && leaveOnServer && !deleteMailLeftOnServer)
continue;
uidl = strstr(header.get(), X_UIDL);
if (uidl)
{
if (! (flags & MSG_FLAG_PARTIAL) && !leaveOnServer)
continue;
uidl += X_UIDL_LEN + 2; // skip UIDL: header
len = strlen(uidl);
msgPop3Server->AddUidlToMarkDeleted(uidl);
msgPop3Server->AddUidlToMark(uidl, mark);
// remember this pop server in list of servers with msgs deleted
if (pop3Servers.IndexOfObject(msgPop3Server) == kNotFound)
pop3Servers.AppendObject(msgPop3Server);
@ -3079,13 +3083,39 @@ nsMsgLocalMailFolder::MarkMsgsOnPop3Server(nsISupportsArray *aMessages, PRBool a
// need to do this for all pop3 mail servers that had messages deleted.
PRInt32 serverCount = pop3Servers.Count();
for (PRUint32 index = 0; index < serverCount; index++)
pop3Servers[index]->MarkMessagesDeleted(aDeleteMsgs);
pop3Servers[index]->MarkMessages();
mailboxSpec->CloseStream();
return rv;
}
NS_IMETHODIMP nsMsgLocalMailFolder::DownloadMessagesForOffline(
nsISupportsArray *aMessages, nsIMsgWindow *aWindow)
{
nsresult rv;
MarkMsgsOnPop3Server(aMessages, POP3_FETCH_BODY);
rv = GetNewMessages(aWindow, nsnull);
if (NS_SUCCEEDED(rv))
{
PRUint32 srcCount;
aMessages->Count(&srcCount);
for (PRInt32 i = 0; i < srcCount; i++)
{
nsCOMPtr<nsIMsgDBHdr> msgDBHdr (do_QueryElementAt(aMessages, i, &rv));
if (msgDBHdr)
{
PRUint32 flags = 0;
msgDBHdr->GetFlags(&flags);
if (flags & MSG_FLAG_PARTIAL)
mDatabase->DeleteHeader(msgDBHdr, nsnull, PR_FALSE, PR_TRUE);
}
}
}
return rv;
}
// TODO: once we move certain code into the IncomingServer (search for TODO)
// this method will go away.

View File

@ -174,6 +174,10 @@ public:
NS_IMETHOD GetName(PRUnichar **aName);
// Used when headers_only is TRUE
NS_IMETHOD DownloadMessagesForOffline(nsISupportsArray *aMessages, nsIMsgWindow *aWindow);
protected:
nsresult CopyFolderAcrossServer(nsIMsgFolder *srcFolder, nsIMsgWindow *msgWindow,nsIMsgCopyServiceListener* listener);

View File

@ -346,7 +346,7 @@ nsLocalMoveCopyMsgTxn::UndoTransactionInternal()
}
nsCOMPtr <nsIMsgLocalMailFolder> localFolder = do_QueryInterface(srcFolder);
if (localFolder)
localFolder->MarkMsgsOnPop3Server(srcMessages, PR_FALSE /*deleteMsgs*/);
localFolder->MarkMsgsOnPop3Server(srcMessages, POP3_NONE /*deleteMsgs*/);
}
srcDB->SetSummaryValid(PR_TRUE);
srcDB->Commit(nsMsgDBCommitType::kLargeCommit);
@ -430,7 +430,7 @@ nsLocalMoveCopyMsgTxn::RedoTransaction()
{
nsCOMPtr <nsIMsgLocalMailFolder> localFolder = do_QueryInterface(srcFolder);
if (localFolder)
localFolder->MarkMsgsOnPop3Server(srcMessages, PR_TRUE /*deleteMsgs*/);
localFolder->MarkMsgsOnPop3Server(srcMessages, POP3_DELETE /*deleteMsgs*/);
rv = srcDB->DeleteMessages(&m_srcKeyArray, nsnull);
srcDB->SetSummaryValid(PR_TRUE);

View File

@ -1722,7 +1722,29 @@ NS_IMETHODIMP nsParseNewMailState::ApplyFilterHit(nsIMsgFilter *filter, nsIMsgWi
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISupports> iSupports = do_QueryInterface(msgHdr);
messages->AppendElement(iSupports);
localFolder->MarkMsgsOnPop3Server(messages, PR_TRUE);
// This action ignores the deleteMailLeftOnServer preference
localFolder->MarkMsgsOnPop3Server(messages, POP3_FORCE_DEL);
}
}
break;
case nsMsgFilterAction::FetchBodyFromPop3Server:
{
PRUint32 flags = 0;
nsCOMPtr <nsIMsgFolder> downloadFolder;
msgHdr->GetFolder(getter_AddRefs(downloadFolder));
nsCOMPtr <nsIMsgLocalMailFolder> localFolder = do_QueryInterface(downloadFolder);
msgHdr->GetFlags(&flags);
if (localFolder && (flags & MSG_FLAG_PARTIAL))
{
nsCOMPtr<nsISupportsArray> messages;
rv = NS_NewISupportsArray(getter_AddRefs(messages));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISupports> iSupports = do_QueryInterface(msgHdr);
messages->AppendElement(iSupports);
localFolder->MarkMsgsOnPop3Server(messages, POP3_FETCH_BODY);
// Don't add this header to the DB, we're going to replace it
// with the full message.
m_msgMovedByFilter = PR_TRUE;
}
}
break;

View File

@ -109,6 +109,10 @@ NS_IMPL_SERVERPREF_BOOL(nsPop3IncomingServer,
LeaveMessagesOnServer,
"leave_on_server")
NS_IMPL_SERVERPREF_BOOL(nsPop3IncomingServer,
HeadersOnly,
"headers_only")
NS_IMPL_SERVERPREF_BOOL(nsPop3IncomingServer,
DeleteMailLeftOnServer,
"delete_mail_left_on_server")
@ -547,17 +551,36 @@ NS_IMETHODIMP nsPop3IncomingServer::GetRunningProtocol(nsIPop3Protocol **aProtoc
return NS_OK;
}
NS_IMETHODIMP nsPop3IncomingServer::AddUidlToMarkDeleted(const char *aUidl)
NS_IMETHODIMP nsPop3IncomingServer::AddUidlToMark(const char *aUidl,
PRInt32 aMark)
{
return m_uidlsToMarkDeleted.AppendCString(nsDependentCString(aUidl));
Pop3UidlEntry *uidlEntry;
nsresult rv = NS_ERROR_OUT_OF_MEMORY;
uidlEntry = PR_NEWZAP(Pop3UidlEntry);
if (uidlEntry)
{
uidlEntry->uidl = strdup(aUidl);
if (uidlEntry->uidl)
{
uidlEntry->status = (aMark == POP3_DELETE) ? DELETE_CHAR :
(aMark == POP3_FETCH_BODY) ? FETCH_BODY : KEEP;
m_uidlsToMark.AppendElement(uidlEntry);
rv = NS_OK;
} else
{
PR_Free(uidlEntry);
}
}
return rv;
}
NS_IMETHODIMP nsPop3IncomingServer::MarkMessagesDeleted(PRBool aDeleteMsgs)
NS_IMETHODIMP nsPop3IncomingServer::MarkMessages()
{
nsresult rv;
if (m_runningProtocol)
{
rv = m_runningProtocol->MarkMessagesDeleted(&m_uidlsToMarkDeleted, aDeleteMsgs);
rv = m_runningProtocol->MarkMessages(&m_uidlsToMark);
}
else
{
@ -570,9 +593,16 @@ NS_IMETHODIMP nsPop3IncomingServer::MarkMessagesDeleted(PRBool aDeleteMsgs)
GetHostName(getter_Copies(hostName));
GetUsername(getter_Copies(userName));
// do it all in one fell swoop
rv = nsPop3Protocol::MarkMsgDeletedForHost(hostName, userName, localPath, m_uidlsToMarkDeleted, aDeleteMsgs);
rv = nsPop3Protocol::MarkMsgForHost(hostName, userName, localPath, m_uidlsToMark);
}
m_uidlsToMarkDeleted.Clear();
PRUint32 count = m_uidlsToMark.Count();
for (PRUint32 i = 0; i < count; i++)
{
Pop3UidlEntry *ue = NS_STATIC_CAST(Pop3UidlEntry*,m_uidlsToMark[i]);
PR_Free(ue->uidl);
PR_Free(ue);
}
m_uidlsToMark.Clear();
return rv;
}

View File

@ -79,7 +79,7 @@ private:
PRBool m_authenticated;
nsCOMPtr <nsIPop3Protocol> m_runningProtocol;
nsCOMPtr <nsIMsgFolder> m_rootMsgFolder;
nsCStringArray m_uidlsToMarkDeleted;
nsVoidArray m_uidlsToMark;
};
#endif

View File

@ -158,10 +158,10 @@ put_hash(PLHashTable* table, const char* key, char value, PRTime dateReceived)
if (tmp)
{
tmp->uidl = PL_strdup(key);
tmp->dateReceived = dateReceived;
tmp->status = value;
if (tmp->uidl)
{
tmp->dateReceived = dateReceived;
tmp->status = value;
PL_HashTableAdd(table, (const void *)tmp->uidl, (void*) tmp);
}
else
@ -313,7 +313,7 @@ net_pop3_load_state(const char* searchhost,
if (flags && uidl)
{
if ((flags[0] == KEEP) || (flags[0] == DELETE_CHAR) ||
(flags[0] == TOO_BIG))
(flags[0] == TOO_BIG) || (flags[0] == FETCH_BODY))
{
put_hash(current->hash, uidl, flags[0], dateReceived);
}
@ -368,6 +368,7 @@ net_pop3_write_mapper(PLHashEntry* he, PRIntn msgindex, void* arg)
Pop3UidlEntry *uidlEntry = (Pop3UidlEntry *) he->value;
NS_ASSERTION((uidlEntry->status == KEEP) ||
(uidlEntry->status == DELETE_CHAR) ||
(uidlEntry->status == FETCH_BODY) ||
(uidlEntry->status == TOO_BIG), "invalid status");
char* tmpBuffer = PR_smprintf("%c %s %d" MSG_LINEBREAK, uidlEntry->status, (char*)
uidlEntry->uidl, uidlEntry->dateReceived);
@ -446,15 +447,14 @@ message is not found, then the message was downloaded completly and already dele
from the server. So this only applies to messages kept on the server or too big
for download. */
/* static */
void nsPop3Protocol::MarkMsgDeletedInHashTable(PLHashTable *hashTable, const char *uidl, PRBool deleteChar, PRBool *changed)
void nsPop3Protocol::MarkMsgInHashTable(PLHashTable *hashTable, const Pop3UidlEntry *uidlE, PRBool *changed)
{
Pop3UidlEntry *uidlEntry = (Pop3UidlEntry *) PL_HashTableLookup(hashTable, uidl);
Pop3UidlEntry *uidlEntry = (Pop3UidlEntry *) PL_HashTableLookup(hashTable, uidlE->uidl);
if (uidlEntry)
{
char newStatus = (deleteChar) ? DELETE_CHAR : KEEP;
if (uidlEntry->status != newStatus)
if (uidlEntry->status != uidlE->status)
{
uidlEntry->status = newStatus;
uidlEntry->status = uidlE->status;
*changed = PR_TRUE;
}
}
@ -462,10 +462,9 @@ void nsPop3Protocol::MarkMsgDeletedInHashTable(PLHashTable *hashTable, const cha
/* static */
nsresult
nsPop3Protocol::MarkMsgDeletedForHost(const char *hostName, const char *userName,
nsPop3Protocol::MarkMsgForHost(const char *hostName, const char *userName,
nsIFileSpec *mailDirectory,
nsCStringArray &UIDLArray,
PRBool deleteMsgs)
nsVoidArray &UIDLArray)
{
if (!hostName || !userName || !mailDirectory)
return NS_ERROR_NULL_POINTER;
@ -478,7 +477,10 @@ nsPop3Protocol::MarkMsgDeletedForHost(const char *hostName, const char *userName
PRUint32 count = UIDLArray.Count();
for (PRUint32 i = 0; i < count; i++)
MarkMsgDeletedInHashTable(uidlHost->hash, UIDLArray[i]->get(), deleteMsgs, &changed);
{
MarkMsgInHashTable(uidlHost->hash,
NS_STATIC_CAST(Pop3UidlEntry*,UIDLArray[i]), &changed);
}
if (changed)
net_pop3_write_state(uidlHost, mailDirectory);
@ -798,6 +800,7 @@ nsresult nsPop3Protocol::LoadUrl(nsIURI* aURL, nsISupports * /* aConsumer */)
// size limit
m_pop3Server->GetLeaveMessagesOnServer(&m_pop3ConData->leave_on_server);
m_pop3Server->GetHeadersOnly(&m_pop3ConData->headers_only);
PRBool limitMessageSize = PR_FALSE;
nsCOMPtr<nsIMsgIncomingServer> server = do_QueryInterface(m_pop3Server);
@ -2396,7 +2399,7 @@ PRInt32 nsPop3Protocol::GetUidlList(nsIInputStream* inputStream,
PRInt32
nsPop3Protocol::GetMsg()
{
char c;
char c = 0;
int i;
PRBool prefBool = PR_FALSE;
PRInt32 popstateTimestamp = TimeInSecondsFromPRTime(PR_Now());
@ -2636,10 +2639,18 @@ nsPop3Protocol::GetMsg()
{
m_pop3ConData->next_state = POP3_GET_MSG;
}
else if ((c != TOO_BIG) && (m_pop3ConData->size_limit > 0) &&
(info->size > m_pop3ConData->size_limit) &&
else if (c == FETCH_BODY)
{
m_pop3ConData->next_state = POP3_SEND_RETR;
PL_HashTableRemove (m_pop3ConData->uidlinfo->hash, (void*)
info->uidl);
}
else if ((c != TOO_BIG) &&
(TestCapFlag(POP3_TOP_UNDEFINED | POP3_HAS_TOP)) &&
!m_pop3ConData->only_uidl)
(m_pop3ConData->headers_only ||
((m_pop3ConData->size_limit > 0) &&
(info->size > m_pop3ConData->size_limit) &&
!m_pop3ConData->only_uidl)))
{
/* message is too big */
m_pop3ConData->truncating_cur_msg = PR_TRUE;
@ -2678,7 +2689,7 @@ nsPop3Protocol::GetMsg()
// if this is a message we already know about (i.e., it was in popstate.dat already),
// we need to maintain the original date the message was downloaded.
if (info->uidl && !m_pop3ConData->only_uidl && !m_pop3ConData->truncating_cur_msg)
if (info->uidl && !m_pop3ConData->only_uidl && !m_pop3ConData->truncating_cur_msg)
/* message already marked as too_big */
put_hash(m_pop3ConData->newuidl, info->uidl, KEEP, popstateTimestamp);
}
@ -2694,8 +2705,9 @@ nsPop3Protocol::GetMsg()
*/
PRInt32 nsPop3Protocol::SendTop()
{
char * cmd = PR_smprintf( "TOP %ld 20" CRLF,
m_pop3ConData->msg_info[m_pop3ConData->last_accessed_msg].msgnum);
char * cmd = PR_smprintf( "TOP %ld %d" CRLF,
m_pop3ConData->msg_info[m_pop3ConData->last_accessed_msg].msgnum,
m_pop3ConData->headers_only ? 0 : 20);
PRInt32 status = -1;
if (cmd)
{
@ -2841,7 +2853,6 @@ nsPop3Protocol::RetrResponse(nsIInputStream* inputStream,
*/
if (m_pop3ConData->truncating_cur_msg)
{ /* TOP, truncated message */
m_pop3ConData->cur_msg_size = m_pop3ConData->size_limit;
flags |= MSG_FLAG_PARTIAL;
}
else
@ -2910,8 +2921,8 @@ nsPop3Protocol::RetrResponse(nsIInputStream* inputStream,
nsCOMPtr<nsIMsgWindow> msgWindow;
if (NS_SUCCEEDED(rv))
rv = mailnewsUrl->GetMsgWindow(getter_AddRefs(msgWindow));
rv = m_nsIPop3Sink->IncorporateComplete(msgWindow);
rv = m_nsIPop3Sink->IncorporateComplete(msgWindow,
m_pop3ConData->truncating_cur_msg ? m_pop3ConData->cur_msg_size : 0);
// The following was added to prevent the loss of Data when we try
// and write to somewhere we dont have write access error to (See
// bug 62480)
@ -2980,7 +2991,8 @@ nsPop3Protocol::RetrResponse(nsIInputStream* inputStream,
if (NS_SUCCEEDED(rv))
rv = mailnewsUrl->GetMsgWindow(getter_AddRefs(msgWindow));
rv =
m_nsIPop3Sink->IncorporateComplete(msgWindow);
m_nsIPop3Sink->IncorporateComplete(msgWindow,
m_pop3ConData->truncating_cur_msg ? m_pop3ConData->cur_msg_size : 0);
// The following was added to prevent the loss of Data when we try
// and write to somewhere we dont have write access error to (See
@ -3001,10 +3013,34 @@ nsPop3Protocol::RetrResponse(nsIInputStream* inputStream,
if (m_pop3ConData->truncating_cur_msg ||
m_pop3ConData->leave_on_server )
{
Pop3UidlEntry *uidlEntry = NULL;
// A filter might have decided to retrieve this full msg
if (m_pop3ConData->truncating_cur_msg)
{
Pop3MsgInfo* info = m_pop3ConData->msg_info + m_pop3ConData->last_accessed_msg;
uidlEntry = (Pop3UidlEntry *)PL_HashTableLookup(m_pop3ConData->newuidl, info->uidl);
}
if (uidlEntry && uidlEntry->status == FETCH_BODY)
{
// A filter decided to retrieve this full msg
m_pop3ConData->next_state = POP3_SEND_RETR;
m_pop3ConData->truncating_cur_msg = PR_FALSE;
} else
{
/* We've retrieved all or part of this message, but we want to
keep it on the server. Go on to the next message. */
m_pop3ConData->last_accessed_msg++;
m_pop3ConData->next_state = POP3_GET_MSG;
m_pop3ConData->last_accessed_msg++;
m_pop3ConData->next_state = POP3_GET_MSG;
}
if (m_pop3ConData->only_uidl)
{
/* GetMsg didn't update this field. Do it now. */
uidlEntry = (Pop3UidlEntry *)PL_HashTableLookup(m_pop3ConData->uidlinfo->hash, m_pop3ConData->only_uidl);
NS_ASSERTION(uidlEntry, "uidl not found in uidlinfo");
if (uidlEntry)
put_hash(m_pop3ConData->uidlinfo->hash, m_pop3ConData->only_uidl, KEEP, uidlEntry->dateReceived);
}
} else
{
m_pop3ConData->next_state = POP3_SEND_DELE;
@ -3122,7 +3158,8 @@ nsPop3Protocol::HandleLine(char *line, PRUint32 line_length)
nsCOMPtr<nsIMsgWindow> msgWindow;
if (NS_SUCCEEDED(rv))
rv = mailnewsUrl->GetMsgWindow(getter_AddRefs(msgWindow));
rv = m_nsIPop3Sink->IncorporateComplete(msgWindow);
rv = m_nsIPop3Sink->IncorporateComplete(msgWindow,
m_pop3ConData->truncating_cur_msg ? m_pop3ConData->cur_msg_size : 0);
// The following was added to prevent the loss of Data when we try
// and write to somewhere we dont have write access error to (See
@ -3711,7 +3748,7 @@ nsresult nsPop3Protocol::CloseSocket()
return rv;
}
NS_IMETHODIMP nsPop3Protocol::MarkMessagesDeleted(nsCStringArray *aUIDLArray, PRBool aDeleteMsgs)
NS_IMETHODIMP nsPop3Protocol::MarkMessages(nsVoidArray *aUIDLArray)
{
NS_ENSURE_ARG_POINTER(aUIDLArray);
PRUint32 count = aUIDLArray->Count();
@ -3720,9 +3757,9 @@ NS_IMETHODIMP nsPop3Protocol::MarkMessagesDeleted(nsCStringArray *aUIDLArray, PR
{
PRBool changed;
if (m_pop3ConData->newuidl)
MarkMsgDeletedInHashTable(m_pop3ConData->newuidl, aUIDLArray->CStringAt(i)->get(), aDeleteMsgs, &changed);
MarkMsgInHashTable(m_pop3ConData->newuidl, NS_STATIC_CAST(Pop3UidlEntry*,aUIDLArray->ElementAt(i)), &changed);
if (m_pop3ConData->uidlinfo)
MarkMsgDeletedInHashTable(m_pop3ConData->uidlinfo->hash, aUIDLArray->CStringAt(i)->get(), aDeleteMsgs, &changed);
MarkMsgInHashTable(m_pop3ConData->uidlinfo->hash, NS_STATIC_CAST(Pop3UidlEntry*,aUIDLArray->ElementAt(i)), &changed);
}
return NS_OK;
}

View File

@ -175,10 +175,11 @@ enum Pop3StatesEnum {
#define KEEP 'k' /* If we want to keep this item on server. */
#define DELETE_CHAR 'd' /* If we want to delete this item. */
#define TOO_BIG 'b' /* item left on server because it was too big */
#define FETCH_BODY 'f' /* Fetch full body of a partial msg */
typedef struct Pop3UidlEntry { /* information about this message */
char* uidl;
char status; // KEEP=='k', DELETE='d' TOO_BIG='b'
char status; // KEEP=='k', DELETE='d' TOO_BIG='b' FETCH_BODY='f'
PRInt32 dateReceived; // time message received, used for aging
} Pop3UidlEntry;
@ -199,6 +200,8 @@ typedef struct Pop3MsgInfo {
typedef struct _Pop3ConData {
PRBool leave_on_server; /* Whether we're supposed to leave messages
on server. */
PRBool headers_only; /* Whether to just fetch headers on initial
downloads. */
PRInt32 size_limit; /* Leave messages bigger than this on the
server and only download a partial
message. */
@ -299,13 +302,12 @@ public:
// for nsMsgLineBuffer
virtual PRInt32 HandleLine(char *line, PRUint32 line_length);
static void MarkMsgDeletedInHashTable(PLHashTable *hashTable, const char *uidl,
PRBool deleteChar, PRBool *changed);
static void MarkMsgInHashTable(PLHashTable *hashTable, const Pop3UidlEntry *uidl,
PRBool *changed);
static nsresult MarkMsgDeletedForHost(const char *hostName, const char *userName,
static nsresult MarkMsgForHost(const char *hostName, const char *userName,
nsIFileSpec *mailDirectory,
nsCStringArray &UIDLArray,
PRBool deleteMsgs);
nsVoidArray &UIDLArray);
private:
nsCString m_ApopTimestamp;
nsCOMPtr<nsIMsgStringService> mStringService;

View File

@ -533,7 +533,7 @@ nsresult nsPop3Sink::WriteLineToMailbox(const char *buffer)
}
NS_IMETHODIMP
nsPop3Sink::IncorporateComplete(nsIMsgWindow *aMsgWindow)
nsPop3Sink::IncorporateComplete(nsIMsgWindow *aMsgWindow, PRInt32 aSize)
{
if (m_buildMessageUri && m_baseMessageUri)
{
@ -549,7 +549,14 @@ nsPop3Sink::IncorporateComplete(nsIMsgWindow *aMsgWindow)
if (NS_FAILED(rv)) return rv;
NS_ASSERTION(m_newMailParser, "could not get m_newMailParser");
if (m_newMailParser)
{
// PublishMsgHdr clears m_newMsgHdr, so we need a comptr to
// hold onto it.
nsCOMPtr <nsIMsgDBHdr> hdr = m_newMailParser->m_newMsgHdr;
m_newMailParser->PublishMsgHeader(aMsgWindow);
if (aSize)
hdr->SetUint32Property("onlineSize", aSize);
}
#ifdef DEBUG
printf("Incorporate message complete.\n");

View File

@ -284,3 +284,24 @@
## @name MIME_FORWARDED_MESSAGE_USER_WROTE
## @loc
1041=-------- Original Message --------
# Partial Message Format2 1
## @name MIME_MSG_PARTIAL_FMT2_1
## @loc
# LOCALIZATION NOTE (1037): In the following line, translate only the words, "Not Downloaded".
1042=<P><CENTER><TABLE BORDER CELLSPACING=5 CELLPADDING=10 WIDTH="80%%"><TR><TD ALIGN=CENTER><FONT SIZE="+1"><B>Not Downloaded</B></FONT><HR>
# Partial Message Format2 2
## @name MIME_MSG_PARTIAL_FMT2_2
## @loc
# LOCALIZATION NOTE (1038): Translate the following two lines as a single sentence. In the middle of the two sections
# there will be a URL. You may translate the text in any order you wish, but the html tags must stay in the same locations.
# In particular, the "<B>" tag must begin the first section, which must end with the "<A HREF=" tag. Do not translate the html tag,"<P>"
1043=<B>Only the headers for this message were downloaded from the mail server.<P>Click <A HREF="
# Partial Message Format2 3
## @name MIME_MSG_PARTIAL_FMT_3
## @loc
# LOCALIZATION NOTE (1039): This section must begin with the ">" sign and end with the tags,"</B></TD></TR></TABLE></CENTER>"
# Do not translate "</A>" tag.
1044=">here</A> to download the rest of the message.</B></TD></TR></TABLE></CENTER>

View File

@ -111,6 +111,7 @@ MimeMessage_initialize (MimeObject *object)
{
MimeMessage *msg = (MimeMessage *)object;
msg->grabSubject = PR_FALSE;
msg->bodyLength = 0;
return ((MimeObjectClass*)&MIME_SUPERCLASS)->initialize(object);
}
@ -193,6 +194,8 @@ MimeMessage_parse_line (char *aLine, PRInt32 aLength, MimeObject *obj)
PR_ASSERT(kid);
if (!kid) return -1;
msg->bodyLength += length;
/* Don't allow MimeMessage objects to not end in a newline, since it
would be inappropriate for any following part to appear on the same
line as the last line of the message.
@ -521,8 +524,11 @@ MimeMessage_close_headers (MimeObject *obj)
char dummy = 0;
if (sscanf(xmoz, " %lx %c", &flags, &dummy) == 1 &&
flags & MSG_FLAG_PARTIAL)
{
obj->options->html_closure = obj;
obj->options->generate_footer_html_fn =
MimeMessage_partial_message_html;
}
PR_FREEIF(xmoz);
}
}
@ -816,12 +822,14 @@ static char *
MimeMessage_partial_message_html(const char *data, void *closure,
MimeHeaders *headers)
{
MimeMessage *msg = (MimeMessage *)closure;
nsCAutoString orig_url(data);
char *partialMsgHtml = nsnull;
char *uidl = MimeHeaders_get(headers, HEADER_X_UIDL, PR_FALSE, PR_FALSE);
char *msgId = MimeHeaders_get(headers, HEADER_MESSAGE_ID, PR_FALSE,
PR_FALSE);
char *msgIdPtr = PL_strstr(msgId, "<");
int msgBase;
orig_url.ReplaceSubstring("mailbox-message", "mailbox");
orig_url.ReplaceSubstring("#", "?number=");
@ -834,11 +842,12 @@ MimeMessage_partial_message_html(const char *data, void *closure,
if (gtPtr)
*gtPtr = 0;
msgBase = (msg->bodyLength > MSG_LINEBREAK_LEN) ? MIME_MSG_PARTIAL_FMT_1 : MIME_MSG_PARTIAL_FMT2_1;
char *escapedUidl = uidl ? nsEscape(uidl, url_XAlphas) : nsnull;
char *escapedMsgId = msgIdPtr ? nsEscape(msgIdPtr, url_Path) : nsnull;
char *fmt1 = MimeGetStringByID(1037);
char *fmt2 = MimeGetStringByID(1038);
char *fmt3 = MimeGetStringByID(1039);
char *fmt1 = MimeGetStringByID(msgBase);
char *fmt2 = MimeGetStringByID(msgBase+1);
char *fmt3 = MimeGetStringByID(msgBase+2);
char *msgUrl = PR_smprintf("%s&messageid=%s&uidl=%s",
orig_url.get(), escapedMsgId, escapedUidl);
partialMsgHtml = PR_smprintf("%s%s%s%s", fmt1,fmt2, msgUrl, fmt3);

View File

@ -64,6 +64,7 @@ struct MimeMessage {
PRBool crypto_msg_signed_p; /* What the emitted xlation-stamp *says*. */
PRBool crypto_msg_encrypted_p;
PRBool grabSubject; /* Should we try to grab the subject of this message */
PRInt32 bodyLength;
};
#endif /* _MIMEMSG_H_ */

View File

@ -82,5 +82,8 @@
#define MIME_MSG_PARTIAL_FMT_3 1039
#define MIME_MSG_DEFAULT_ATTACHMENT_NAME 1040
#define MIME_FORWARDED_MESSAGE_HTML_USER_WROTE 1041
#define MIME_MSG_PARTIAL_FMT2_1 1042
#define MIME_MSG_PARTIAL_FMT2_2 1043
#define MIME_MSG_PARTIAL_FMT2_3 1044
#endif /* _NAME_OF_THIS_HEADER_FILE__ */