bunch of stuff to get message header download working

This commit is contained in:
bienvenu%netscape.com 1999-04-09 01:46:22 +00:00
Родитель 72bc82580f
Коммит c48b623977
12 изменённых файлов: 420 добавлений и 82 удалений

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

@ -133,6 +133,8 @@ public:
NS_IMETHOD GetImapPartToFetch(char **resultPart) const = 0;
NS_IMETHOD AllocateCannonicalPath(const char *serverPath, char onlineDelimiter, char **allocatedPath ) const = 0;
NS_IMETHOD CreateListOfMessageIdsString(char **result) const = 0;
};
#endif /* nsIImapUrl_h___ */

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

@ -56,6 +56,7 @@ CPP_OBJS= .\$(OBJDIR)\nsImapUrl.obj \
EXPORTS= nsImapUrl.h \
nsImapProtocol.h \
nsImapCore.h \
nsImapFlagAndUidState.h \
nsImapProxyEvent.h \
nsImapHostSessionList.h \
nsImapService.h \

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

@ -68,10 +68,8 @@ nsIMAPBodyShell::nsIMAPBodyShell(nsImapProtocol *protocolConnection, const char
NS_ASSERTION(buf, "null buffer passed to nsIMAPBodyShell constructor");
if (!buf)
return;
m_UID = PR_smprintf("%ld",UID);
NS_ASSERTION(m_UID, "out of memory in body shell");
if (!m_UID)
return;
m_UID = "";
m_UID.Append(UID, 10);
#ifdef DEBUG_chrisf
NS_ASSERTION(folderName);
#endif
@ -95,7 +93,6 @@ nsIMAPBodyShell::~nsIMAPBodyShell()
{
delete m_message;
delete m_prefetchQueue;
PR_FREEIF(m_UID);
PR_FREEIF(m_folderName);
}
@ -1509,7 +1506,7 @@ PRBool nsIMAPBodyShellCache::EjectEntry()
nsIMAPBodyShell *removedShell = (nsIMAPBodyShell *) (m_shellList->ElementAt(0));
m_shellList->RemoveElementAt(0);
nsCStringKey hashKey (removedShell->GetUID());
nsCStringKey hashKey (removedShell->GetUID().GetBuffer());
m_shellHash->Remove(&hashKey);
delete removedShell;
@ -1529,11 +1526,11 @@ PRBool nsIMAPBodyShellCache::AddShellToCache(nsIMAPBodyShell *shell)
// First, for safety sake, remove any entry with the given UID,
// just in case we have a collision between two messages in different
// folders with the same UID.
nsCStringKey hashKey1(shell->GetUID());
nsCStringKey hashKey1(shell->GetUID().GetBuffer());
nsIMAPBodyShell *foundShell = (nsIMAPBodyShell *) m_shellHash->Get(&hashKey1);
if (foundShell)
{
nsCStringKey hashKey(foundShell->GetUID());
nsCStringKey hashKey(foundShell->GetUID().GetBuffer());
m_shellHash->Remove(&hashKey);
m_shellList->RemoveElement(foundShell);
}
@ -1541,7 +1538,7 @@ PRBool nsIMAPBodyShellCache::AddShellToCache(nsIMAPBodyShell *shell)
// Add the new one to the cache
m_shellList->AppendElement(shell);
nsCStringKey hashKey2 (shell->GetUID());
nsCStringKey hashKey2 (shell->GetUID().GetBuffer());
m_shellHash->Put(&hashKey2, shell);
shell->SetIsCached(TRUE);
@ -1556,12 +1553,12 @@ PRBool nsIMAPBodyShellCache::AddShellToCache(nsIMAPBodyShell *shell)
}
nsIMAPBodyShell *nsIMAPBodyShellCache::FindShellForUID(const char *UID, const char *mailboxName)
nsIMAPBodyShell *nsIMAPBodyShellCache::FindShellForUID(nsString2 &UID, const char *mailboxName)
{
if (!UID)
return NULL;
nsCStringKey hashKey(UID);
nsCStringKey hashKey(UID.GetBuffer());
nsIMAPBodyShell *foundShell = (nsIMAPBodyShell *) m_shellHash->Get(&hashKey);
if (!foundShell)
@ -1580,9 +1577,10 @@ nsIMAPBodyShell *nsIMAPBodyShellCache::FindShellForUID(const char *UID, const ch
nsIMAPBodyShell *nsIMAPBodyShellCache::FindShellForUID(PRUint32 UID, const char *mailboxName)
{
char *uidString = PR_smprintf("%ld", UID);
nsString2 uidString;
uidString.Append(UID, 10);
nsIMAPBodyShell *rv = FindShellForUID(uidString, mailboxName);
PR_FREEIF(uidString);
return rv;
}

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

@ -25,6 +25,7 @@ nsIMAPBodyShell and associated classes
#include "nsImapCore.h"
#include "nsIMAPGenericParser.h"
#include "nsString2.h"
class nsImapProtocol;
@ -259,7 +260,7 @@ public:
nsImapProtocol *GetConnection() { return m_protocolConnection; }
PRBool GetPseudoInterrupted();
PRBool DeathSignalReceived();
const char *GetUID() { return m_UID; }
nsString2 &GetUID() { return m_UID; }
const char *GetFolderName() { return m_folderName; }
char *GetGeneratingPart() { return m_generatingPart; }
PRBool IsBeingGenerated() { return m_isBeingGenerated; } // Returns TRUE if this is in the process of being
@ -276,7 +277,7 @@ protected:
PRBool m_isValid;
nsImapProtocol *m_protocolConnection; // Connection, for filling in parts
char *m_UID; // UID of this message
nsString2 m_UID; // UID of this message
char *m_folderName; // folder that contains this message
char *m_generatingPart; // If a specific part is being generated, this is it. Otherwise, NULL.
PRBool m_isBeingGenerated; // TRUE if this body shell is in the process of being generated
@ -308,7 +309,7 @@ public:
PRBool AddShellToCache(nsIMAPBodyShell *shell); // Adds shell to cache, possibly ejecting
// another entry based on scheme in EjectEntry().
nsIMAPBodyShell *FindShellForUID(const char *UID, const char *mailboxName); // Looks up a shell in the cache given the message's UID.
nsIMAPBodyShell *FindShellForUID(nsString2 &UID, const char *mailboxName); // Looks up a shell in the cache given the message's UID.
nsIMAPBodyShell *FindShellForUID(PRUint32 UID, const char *mailboxName); // Looks up a shell in the cache given the message's UID.
// Returns the shell if found, NULL if not found.

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

@ -619,12 +619,14 @@ NS_IMETHODIMP nsIMAPHostSessionList::AddShellToCacheForHost(const char *hostName
NS_IMETHODIMP nsIMAPHostSessionList::FindShellInCacheForHost(const char *hostName, const char *userName, const char *mailboxName, const char *UID, nsIMAPBodyShell &shell)
{
nsString2 uidString = UID;
PR_EnterMonitor(gCachedHostInfoMonitor);
nsIMAPHostInfo *host = FindHost(hostName, userName);
if (host)
{
if (host->fShellCache)
shell = *host->fShellCache->FindShellForUID(UID, mailboxName);
shell = *host->fShellCache->FindShellForUID(uidString, mailboxName);
}
PR_ExitMonitor(gCachedHostInfoMonitor);
return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;

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

@ -221,7 +221,7 @@ typedef struct _TunnelInfo {
typedef struct _delete_message_struct {
char *onlineFolderName;
XP_Bool deleteAllMsgs;
PRBool deleteAllMsgs;
char *msgIdString;
} delete_message_struct;
@ -259,8 +259,8 @@ typedef struct _MessageSizeInfo
{
char *id;
char *folderName;
XP_Bool idIsUid;
uint32 size;
PRBool idIsUid;
PRUint32 size;
} MessageSizeInfo;
@ -286,17 +286,17 @@ public:
TLineDownloadCache();
virtual ~TLineDownloadCache();
uint32 CurrentUID();
uint32 SpaceAvailable();
XP_Bool CacheEmpty();
PRUint32 CurrentUID();
PRUint32 SpaceAvailable();
PRBool CacheEmpty();
msg_line_info *GetCurrentLineInfo();
void ResetCache();
void CacheLine(const char *line, uint32 uid);
void CacheLine(const char *line, PRUint32 uid);
private:
char fLineCache[kDownLoadCacheSize];
uint32 fBytesUsed;
PRUint32 fBytesUsed;
msg_line_info *fLineInfo;

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

@ -22,14 +22,13 @@
#include "nsImapFlagAndUidState.h"
/* amount to expand for imap entry flags when we need more */
const PRInt32 kFlagEntrySize = 100;
nsImapFlagAndUidState::nsImapFlagAndUidState(PRInt32 numberOfMessages, PRUint16 flags)
{
fNumberOfMessagesAdded = 0;
fNumberOfMessageSlotsAllocated = numberOfMessages;
if (!fNumberOfMessageSlotsAllocated)
fNumberOfMessageSlotsAllocated = kFlagEntrySize;
fNumberOfMessageSlotsAllocated = kImapFlagAndUidStateSize;
fFlags = (imapMessageFlagsType*) PR_Malloc(sizeof(imapMessageFlagsType) * fNumberOfMessageSlotsAllocated); // new imapMessageFlagsType[fNumberOfMessageSlotsAllocated];
fUids.SetSize(fNumberOfMessageSlotsAllocated);
@ -100,7 +99,7 @@ void nsImapFlagAndUidState::AddUidFlagPair(PRUint32 uid, imapMessageFlagsType fl
// make sure there is room for this pair
if (fNumberOfMessagesAdded >= fNumberOfMessageSlotsAllocated)
{
fNumberOfMessageSlotsAllocated += kFlagEntrySize;
fNumberOfMessageSlotsAllocated += kImapFlagAndUidStateSize;
fUids.SetSize(fNumberOfMessageSlotsAllocated);
fFlags = (imapMessageFlagsType*) PR_REALLOC(fFlags, sizeof(imapMessageFlagsType) * fNumberOfMessageSlotsAllocated); // new imapMessageFlagsType[fNumberOfMessageSlotsAllocated];
}

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

@ -21,6 +21,8 @@
#include "nsMsgKeyArray.h"
const PRInt32 kImapFlagAndUidStateSize = 100;
class nsImapFlagAndUidState {
public:
nsImapFlagAndUidState(int numberOfMessages, PRUint16 flags = 0);

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

@ -50,6 +50,8 @@ static NS_DEFINE_CID(kNetServiceCID, NS_NETSERVICE_CID);
#define IMAP_DB_HEADERS "From To Cc Subject Date Priority X-Priority Message-ID References Newsgroups"
static const int32 kImapSleepTime = 1000000;
// **** helper class for downloading line ****
TLineDownloadCache::TLineDownloadCache()
{
@ -64,12 +66,12 @@ TLineDownloadCache::~TLineDownloadCache()
PR_FREEIF( fLineInfo);
}
uint32 TLineDownloadCache::CurrentUID()
PRUint32 TLineDownloadCache::CurrentUID()
{
return fLineInfo->uidOfMessage;
}
uint32 TLineDownloadCache::SpaceAvailable()
PRUint32 TLineDownloadCache::SpaceAvailable()
{
return kDownLoadCacheSize - fBytesUsed;
}
@ -84,14 +86,14 @@ void TLineDownloadCache::ResetCache()
fBytesUsed = 0;
}
XP_Bool TLineDownloadCache::CacheEmpty()
PRBool TLineDownloadCache::CacheEmpty()
{
return fBytesUsed == 0;
}
void TLineDownloadCache::CacheLine(const char *line, uint32 uid)
void TLineDownloadCache::CacheLine(const char *line, PRUint32 uid)
{
uint32 lineLength = PL_strlen(line);
PRUint32 lineLength = PL_strlen(line);
NS_ASSERTION((lineLength + 1) <= SpaceAvailable(),
"Oops... line length greater than space available");
@ -142,7 +144,7 @@ NS_IMETHODIMP nsImapProtocol::QueryInterface(const nsIID &aIID, void** aInstance
}
nsImapProtocol::nsImapProtocol() :
m_parser(*this), m_currentCommand(eOneByte, 0)
m_parser(*this), m_currentCommand(eOneByte, 0), m_flagState(kImapFlagAndUidStateSize, PR_FALSE)
{
NS_INIT_REFCNT();
m_runningUrl = nsnull; // initialize to NULL
@ -163,6 +165,8 @@ nsImapProtocol::nsImapProtocol() :
m_dataMemberMonitor = nsnull;
m_threadDeathMonitor = nsnull;
m_eventCompletionMonitor = nsnull;
m_waitForBodyIdsMonitor = nsnull;
m_fetchMsgListMonitor = nsnull;
m_imapThreadIsRunning = PR_FALSE;
m_consumer = nsnull;
m_currentServerCommandTagNumber = 0;
@ -256,6 +260,16 @@ nsImapProtocol::~nsImapProtocol()
PR_DestroyMonitor(m_eventCompletionMonitor);
m_eventCompletionMonitor = nsnull;
}
if (m_waitForBodyIdsMonitor)
{
PR_DestroyMonitor(m_waitForBodyIdsMonitor);
m_waitForBodyIdsMonitor = nsnull;
}
if (m_fetchMsgListMonitor)
{
PR_DestroyMonitor(m_fetchMsgListMonitor);
m_fetchMsgListMonitor = nsnull;
}
}
const char*
@ -427,6 +441,8 @@ void nsImapProtocol::SetupWithUrl(nsIURL * aURL)
m_dataMemberMonitor = PR_NewMonitor();
m_threadDeathMonitor = PR_NewMonitor();
m_eventCompletionMonitor = PR_NewMonitor();
m_waitForBodyIdsMonitor = PR_NewMonitor();
m_fetchMsgListMonitor = PR_NewMonitor();
m_thread = PR_CreateThread(PR_USER_THREAD, ImapThreadMain, (void*)
this, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
@ -849,19 +865,19 @@ nsImapProtocol::AdjustChunkSize()
// message...
void
nsImapProtocol::FetchMessage(const char *messageIds,
nsImapProtocol::FetchMessage(nsString2 &messageIds,
nsIMAPeFetchFields whatToFetch,
PRBool idIsUid,
uint32 startByte, uint32 endByte,
PRUint32 startByte, PRUint32 endByte,
char *part)
{
IncrementCommandTagNumber();
char commandString[350];
nsString2 commandString;
if (idIsUid)
PL_strcpy(commandString, "%s UID fetch");
commandString = "%s UID fetch";
else
PL_strcpy(commandString, "%s fetch");
commandString = "%s fetch";
switch (whatToFetch) {
case kEveryThingRFC822:
@ -872,16 +888,16 @@ nsImapProtocol::FetchMessage(const char *messageIds,
if (GetServerStateParser().ServerHasIMAP4Rev1Capability())
{
if (GetServerStateParser().GetCapabilityFlag() & kHasXSenderCapability)
PL_strcat(commandString, " %s (XSENDER UID RFC822.SIZE BODY[]");
commandString.Append(" %s (XSENDER UID RFC822.SIZE BODY[]");
else
PL_strcat(commandString, " %s (UID RFC822.SIZE BODY[]");
commandString.Append(" %s (UID RFC822.SIZE BODY[]");
}
else
{
if (GetServerStateParser().GetCapabilityFlag() & kHasXSenderCapability)
PL_strcat(commandString, " %s (XSENDER UID RFC822.SIZE RFC822");
commandString.Append(" %s (XSENDER UID RFC822.SIZE RFC822");
else
PL_strcat(commandString, " %s (UID RFC822.SIZE RFC822");
commandString.Append(" %s (UID RFC822.SIZE RFC822");
}
if (endByte > 0)
{
@ -889,17 +905,17 @@ nsImapProtocol::FetchMessage(const char *messageIds,
char *byterangeString = PR_smprintf("<%ld.%ld>",startByte,endByte);
if (byterangeString)
{
PL_strcat(commandString, byterangeString);
commandString.Append(byterangeString);
PR_Free(byterangeString);
}
}
PL_strcat(commandString, ")");
commandString.Append(")");
break;
case kEveryThingRFC822Peek:
{
char *formatString = "";
uint32 server_capabilityFlags = GetServerStateParser().GetCapabilityFlag();
PRUint32 server_capabilityFlags = GetServerStateParser().GetCapabilityFlag();
if (server_capabilityFlags & kIMAP4rev1Capability)
{
@ -917,7 +933,7 @@ nsImapProtocol::FetchMessage(const char *messageIds,
formatString = " %s (UID RFC822.SIZE RFC822.peek)";
}
PL_strcat(commandString, formatString);
commandString.Append(formatString);
}
break;
case kHeadersRFC822andUid:
@ -943,46 +959,46 @@ nsImapProtocol::FetchMessage(const char *messageIds,
char *what = PR_smprintf(" BODY.PEEK[HEADER.FIELDS (%s)])", headersToDL);
if (what)
{
PL_strcat(commandString, " %s (UID RFC822.SIZE FLAGS");
PL_strcat(commandString, what);
commandString.Append(" %s (UID RFC822.SIZE FLAGS");
commandString.Append(what);
PR_Free(what);
}
else
{
PL_strcat(commandString, " %s (UID RFC822.SIZE BODY.PEEK[HEADER] FLAGS)");
commandString.Append(" %s (UID RFC822.SIZE BODY.PEEK[HEADER] FLAGS)");
}
PR_Free(headersToDL);
}
else
{
PL_strcat(commandString, " %s (UID RFC822.SIZE BODY.PEEK[HEADER] FLAGS)");
commandString.Append(" %s (UID RFC822.SIZE BODY.PEEK[HEADER] FLAGS)");
}
}
else
PL_strcat(commandString, " %s (UID RFC822.SIZE BODY.PEEK[HEADER] FLAGS)");
commandString.Append(" %s (UID RFC822.SIZE BODY.PEEK[HEADER] FLAGS)");
}
else
PL_strcat(commandString, " %s (UID RFC822.SIZE RFC822.HEADER FLAGS)");
commandString.Append(" %s (UID RFC822.SIZE RFC822.HEADER FLAGS)");
break;
case kUid:
PL_strcat(commandString, " %s (UID)");
commandString.Append(" %s (UID)");
break;
case kFlags:
PL_strcat(commandString, " %s (FLAGS)");
commandString.Append(" %s (FLAGS)");
break;
case kRFC822Size:
PL_strcat(commandString, " %s (RFC822.SIZE)");
commandString.Append(" %s (RFC822.SIZE)");
break;
case kRFC822HeadersOnly:
if (GetServerStateParser().ServerHasIMAP4Rev1Capability())
{
if (part)
{
PL_strcat(commandString, " %s (BODY[");
commandString.Append(" %s (BODY[");
char *what = PR_smprintf("%s.HEADER])", part);
if (what)
{
PL_strcat(commandString, what);
commandString.Append(what);
PR_Free(what);
}
else
@ -991,36 +1007,36 @@ nsImapProtocol::FetchMessage(const char *messageIds,
else
{
// headers for the top-level message
PL_strcat(commandString, " %s (BODY[HEADER])");
commandString.Append(" %s (BODY[HEADER])");
}
}
else
PL_strcat(commandString, " %s (RFC822.HEADER)");
commandString.Append(" %s (RFC822.HEADER)");
break;
case kMIMEPart:
PL_strcat(commandString, " %s (BODY[%s]");
commandString.Append(" %s (BODY[%s]");
if (endByte > 0)
{
// if we are retrieving chunks
char *byterangeString = PR_smprintf("<%ld.%ld>",startByte,endByte);
if (byterangeString)
{
PL_strcat(commandString, byterangeString);
commandString.Append(byterangeString);
PR_Free(byterangeString);
}
}
PL_strcat(commandString, ")");
commandString.Append(")");
break;
case kMIMEHeader:
PL_strcat(commandString, " %s (BODY[%s.MIME])");
commandString.Append(" %s (BODY[%s.MIME])");
break;
};
PL_strcat(commandString,CRLF);
commandString.Append(CRLF);
// since messageIds can be infinitely long, use a dynamic buffer rather than the fixed one
const char *commandTag = GetServerCommandTag();
int protocolStringSize = PL_strlen(commandString) + PL_strlen(messageIds) + PL_strlen(commandTag) + 1 +
int protocolStringSize = commandString.Length() + messageIds.Length() + PL_strlen(commandTag) + 1 +
(part ? PL_strlen(part) : 0);
char *protocolString = (char *) PR_Malloc( protocolStringSize );
@ -1031,18 +1047,18 @@ nsImapProtocol::FetchMessage(const char *messageIds,
{
PR_snprintf(protocolString, // string to create
protocolStringSize, // max size
commandString, // format string
commandString.GetBuffer(), // format string
commandTag, // command tag
messageIds,
messageIds.GetBuffer(),
part);
}
else
{
PR_snprintf(protocolString, // string to create
protocolStringSize, // max size
commandString, // format string
commandString.GetBuffer(), // format string
commandTag, // command tag
messageIds);
messageIds.GetBuffer());
}
int ioStatus = SendData(protocolString);
@ -1055,7 +1071,7 @@ nsImapProtocol::FetchMessage(const char *messageIds,
HandleMemoryFailure();
}
void nsImapProtocol::FetchTryChunking(const char *messageIds,
void nsImapProtocol::FetchTryChunking(nsString2 &messageIds,
nsIMAPeFetchFields whatToFetch,
PRBool idIsUid,
char *part,
@ -1104,7 +1120,7 @@ void nsImapProtocol::FetchTryChunking(const char *messageIds,
}
void nsImapProtocol::PipelinedFetchMessageParts(const char *uid, nsIMAPMessagePartIDArray *parts)
void nsImapProtocol::PipelinedFetchMessageParts(nsString2 &uid, nsIMAPMessagePartIDArray *parts)
{
// assumes no chunking
@ -1348,6 +1364,264 @@ void nsImapProtocol::AbortMessageDownLoad()
}
void nsImapProtocol::ProcessMailboxUpdate(PRBool handlePossibleUndo)
{
if (DeathSignalReceived())
return;
// fetch the flags and uids of all existing messages or new ones
if (!DeathSignalReceived() && GetServerStateParser().NumberOfMessages())
{
if (handlePossibleUndo)
{
// undo any delete flags we may have asked to
char *undoIds;
GetCurrentUrl()->CreateListOfMessageIdsString(&undoIds);
if (undoIds && *undoIds)
{
// if this string started with a '-', then this is an undo of a delete
// if its a '+' its a redo
if (*undoIds == '-')
Store(undoIds+1, "-FLAGS (\\Deleted)", TRUE); // most servers will fail silently on a failure, deal with it?
else if (*undoIds == '+')
Store(undoIds+1, "+FLAGS (\\Deleted)", TRUE); // most servers will fail silently on a failure, deal with it?
else
NS_ASSERTION(FALSE, "bogus undo Id's");
}
PR_FREEIF(undoIds);
}
// make the parser record these flags
nsString2 fetchStr;
PRUint32 added = 0, deleted = 0;
added = m_flagState.GetNumberOfMessages();
deleted = m_flagState.GetNumberOfDeletedMessages();
if (!added || (added == deleted))
{
nsString2 idsToFetch("1:*");
FetchMessage(idsToFetch, kFlags, TRUE); // id string shows uids
// lets see if we should expunge during a full sync of flags.
if (!DeathSignalReceived()) // only expunge if not reading messages manually and before fetching new
{
// ### TODO read gExpungeThreshhold from prefs.
if ((m_flagState.GetNumberOfDeletedMessages() >= 20/* gExpungeThreshold */) /*&&
GetDeleteIsMoveToTrash() */)
Expunge(); // might be expensive, test for user cancel
}
}
else {
fetchStr.Append(GetServerStateParser().HighestRecordedUID() + 1, 10);
fetchStr.Append(":*");
// sprintf(fetchStr, "%ld:*", GetServerStateParser().HighestRecordedUID() + 1);
FetchMessage(fetchStr, kFlags, TRUE); // only new messages please
}
}
else if (!DeathSignalReceived())
GetServerStateParser().ResetFlagInfo(0);
mailbox_spec *new_spec = GetServerStateParser().CreateCurrentMailboxSpec();
if (new_spec && !DeathSignalReceived())
{
#if 0
MWContext *ct = NULL;
LIBNET_LOCK();
if (!DeathSignalReceived())
{
// if this is an expunge url, libmsg will not ask for headers
if (fCurrentUrl->GetIMAPurlType() == TIMAPUrl::kExpungeFolder)
new_spec->box_flags |= kJustExpunged;
ct = new_spec->connection->fCurrentEntry->window_id;
ct->imapURLPane = MSG_FindPane(fCurrentEntry->window_id, MSG_ANYPANE);
}
LIBNET_UNLOCK();
if (ct)
{
if (!ct->currentIMAPfolder)
ct->currentIMAPfolder = (MSG_IMAPFolderInfoMail *) MSG_FindImapFolder(ct->imapURLPane, fCurrentUrl->GetUrlHost(), "INBOX"); // use real folder name
PR_EnterMonitor(fWaitForBodyIdsMonitor);
UpdatedMailboxSpec(new_spec);
}
#endif // 0
}
else if (!new_spec)
HandleMemoryFailure();
// Block until libmsg decides whether to download headers or not.
PRUint32 *msgIdList = NULL;
PRUint32 msgCount = 0;
if (!DeathSignalReceived())
{
WaitForPotentialListOfMsgsToFetch(&msgIdList, msgCount);
if (new_spec)
PR_ExitMonitor(m_waitForBodyIdsMonitor);
if (msgIdList && !DeathSignalReceived() && GetServerStateParser().LastCommandSuccessful())
{
FolderHeaderDump(msgIdList, msgCount);
PR_FREEIF( msgIdList);
}
// this might be bogus, how are we going to do pane notification and stuff when we fetch bodies without
// headers!
}
// wait for a list of bodies to fetch.
if (!DeathSignalReceived() && GetServerStateParser().LastCommandSuccessful())
{
WaitForPotentialListOfMsgsToFetch(&msgIdList, msgCount);
if ( msgCount && !DeathSignalReceived() && GetServerStateParser().LastCommandSuccessful())
{
FolderMsgDump(msgIdList, msgCount, kEveryThingRFC822Peek);
PR_FREEIF(msgIdList);
}
}
if (DeathSignalReceived())
GetServerStateParser().ResetFlagInfo(0);
}
void nsImapProtocol::FolderHeaderDump(PRUint32 *msgUids, PRUint32 msgCount)
{
FolderMsgDump(msgUids, msgCount, kHeadersRFC822andUid);
if (GetServerStateParser().NumberOfMessages())
HeaderFetchCompleted();
}
void nsImapProtocol::FolderMsgDump(PRUint32 *msgUids, PRUint32 msgCount, nsIMAPeFetchFields fields)
{
#if 0
// lets worry about this progress stuff later.
switch (fields) {
case TIMAP4BlockingConnection::kHeadersRFC822andUid:
fProgressStringId = XP_RECEIVING_MESSAGE_HEADERS_OF;
break;
case TIMAP4BlockingConnection::kFlags:
fProgressStringId = XP_RECEIVING_MESSAGE_FLAGS_OF;
break;
default:
fProgressStringId = XP_FOLDER_RECEIVING_MESSAGE_OF;
break;
}
fProgressIndex = 0;
fProgressCount = msgCount;
#endif // 0
FolderMsgDumpLoop(msgUids, msgCount, fields);
// fProgressStringId = 0;
}
void nsImapProtocol::WaitForPotentialListOfMsgsToFetch(PRUint32 **msgIdList, PRUint32 &msgCount)
{
PRIntervalTime sleepTime = kImapSleepTime;
PR_EnterMonitor(m_fetchMsgListMonitor);
while(!m_fetchMsgListIsNew && !DeathSignalReceived())
PR_Wait(m_fetchMsgListMonitor, sleepTime);
m_fetchMsgListIsNew = FALSE;
*msgIdList = m_fetchMsgIdList;
msgCount = m_fetchCount;
PR_ExitMonitor(m_fetchMsgListMonitor);
}
void nsImapProtocol::NotifyKeyList(PRUint32 *keys, PRUint32 keyCount)
{
PR_EnterMonitor(m_fetchMsgListMonitor);
m_fetchMsgIdList = keys;
m_fetchCount = keyCount;
m_fetchMsgListIsNew = TRUE;
PR_Notify(m_fetchMsgListMonitor);
PR_ExitMonitor(m_fetchMsgListMonitor);
}
void nsImapProtocol::FolderMsgDumpLoop(PRUint32 *msgUids, PRUint32 msgCount, nsIMAPeFetchFields fields)
{
// PastPasswordCheckEvent();
PRUint32 msgCountLeft = msgCount;
PRUint32 msgsDownloaded = 0;
do
{
nsString2 idString;
PRUint32 msgsToDownload = (msgCountLeft > 200) ? 200 : msgCountLeft;
AllocateImapUidString(msgUids + msgsDownloaded, msgsToDownload, idString); // 20 * 200
// except I don't think this works ### DB
FetchMessage(idString, fields, TRUE); // msg ids are uids
msgsDownloaded += msgsToDownload;
msgCountLeft -= msgsDownloaded;
}
while (msgCountLeft > 0);
}
void nsImapProtocol::HeaderFetchCompleted()
{
if (m_imapMiscellaneous)
m_imapMiscellaneous->HeaderFetchCompleted(this);
// need to block until this finishes - Jeff, how does that work?
}
void nsImapProtocol::AllocateImapUidString(PRUint32 *msgUids, PRUint32 msgCount, nsString2 &returnString)
{
int blocksAllocated = 1;
PRInt32 startSequence = (msgCount > 0) ? msgUids[0] : -1;
PRInt32 curSequenceEnd = startSequence;
PRUint32 total = msgCount;
for (PRUint32 keyIndex=0; keyIndex < total; keyIndex++)
{
PRInt32 curKey = msgUids[keyIndex];
PRInt32 nextKey = (keyIndex + 1 < total) ? msgUids[keyIndex + 1] : -1;
PRBool lastKey = (nextKey == -1);
if (lastKey)
curSequenceEnd = curKey;
if (nextKey == curSequenceEnd + 1 && !lastKey)
{
curSequenceEnd = nextKey;
continue;
}
else if (curSequenceEnd > startSequence)
{
returnString.Append(startSequence, 10);
returnString += ':';
returnString.Append(curSequenceEnd, 10);
if (!lastKey)
returnString += ',';
// sprintf(currentidString, "%ld:%ld,", startSequence, curSequenceEnd);
startSequence = nextKey;
curSequenceEnd = startSequence;
}
else
{
startSequence = nextKey;
curSequenceEnd = startSequence;
returnString.Append(msgUids[keyIndex], 10);
if (!lastKey)
returnString += ',';
// sprintf(currentidString, "%ld,", msgUids[keyIndex]);
}
}
}
// log info including current state...
void nsImapProtocol::Log(const char *logSubName, const char *extraInfo, const char *logData)
{
@ -1395,7 +1669,7 @@ void nsImapProtocol::Log(const char *logSubName, const char *extraInfo, const ch
// In 4.5, this posted an event back to libmsg and blocked until it got a response.
// We may still have to do this.It would be nice if we could preflight this value,
// but we may not always know when we'll need it.
PRUint32 nsImapProtocol::GetMessageSize(const char *messageId, PRBool idsAreUids)
PRUint32 nsImapProtocol::GetMessageSize(nsString2 &messageId, PRBool idsAreUids)
{
NS_ASSERTION(FALSE, "not implemented yet");
return 0;

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

@ -31,6 +31,7 @@
#include "nsImapServerResponseParser.h"
#include "nsImapProxyEvent.h"
#include "nsImapFlagAndUidState.h"
class nsIMAPMessagePartIDArray;
class nsIMsgIncomingServer;
@ -90,17 +91,17 @@ public:
PRBool GetShouldDownloadArbitraryHeaders();
char *GetArbitraryHeadersToDownload();
virtual void AdjustChunkSize();
virtual void FetchMessage(const char *messageIds,
virtual void FetchMessage(nsString2 &messageIds,
nsIMAPeFetchFields whatToFetch,
XP_Bool idAreUid,
uint32 startByte = 0, uint32 endByte = 0,
PRBool idAreUid,
PRUint32 startByte = 0, PRUint32 endByte = 0,
char *part = 0);
void FetchTryChunking(const char *messageIds,
void FetchTryChunking(nsString2 &messageIds,
nsIMAPeFetchFields whatToFetch,
PRBool idIsUid,
char *part,
PRUint32 downloadSize);
virtual void PipelinedFetchMessageParts(const char *uid, nsIMAPMessagePartIDArray *parts);
virtual void PipelinedFetchMessageParts(nsString2 &uid, nsIMAPMessagePartIDArray *parts);
// used when streaming a message fetch
virtual void BeginMessageDownLoad(PRUint32 totalSize, // for user, headers and body
@ -111,6 +112,7 @@ public:
virtual void PostLineDownLoadEvent(msg_line_info *downloadLineDontDelete);
virtual void AddXMozillaStatusLine(uint16 flags); // for XSender auth info
virtual void ProcessMailboxUpdate(PRBool handlePossibleUndo);
// Send log output...
void Log(const char *logSubName, const char *extraInfo, const char *logData);
@ -120,7 +122,7 @@ public:
PRBool GetPseudoInterrupted();
void PseudoInterrupt(PRBool the_interrupt);
PRUint32 GetMessageSize(const char *messageId, PRBool idsAreUids);
PRUint32 GetMessageSize(nsString2 &messageId, PRBool idsAreUids);
PRBool DeathSignalReceived();
void ResetProgressInfo();
@ -215,6 +217,8 @@ private:
PRMonitor *m_dataMemberMonitor;
PRMonitor *m_threadDeathMonitor;
PRMonitor *m_eventCompletionMonitor;
PRMonitor *m_waitForBodyIdsMonitor;
PRMonitor *m_fetchMsgListMonitor;
PRBool m_imapThreadIsRunning;
static void ImapThreadMain(void *aParm);
@ -241,6 +245,20 @@ private:
virtual void ProcessCurrentURL();
virtual void ParseIMAPandCheckForNewMail(char* commandString = nsnull);
// listing header functions
void FolderHeaderDump(PRUint32 *msgUids, PRUint32 msgCount);
void FolderMsgDump(PRUint32 *msgUids, PRUint32 msgCount, nsIMAPeFetchFields fields);
void FolderMsgDumpLoop(PRUint32 *msgUids, PRUint32 msgCount, nsIMAPeFetchFields fields);
void WaitForPotentialListOfMsgsToFetch(PRUint32 **msgIdList, PRUint32 &msgCount);
void NotifyKeyList(PRUint32 *keys, PRUint32 keyCount);
void AllocateImapUidString(PRUint32 *msgUids, PRUint32 msgCount, nsString2 &returnString);
void HeaderFetchCompleted();
// header listing data
PRBool m_fetchMsgListIsNew;
PRUint32 m_fetchCount;
PRUint32 *m_fetchMsgIdList;
// initialization function given a new url and transport layer
void SetupWithUrl(nsIURL * aURL);
@ -253,9 +271,10 @@ private:
PRInt32 SendData(const char * dataBuffer);
// state ported over from 4.5
PRBool m_pseudoInterrupted;
PRBool m_active;
PRBool m_threadShouldDie;
PRBool m_pseudoInterrupted;
PRBool m_active;
PRBool m_threadShouldDie;
nsImapFlagAndUidState m_flagState;
// manage the IMAP server command tags
char m_currentServerCommandTag[10]; // enough for a billion

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

@ -63,6 +63,7 @@ nsImapUrl::nsImapUrl()
m_imapMessage = nsnull;
m_imapExtension = nsnull;
m_imapMiscellaneous = nsnull;
m_listOfMessageIds = nsnull;
m_runningUrl = PR_FALSE;
@ -86,6 +87,8 @@ nsImapUrl::~nsImapUrl()
PR_FREEIF(m_protocol);
PR_FREEIF(m_host);
PR_FREEIF(m_search);
PR_FREEIF(m_listOfMessageIds);
}
NS_IMPL_THREADSAFE_ADDREF(nsImapUrl);
@ -732,6 +735,38 @@ NS_IMETHODIMP nsImapUrl::GetContentLength(PRInt32 *len)
return NS_OK;
}
NS_IMETHODIMP nsImapUrl::CreateListOfMessageIdsString(char **aResult) const
{
if (nsnull == aResult || !m_listOfMessageIds)
return NS_ERROR_NULL_POINTER;
NS_LOCK_INSTANCE();
char *returnIdString = PL_strdup(m_listOfMessageIds);
if (returnIdString)
{
// 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 = returnIdString;
while (*currentChar && (*currentChar != '&'))
currentChar++;
if (*currentChar == '&')
*currentChar = 0;
// we should also strip off anything after "/;section="
// since that can specify an IMAP MIME part
char *wherepart = PL_strstr(returnIdString, "/;section=");
if (wherepart)
*wherepart = 0;
}
*aResult = returnIdString;
NS_UNLOCK_INSTANCE();
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////////
// End of nsIURL support
////////////////////////////////////////////////////////////////////////////////////

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

@ -106,6 +106,9 @@ public:
NS_IMETHOD GetImapPartToFetch(char **result) const;
NS_IMETHOD AllocateCannonicalPath(const char *serverPath, char onlineDelimiter, char **allocatedPath ) const;
NS_IMETHOD CreateListOfMessageIdsString(char **result) const;
// nsImapUrl
nsImapUrl();
virtual ~nsImapUrl();
@ -125,6 +128,8 @@ protected:
PRUint32 m_port;
char *m_search;
char *m_errorMessage;
char *m_listOfMessageIds;
PRBool m_runningUrl;