port miscellaneous methods, like search, use more nsString2's, fix bug in header download

This commit is contained in:
bienvenu%netscape.com 1999-04-16 21:29:09 +00:00
parent db889ee887
commit 51daf4c0b0
7 changed files with 397 additions and 296 deletions

View File

@ -157,10 +157,12 @@ public:
NS_IMETHOD AllocateServerPath(const char * aCanonicalPath, char aOnlineDelimiter, char ** aAllocatedPath) = 0;
NS_IMETHOD CreateServerSourceFolderPathString(char **result) = 0;
NS_IMETHOD CreateCanonicalSourceFolderPathString(char **result) = 0;
NS_IMETHOD CreateServerDestinationFolderPathString(char **result) = 0;
NS_IMETHOD AddOnlineDirectoryIfNecessary(const char *onlineMailboxName, char ** directory) = 0;
NS_IMETHOD CreateListOfMessageIdsString(char **result) = 0;
NS_IMETHOD CreateSearchCriteriaString(nsString2 *aResult) = 0;
NS_IMETHOD CreateListOfMessageIdsString(nsString2 *result) = 0;
NS_IMETHOD MessageIdsAreUids(PRBool *result) = 0;
NS_IMETHOD GetMsgFlags(imapMessageFlagsType *result) = 0; // kAddMsgFlags or kSubtractMsgFlags only

View File

@ -236,10 +236,10 @@ PRInt32 nsIMAPBodyShell::Generate(char *partNum)
NS_ASSERTION(GetIsValid());
#endif
m_generatingWholeMessage = TRUE;
PRUint32 messageSize = m_protocolConnection->GetMessageSize(GetUID(), TRUE);
PRUint32 messageSize = m_protocolConnection->GetMessageSize(GetUID(), PR_TRUE);
m_protocolConnection->SetContentModified(FALSE); // So that when we cache it, we know we have the whole message
if (!DeathSignalReceived())
m_protocolConnection->FetchTryChunking(GetUID(), kEveryThingRFC822, TRUE, NULL, messageSize);
m_protocolConnection->FetchTryChunking(GetUID(), kEveryThingRFC822, PR_TRUE, NULL, messageSize, PR_TRUE);
contentLength = (PRInt32) messageSize; // ugh
}
else
@ -554,8 +554,11 @@ PRInt32 nsIMAPBodypart::GeneratePart(PRBool stream, PRBool prefetch)
{
if (stream && !m_shell->DeathSignalReceived())
{
char *generatingPart = m_shell->GetGeneratingPart();
PRBool fetchingSpecificPart = (generatingPart && !PL_strcmp(generatingPart, m_partNumberString));
m_shell->GetConnection()->Log("SHELL","GENERATE-Part-Inline",m_partNumberString);
m_shell->GetConnection()->FetchTryChunking(m_shell->GetUID(), kMIMEPart, TRUE, m_partNumberString, m_partLength);
m_shell->GetConnection()->FetchTryChunking(m_shell->GetUID(), kMIMEPart, TRUE, m_partNumberString, m_partLength, !fetchingSpecificPart);
}
return m_partLength; // the part length has been filled in from the BODYSTRUCTURE response
}

View File

@ -67,6 +67,17 @@ typedef PRUint16 imapMessageFlagsType;
#define IMAP_URL_TOKEN_SEPARATOR ">"
#define kUidUnknown -1
// this has to do with Mime Parts on Demand. It used to live in net.h
// I'm not sure where this will live, but here is OK temporarily
typedef enum {
IMAP_CONTENT_NOT_MODIFIED = 0,
IMAP_CONTENT_MODIFIED_VIEW_INLINE,
IMAP_CONTENT_MODIFIED_VIEW_AS_LINKS,
IMAP_CONTENT_FORCE_CONTENT_NOT_MODIFIED
} IMAP_ContentModifiedType;
// I think this should really go in an imap.h equivalent file
typedef enum {
kPersonalNamespace = 0,

View File

@ -1110,134 +1110,131 @@ void nsImapProtocol::ProcessSelectedStateURL()
break;
case nsIImapUrl::nsImapMsgFetch:
{
char *messageIdString;
nsString2 messageIdString(eOneByte);
m_runningUrl->CreateListOfMessageIdsString(&messageIdString);
if (messageIdString)
{
#ifdef HAVE_PORT
// we dont want to send the flags back in a group
// GetServerStateParser().ResetFlagInfo(0);
if (HandlingMultipleMessages(messageIdString))
{
// multiple messages, fetch them all
m_progressStringId = XP_FOLDER_RECEIVING_MESSAGE_OF;
m_progressIndex = 0;
m_progressCount = CountMessagesInIdString(messageIdString);
FetchMessage(messageIdString,
kEveryThingRFC822Peek,
bMessageIdsAreUids);
m_progressStringId = 0;
}
else
{
// A single message ID
// we dont want to send the flags back in a group
// GetServerStateParser().ResetFlagInfo(0);
if (HandlingMultipleMessages(messageIdString))
{
// multiple messages, fetch them all
// m_progressStringId = XP_FOLDER_RECEIVING_MESSAGE_OF;
m_progressIndex = 0;
m_progressCount = CountMessagesInIdString(messageIdString);
FetchMessage(messageIdString,
kEveryThingRFC822Peek,
bMessageIdsAreUids);
m_progressStringId = 0;
}
else
{
// A single message ID
// First, let's see if we're requesting a specific MIME part
char *imappart = nsnull;
m_runningUrl->GetImapPartToFetch(&imappart);
if (imappart)
// First, let's see if we're requesting a specific MIME part
char *imappart = nsnull;
m_runningUrl->GetImapPartToFetch(&imappart);
if (imappart)
{
if (bMessageIdsAreUids)
{
if (bMessageIdsAreUids)
// We actually want a specific MIME part of the message.
// The Body Shell will generate it, even though we haven't downloaded it yet.
#ifdef DOING_MPOD
IMAP_ContentModifiedType modType = GetShowAttachmentsInline() ?
IMAP_CONTENT_MODIFIED_VIEW_INLINE :
IMAP_CONTENT_MODIFIED_VIEW_AS_LINKS;
nsIMAPBodyShell *foundShell = TIMAPHostInfo::FindShellInCacheForHost(m_runningUrl->GetUrlHost(),
GetServerStateParser().GetSelectedMailboxName(), messageIdString, modType);
if (!foundShell)
{
// We actually want a specific MIME part of the message.
// The Body Shell will generate it, even though we haven't downloaded it yet.
IMAP_ContentModifiedType modType = GetShowAttachmentsInline() ?
IMAP_CONTENT_MODIFIED_VIEW_INLINE :
IMAP_CONTENT_MODIFIED_VIEW_AS_LINKS;
nsIMAPBodyShell *foundShell = TIMAPHostInfo::FindShellInCacheForHost(m_runningUrl->GetUrlHost(),
GetServerStateParser().GetSelectedMailboxName(), messageIdString, modType);
if (!foundShell)
{
// The shell wasn't in the cache. Deal with this case later.
Log("SHELL",NULL,"Loading part, shell not found in cache!");
//PR_LOG(IMAP, out, ("BODYSHELL: Loading part, shell not found in cache!"));
// The parser will extract the part number from the current URL.
SetContentModified(modType);
Bodystructure(messageIdString, bMessageIdsAreUids);
}
else
{
Log("SHELL", NULL, "Loading Part, using cached shell.");
//PR_LOG(IMAP, out, ("BODYSHELL: Loading part, using cached shell."));
SetContentModified(modType);
foundShell->SetConnection(this);
GetServerStateParser().UseCachedShell(foundShell);
foundShell->Generate(imappart);
GetServerStateParser().UseCachedShell(NULL);
}
// The shell wasn't in the cache. Deal with this case later.
Log("SHELL",NULL,"Loading part, shell not found in cache!");
//PR_LOG(IMAP, out, ("BODYSHELL: Loading part, shell not found in cache!"));
// The parser will extract the part number from the current URL.
SetContentModified(modType);
Bodystructure(messageIdString, bMessageIdsAreUids);
}
else
{
// Message IDs are not UIDs.
NS_ASSERTION(PR_FALSE, "message ids aren't uids");
Log("SHELL", NULL, "Loading Part, using cached shell.");
//PR_LOG(IMAP, out, ("BODYSHELL: Loading part, using cached shell."));
SetContentModified(modType);
foundShell->SetConnection(this);
GetServerStateParser().UseCachedShell(foundShell);
foundShell->Generate(imappart);
GetServerStateParser().UseCachedShell(NULL);
}
PR_Free(imappart);
#endif // DOING_MPOD
}
else
{
// downloading a single message: try to do it by bodystructure, and/or do it by chunks
PRUint32 messageSize = GetMessageSize(messageIdString,
bMessageIdsAreUids);
// We need to check the format_out bits to see if we are allowed to leave out parts,
// or if we are required to get the whole thing. Some instances where we are allowed
// to do it by parts: when viewing a message, or its source
// Some times when we're NOT allowed: when forwarding a message, saving it, moving it, etc.
XP_Bool allowedToBreakApart = (ce && !DeathSignalReceived()) ? ce->URL_s->allow_content_change : FALSE;
// Message IDs are not UIDs.
NS_ASSERTION(PR_FALSE, "message ids aren't uids");
}
PR_Free(imappart);
}
else
{
// downloading a single message: try to do it by bodystructure, and/or do it by chunks
PRUint32 messageSize = GetMessageSize(messageIdString,
bMessageIdsAreUids);
// We need to check the format_out bits to see if we are allowed to leave out parts,
// or if we are required to get the whole thing. Some instances where we are allowed
// to do it by parts: when viewing a message, or its source
// Some times when we're NOT allowed: when forwarding a message, saving it, moving it, etc.
#ifdef DOING_MPOD
PRBool allowedToBreakApart = (ce && !DeathSignalReceived()) ? ce->URL_s->allow_content_change : FALSE;
if (gMIMEOnDemand &&
allowedToBreakApart &&
!GetShouldFetchAllParts() &&
GetServerStateParser().ServerHasIMAP4Rev1Capability() &&
(messageSize > (uint32) gMIMEOnDemandThreshold) &&
!m_runningUrl->MimePartSelectorDetected()) // if a ?part=, don't do BS.
if (gMIMEOnDemand &&
allowedToBreakApart &&
!GetShouldFetchAllParts() &&
GetServerStateParser().ServerHasIMAP4Rev1Capability() &&
(messageSize > (uint32) gMIMEOnDemandThreshold) &&
!m_runningUrl->MimePartSelectorDetected()) // if a ?part=, don't do BS.
{
// OK, we're doing bodystructure
// Before fetching the bodystructure, let's check our body shell cache to see if
// we already have it around.
nsIMAPBodyShell *foundShell = NULL;
IMAP_ContentModifiedType modType = GetShowAttachmentsInline() ?
IMAP_CONTENT_MODIFIED_VIEW_INLINE :
IMAP_CONTENT_MODIFIED_VIEW_AS_LINKS;
SetContentModified(modType); // This will be looked at by the cache
if (bMessageIdsAreUids)
{
// OK, we're doing bodystructure
// Before fetching the bodystructure, let's check our body shell cache to see if
// we already have it around.
nsIMAPBodyShell *foundShell = NULL;
IMAP_ContentModifiedType modType = GetShowAttachmentsInline() ?
IMAP_CONTENT_MODIFIED_VIEW_INLINE :
IMAP_CONTENT_MODIFIED_VIEW_AS_LINKS;
SetContentModified(modType); // This will be looked at by the cache
if (bMessageIdsAreUids)
foundShell = TIMAPHostInfo::FindShellInCacheForHost(m_runningUrl->GetUrlHost(),
GetServerStateParser().GetSelectedMailboxName(), messageIdString, modType);
if (foundShell)
{
foundShell = TIMAPHostInfo::FindShellInCacheForHost(m_runningUrl->GetUrlHost(),
GetServerStateParser().GetSelectedMailboxName(), messageIdString, modType);
if (foundShell)
{
Log("SHELL",NULL,"Loading message, using cached shell.");
//PR_LOG(IMAP, out, ("BODYSHELL: Loading message, using cached shell."));
foundShell->SetConnection(this);
GetServerStateParser().UseCachedShell(foundShell);
foundShell->Generate(NULL);
GetServerStateParser().UseCachedShell(NULL);
}
Log("SHELL",NULL,"Loading message, using cached shell.");
//PR_LOG(IMAP, out, ("BODYSHELL: Loading message, using cached shell."));
foundShell->SetConnection(this);
GetServerStateParser().UseCachedShell(foundShell);
foundShell->Generate(NULL);
GetServerStateParser().UseCachedShell(NULL);
}
}
if (!foundShell)
Bodystructure(messageIdString, bMessageIdsAreUids);
}
else
{
// Not doing bodystructure. Fetch the whole thing, and try to do
// it in chunks.
SetContentModified(IMAP_CONTENT_NOT_MODIFIED);
FetchTryChunking(messageIdString, TIMAP4BlockingConnection::kEveryThingRFC822,
bMessageIdsAreUids, NULL, messageSize, TRUE);
}
if (!foundShell)
Bodystructure(messageIdString, bMessageIdsAreUids);
}
else
#endif // DOING_MPOD
{
// Not doing bodystructure. Fetch the whole thing, and try to do
// it in chunks.
SetContentModified(IMAP_CONTENT_NOT_MODIFIED);
FetchTryChunking(messageIdString, kEveryThingRFC822,
bMessageIdsAreUids, NULL, messageSize, TRUE);
}
}
PR_FREEIF( messageIdString);
#endif // HAVE_PORT
}
else
HandleMemoryFailure();
}
}
break;
case nsIImapUrl::nsImapExpungeFolder:
@ -1249,140 +1246,112 @@ void nsImapProtocol::ProcessSelectedStateURL()
break;
case nsIImapUrl::nsImapMsgHeader:
{
char *messageIdString = nsnull;
m_runningUrl->CreateListOfMessageIdsString(&messageIdString);
nsString2 messageIds(messageIdString, eOneByte);
nsString2 messageIds(eOneByte);
m_runningUrl->CreateListOfMessageIdsString(&messageIds);
if (messageIdString)
{
// we don't want to send the flags back in a group
// GetServerStateParser().ResetFlagInfo(0);
FetchMessage(messageIds,
kHeadersRFC822andUid,
bMessageIdsAreUids);
PR_FREEIF( messageIdString);
}
else
HandleMemoryFailure();
FetchMessage(messageIds,
kHeadersRFC822andUid,
bMessageIdsAreUids);
}
break;
case nsIImapUrl::nsImapSearch:
{
#ifdef HAVE_PORT
char *searchCriteriaString =
m_runningUrl->CreateSearchCriteriaString();
if (searchCriteriaString)
{
Search(searchCriteriaString, bMessageIdsAreUids);
// drop the results on the floor for now
PR_FREEIF( searchCriteriaString);
}
else
HandleMemoryFailure();
#endif
}
nsString2 searchCriteriaString(eOneByte);
m_runningUrl->CreateSearchCriteriaString(&searchCriteriaString);
Search(searchCriteriaString, bMessageIdsAreUids);
// drop the results on the floor for now
}
break;
case nsIImapUrl::nsImapDeleteMsg:
{
#ifdef HAVE_PORT
char *messageIdString =
m_runningUrl->CreateListOfMessageIdsString();
if (messageIdString)
nsString2 messageIdString(eOneByte);
m_runningUrl->CreateListOfMessageIdsString(&messageIdString);
#ifdef DO_PROGRESS
if (HandlingMultipleMessages(messageIdString))
ProgressEventFunction_UsingId (XP_IMAP_DELETING_MESSAGES);
else
ProgressEventFunction_UsingId(XP_IMAP_DELETING_MESSAGE);
#endif
Store(messageIdString, "+FLAGS (\\Deleted)",
bMessageIdsAreUids);
if (GetServerStateParser().LastCommandSuccessful())
{
if (HandlingMultipleMessages(messageIdString))
ProgressEventFunction_UsingId (XP_IMAP_DELETING_MESSAGES);
else
ProgressEventFunction_UsingId(XP_IMAP_DELETING_MESSAGE);
Store(messageIdString, "+FLAGS (\\Deleted)",
bMessageIdsAreUids);
if (GetServerStateParser().LastCommandSuccessful())
{
struct delete_message_struct *deleteMsg = (struct delete_message_struct *) XP_ALLOC (sizeof(struct delete_message_struct));
delete_message_struct *deleteMsg = (delete_message_struct *) PR_Malloc (sizeof(delete_message_struct));
// convert name back from utf7
utf_name_struct *nameStruct = (utf_name_struct *) XP_ALLOC(sizeof(utf_name_struct));
char *convertedCanonicalName = NULL;
if (nameStruct)
{
nameStruct->toUtf7Imap = FALSE;
nameStruct->sourceString = (unsigned char *) GetServerStateParser().GetSelectedMailboxName();
nameStruct->convertedString = NULL;
ConvertImapUtf7(nameStruct, NULL);
if (nameStruct->convertedString)
convertedCanonicalName = m_runningUrl->AllocateCanonicalPath((char *) nameStruct->convertedString);
}
// convert name back from utf7
utf_name_struct *nameStruct = (utf_name_struct *) PR_Malloc(sizeof(utf_name_struct));
char *convertedCanonicalName = NULL;
if (nameStruct)
{
nameStruct->toUtf7Imap = PR_FALSE;
nameStruct->sourceString = (unsigned char *) GetServerStateParser().GetSelectedMailboxName();
nameStruct->convertedString = NULL;
#ifdef DO_UTF7_YET
ConvertImapUtf7(nameStruct, NULL);
#endif
if (nameStruct->convertedString)
m_runningUrl->AllocateCanonicalPath((char *) nameStruct->convertedString,
kOnlineHierarchySeparatorUnknown, &convertedCanonicalName);
}
deleteMsg->onlineFolderName = convertedCanonicalName;
deleteMsg->deleteAllMsgs = FALSE;
deleteMsg->msgIdString = messageIdString; // storage adopted, do not delete
messageIdString = nil; // deleting nil is ok
TImapFEEvent *deleteEvent =
new TImapFEEvent(NotifyMessageDeletedEvent, // function to call
(void *) this,
(void *) deleteMsg, TRUE);
if (deleteEvent)
fFEEventQueue->AdoptEventToEnd(deleteEvent);
else
HandleMemoryFailure();
}
FREEIF( messageIdString);
deleteMsg->onlineFolderName = convertedCanonicalName;
deleteMsg->deleteAllMsgs = FALSE;
deleteMsg->msgIdString = messageIdString.ToNewCString(); // storage adopted, do not delete
if (m_imapMessage)
m_imapMessage->NotifyMessageDeleted(this, deleteMsg);
// notice we don't wait for this to finish...
}
else
HandleMemoryFailure();
#endif // HAVE_PORT
}
break;
case nsIImapUrl::nsImapDeleteAllMsgs:
{
#ifdef HAVE_PORT
uint32 numberOfMessages = GetServerStateParser().NumberOfMessages();
if (numberOfMessages)
{
char messageIdString[100]; // enough for bazillion msgs
sprintf(messageIdString, "1:*"); /* Reviewed 4.51 safe use of sprintf */
nsString2 messageIdString("1:*", eOneByte);
Store(messageIdString, "+FLAGS.SILENT (\\Deleted)", FALSE); // use sequence #'s
Store(messageIdString, "+FLAGS.SILENT (\\Deleted)", PR_FALSE); // use sequence #'s
if (GetServerStateParser().LastCommandSuccessful())
Expunge(); // expunge messages with deleted flag
if (GetServerStateParser().LastCommandSuccessful())
{
struct delete_message_struct *deleteMsg = (struct delete_message_struct *) XP_ALLOC (sizeof(struct delete_message_struct));
delete_message_struct *deleteMsg = (delete_message_struct *) PR_Malloc (sizeof(delete_message_struct));
// convert name back from utf7
utf_name_struct *nameStruct = (utf_name_struct *) XP_ALLOC(sizeof(utf_name_struct));
utf_name_struct *nameStruct = (utf_name_struct *) PR_Malloc(sizeof(utf_name_struct));
char *convertedCanonicalName = NULL;
if (nameStruct)
{
nameStruct->toUtf7Imap = FALSE;
nameStruct->toUtf7Imap = PR_FALSE;
nameStruct->sourceString = (unsigned char *) GetServerStateParser().GetSelectedMailboxName();
nameStruct->convertedString = NULL;
#ifdef DO_UTF7
ConvertImapUtf7(nameStruct, NULL);
#endif
if (nameStruct->convertedString)
convertedCanonicalName = m_runningUrl->AllocateCanonicalPath((char *) nameStruct->convertedString);
m_runningUrl->AllocateCanonicalPath((char *) nameStruct->convertedString,
kOnlineHierarchySeparatorUnknown, &convertedCanonicalName);
}
deleteMsg->onlineFolderName = convertedCanonicalName;
deleteMsg->deleteAllMsgs = TRUE;
deleteMsg->deleteAllMsgs = PR_TRUE;
deleteMsg->msgIdString = nil;
TImapFEEvent *deleteEvent =
new TImapFEEvent(NotifyMessageDeletedEvent, // function to call
(void *) this,
(void *) deleteMsg, TRUE);
if (deleteEvent)
fFEEventQueue->AdoptEventToEnd(deleteEvent);
else
HandleMemoryFailure();
if (m_imapMessage)
m_imapMessage->NotifyMessageDeleted(this, deleteMsg);
}
}
#ifdef HAVE_PORT
DeleteSubFolders(mailboxName);
#endif // HAVE_PORT
#endif
}
break;
case nsIImapUrl::nsImapAppendMsgFromFile:
@ -1413,15 +1382,12 @@ void nsImapProtocol::ProcessSelectedStateURL()
break;
case nsIImapUrl::nsImapAddMsgFlags:
{
char *messageIdString = nsnull;
nsString2 messageIdString(eOneByte);
m_runningUrl->CreateListOfMessageIdsString(&messageIdString);
if (messageIdString)
{
ProcessStoreFlags(messageIdString, bMessageIdsAreUids,
msgFlags, PR_TRUE);
PR_FREEIF( messageIdString);
ProcessStoreFlags(messageIdString, bMessageIdsAreUids,
msgFlags, PR_TRUE);
/*
if ( !DeathSignalReceived() &&
GetServerStateParser().Connected() &&
@ -1432,68 +1398,51 @@ void nsImapProtocol::ProcessSelectedStateURL()
Check(); // flush servers flag state
}
*/
}
else
HandleMemoryFailure();
}
break;
case nsIImapUrl::nsImapSubtractMsgFlags:
{
char *messageIdString = nsnull;
nsString2 messageIdString(eOneByte);
m_runningUrl->CreateListOfMessageIdsString(&messageIdString);
if (messageIdString)
{
ProcessStoreFlags(messageIdString, bMessageIdsAreUids,
msgFlags, FALSE);
ProcessStoreFlags(messageIdString, bMessageIdsAreUids,
msgFlags, FALSE);
PR_FREEIF( messageIdString);
}
else
HandleMemoryFailure();
}
break;
case nsIImapUrl::nsImapSetMsgFlags:
{
char *messageIdString = nsnull;
nsString2 messageIdString(eOneByte);
m_runningUrl->CreateListOfMessageIdsString(&messageIdString);
if (messageIdString)
{
ProcessStoreFlags(messageIdString, bMessageIdsAreUids,
msgFlags, TRUE);
ProcessStoreFlags(messageIdString, bMessageIdsAreUids,
~msgFlags, FALSE);
PR_FREEIF( messageIdString);
}
else
HandleMemoryFailure();
ProcessStoreFlags(messageIdString, bMessageIdsAreUids,
msgFlags, TRUE);
ProcessStoreFlags(messageIdString, bMessageIdsAreUids,
~msgFlags, FALSE);
}
break;
case nsIImapUrl::nsImapBiff:
#ifdef HAVE_PORT
PeriodicBiff();
#endif
break;
case nsIImapUrl::nsImapOnlineCopy:
case nsIImapUrl::nsImapOnlineMove:
{
#ifdef HAVE_PORT
char *messageIdString = nsnull;
nsString2 messageIdString(eOneByte);
m_runningUrl->CreateListOfMessageIdsString(&messageIdString);
char *destinationMailbox =
m_runningUrl->CreateServerDestinationFolderPathString();
char *destinationMailbox = nsnull;
m_runningUrl->CreateServerDestinationFolderPathString(&destinationMailbox);
if (destinationMailbox)
{
char *convertedName = CreateUtf7ConvertedString(destinationMailbox, TRUE);
XP_FREE(destinationMailbox);
PR_Free(destinationMailbox);
destinationMailbox = convertedName;
}
if (messageIdString && destinationMailbox)
if (destinationMailbox)
{
if (m_runningUrl->GetIMAPurlType() == TIMAPUrl::kOnlineMove) {
#ifdef DOING_PROGRESS
if (imapAction == nsIImapUrl::nsImapOnlineMove) {
if (HandlingMultipleMessages(messageIdString))
ProgressEventFunction_UsingIdWithString (XP_IMAP_MOVING_MESSAGES_TO, destinationMailbox);
else
@ -1505,31 +1454,34 @@ void nsImapProtocol::ProcessSelectedStateURL()
else
ProgressEventFunction_UsingIdWithString (XP_IMAP_COPYING_MESSAGE_TO, destinationMailbox);
}
#endif
Copy(messageIdString, destinationMailbox, bMessageIdsAreUids);
FREEIF( destinationMailbox);
PR_FREEIF( destinationMailbox);
ImapOnlineCopyState copyState;
if (DeathSignalReceived())
copyState = kInterruptedState;
else
copyState = GetServerStateParser().LastCommandSuccessful() ?
kSuccessfulCopy : kFailedCopy;
OnlineCopyCompleted(copyState);
if (m_imapMessage)
m_imapMessage->OnlineCopyReport(this, &copyState);
if (GetServerStateParser().LastCommandSuccessful() &&
(m_runningUrl->GetIMAPurlType() == TIMAPUrl::kOnlineMove))
(imapAction == nsIImapUrl::nsImapOnlineMove))
{
Store(messageIdString, "+FLAGS (\\Deleted)", bMessageIdsAreUids);
PRBool storeSuccessful = GetServerStateParser().LastCommandSuccessful();
OnlineCopyCompleted( storeSuccessful ? kSuccessfulDelete : kFailedDelete);
if (m_imapMessage)
{
copyState = storeSuccessful ? kSuccessfulDelete : kFailedDelete;
m_imapMessage->OnlineCopyReport(this, &copyState);
}
}
FREEIF( messageIdString);
}
else
HandleMemoryFailure();
#endif
}
break;
case nsIImapUrl::nsImapOnlineToOfflineCopy:
@ -2086,10 +2038,11 @@ void nsImapProtocol::FetchTryChunking(nsString2 &messageIds,
nsIMAPeFetchFields whatToFetch,
PRBool idIsUid,
char *part,
PRUint32 downloadSize)
PRUint32 downloadSize,
PRBool tryChunking)
{
GetServerStateParser().SetTotalDownloadSize(downloadSize);
if (m_fetchByChunks &&
if (m_fetchByChunks && tryChunking &&
GetServerStateParser().ServerHasIMAP4Rev1Capability() &&
(downloadSize > (PRUint32) m_chunkThreshold))
{
@ -2384,23 +2337,22 @@ void nsImapProtocol::ProcessMailboxUpdate(PRBool handlePossibleUndo)
if (handlePossibleUndo)
{
// undo any delete flags we may have asked to
char *undoIds;
nsString2 undoIds(eOneByte);
GetCurrentUrl()->CreateListOfMessageIdsString(&undoIds);
if (undoIds && *undoIds)
{
nsString2 undoIds2(undoIds + 1);
if (undoIds.Length() > 0)
{
char firstChar = (char) undoIds.CharAt(0);
undoIds.Cut(0, 1); // remove first character
// if this string started with a '-', then this is an undo of a delete
// if its a '+' its a redo
if (*undoIds == '-')
Store(undoIds2, "-FLAGS (\\Deleted)", TRUE); // most servers will fail silently on a failure, deal with it?
else if (*undoIds == '+')
Store(undoIds2, "+FLAGS (\\Deleted)", TRUE); // most servers will fail silently on a failure, deal with it?
if (firstChar == '-')
Store(undoIds, "-FLAGS (\\Deleted)", TRUE); // most servers will fail silently on a failure, deal with it?
else if (firstChar == '+')
Store(undoIds, "+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
@ -2424,7 +2376,8 @@ void nsImapProtocol::ProcessMailboxUpdate(PRBool handlePossibleUndo)
}
}
else {
else
{
fetchStr.Append(GetServerStateParser().HighestRecordedUID() + 1, 10);
fetchStr.Append(":*");
@ -2559,7 +2512,7 @@ void nsImapProtocol::FolderMsgDumpLoop(PRUint32 *msgUids, PRUint32 msgCount, nsI
{
// PastPasswordCheckEvent();
PRUint32 msgCountLeft = msgCount;
PRInt32 msgCountLeft = msgCount;
PRUint32 msgsDownloaded = 0;
do
{
@ -2572,7 +2525,7 @@ void nsImapProtocol::FolderMsgDumpLoop(PRUint32 *msgUids, PRUint32 msgCount, nsI
FetchMessage(idString, fields, TRUE); // msg ids are uids
msgsDownloaded += msgsToDownload;
msgCountLeft -= msgsDownloaded;
msgCountLeft -= msgsToDownload;
}
while (msgCountLeft > 0);
@ -2582,8 +2535,10 @@ void nsImapProtocol::FolderMsgDumpLoop(PRUint32 *msgUids, PRUint32 msgCount, nsI
void nsImapProtocol::HeaderFetchCompleted()
{
if (m_imapMiscellaneous)
{
m_imapMiscellaneous->HeaderFetchCompleted(this);
WaitForFEEventCompletion();
WaitForFEEventCompletion();
}
}
@ -2825,12 +2780,63 @@ PRBool nsImapProtocol::GetShowAttachmentsInline()
return PR_FALSE;
}
/* static */PRBool nsImapProtocol::HandlingMultipleMessages(char *messageIdString)
// message id string utility functions
/* static */PRBool nsImapProtocol::HandlingMultipleMessages(const char *messageIdString)
{
return (PL_strchr(messageIdString,',') != nsnull ||
PL_strchr(messageIdString,':') != nsnull);
}
/* static */PRBool nsImapProtocol::HandlingMultipleMessages(nsString2 &messageIdString)
{
return (messageIdString.FindCharInSet(",:") != -1);
}
PRUint32 nsImapProtocol::CountMessagesInIdString(nsString2 &idString)
{
return CountMessagesInIdString((const char *) idString.GetBuffer());
}
PRUint32 nsImapProtocol::CountMessagesInIdString(const char *idString)
{
PRUint32 numberOfMessages = 0;
char *uidString = PL_strdup(idString);
if (uidString)
{
// This is in the form <id>,<id>, or <id1>:<id2>
char curChar = *uidString;
PRBool isRange = FALSE;
PRInt32 curToken;
PRInt32 saveStartToken=0;
for (char *curCharPtr = uidString; curChar && *curCharPtr;)
{
char *currentKeyToken = curCharPtr;
curChar = *curCharPtr;
while (curChar != ':' && curChar != ',' && curChar != '\0')
curChar = *curCharPtr++;
*(curCharPtr - 1) = '\0';
curToken = atol(currentKeyToken);
if (isRange)
{
while (saveStartToken < curToken)
{
numberOfMessages++;
saveStartToken++;
}
}
numberOfMessages++;
isRange = (curChar == ':');
if (isRange)
saveStartToken = curToken + 1;
}
PR_Free(uidString);
}
return numberOfMessages;
}
PRMonitor *nsImapProtocol::GetDataMemberMonitor()
{
@ -4009,13 +4015,8 @@ void nsImapProtocol::OnStatusForFolder(const char *mailboxName)
ParseIMAPandCheckForNewMail();
mailbox_spec *new_spec = GetServerStateParser().CreateCurrentMailboxSpec(mailboxName);
#ifdef HAVE_PORT
if (new_spec)
UpdateMailboxStatus(new_spec);
if (new_spec && m_imapMailFolder)
m_imapMailFolder->UpdateImapMailboxStatus(this, new_spec);
#endif
}
@ -4516,6 +4517,53 @@ void nsImapProtocol::List(const char *mailboxPattern, PRBool addDirectoryIfNeces
ParseIMAPandCheckForNewMail();
}
void nsImapProtocol::Search(nsString2 &searchCriteria,
PRBool useUID,
PRBool notifyHit /* TRUE */)
{
m_notifySearchHit = notifyHit;
// ProgressEventFunction_UsingId (MK_IMAP_STATUS_SEARCH_MAILBOX);
IncrementCommandTagNumber();
nsString2 protocolString(GetServerCommandTag(), eOneByte);
// the searchCriteria string contains the 'search ....' string
if (useUID)
protocolString.Append(" uid");
protocolString.Append(" ");
protocolString.Append(searchCriteria);
protocolString.Append(CRLF);;
int ioStatus = SendData(protocolString.GetBuffer());
ParseIMAPandCheckForNewMail();
}
void nsImapProtocol::Copy(nsString2 &messageList,
const char *destinationMailbox,
PRBool idsAreUid)
{
IncrementCommandTagNumber();
char *escapedDestination = CreateEscapedMailboxName(destinationMailbox);
nsString2 protocolString(GetServerCommandTag(), eOneByte);
if (idsAreUid)
protocolString.Append(" uid");
protocolString.Append(" copy ");
protocolString.Append(messageList);
protocolString.Append("\"");
protocolString.Append(escapedDestination);
protocolString.Append("\"" CRLF);
int ioStatus = SendData(protocolString.GetBuffer());
ParseIMAPandCheckForNewMail(protocolString.GetBuffer());
PR_FREEIF( escapedDestination);
}
void nsImapProtocol::ProcessAuthenticatedStateURL()
{
nsIImapUrl::nsImapAction imapAction;
@ -4715,7 +4763,7 @@ void nsImapProtocol::ProcessAfterAuthenticated()
}
}
void nsImapProtocol::ProcessStoreFlags(const char *messageIds,
void nsImapProtocol::ProcessStoreFlags(nsString2 &messageIdsString,
PRBool idsAreUids,
imapMessageFlagsType flags,
PRBool addFlags)
@ -4723,7 +4771,6 @@ void nsImapProtocol::ProcessStoreFlags(const char *messageIds,
if (!flags)
return;
nsString2 messageIdsString(messageIds, eOneByte);
nsString2 flagString(eOneByte);
uint16 userFlags = GetServerStateParser().SupportsUserFlags();

View File

@ -101,8 +101,13 @@ public:
void SetFlag (PRUint32 flag) { m_flags |= flag; }
void ClearFlag (PRUint32 flag) { m_flags &= ~flag; }
// message id string utilities.
PRUint32 CountMessagesInIdString(const char *idString);
PRUint32 CountMessagesInIdString(nsString2 &idString);
static PRBool HandlingMultipleMessages(const char *messageIdString);
static PRBool HandlingMultipleMessages(nsString2 &messageIdString);
// used to start fetching a message.
static PRBool HandlingMultipleMessages(char *messageIdString);
PRBool GetShouldDownloadArbitraryHeaders();
char *GetArbitraryHeadersToDownload();
virtual void AdjustChunkSize();
@ -115,7 +120,8 @@ public:
nsIMAPeFetchFields whatToFetch,
PRBool idIsUid,
char *part,
PRUint32 downloadSize);
PRUint32 downloadSize,
PRBool tryChunking);
virtual void PipelinedFetchMessageParts(nsString2 &uid, nsIMAPMessagePartIDArray *parts);
// used when streaming a message fetch
@ -182,10 +188,14 @@ public:
char * CreateUtf7ConvertedString(const char * aSourceString, PRBool
aConvertToUtf7Imap);
void Copy(nsString2 &messageList, const char *destinationMailbox,
PRBool idsAreUid);
void Search(nsString2 &searchCriteria, PRBool useUID,
PRBool notifyHit = PR_TRUE);
// imap commands issued by the parser
void Store(nsString2 &aMessageList, const char * aMessageData, PRBool
aIdsAreUid);
void ProcessStoreFlags(const char *messageIds,
void ProcessStoreFlags(nsString2 &messageIds,
PRBool idsAreUids,
imapMessageFlagsType flags,
PRBool addFlags);
@ -410,6 +420,7 @@ private:
PRInt32 m_progressIndex;
PRInt32 m_progressCount;
PRBool m_notifySearchHit;
PRBool m_mailToFetch;
PRBool m_checkForNewMailDownloadsHeaders;
PRBool m_needNoop;

View File

@ -777,33 +777,43 @@ NS_IMETHODIMP nsImapUrl::GetContentLength(PRInt32 *len)
return NS_OK;
}
NS_IMETHODIMP nsImapUrl::CreateListOfMessageIdsString(char **aResult)
NS_IMETHODIMP nsImapUrl::CreateSearchCriteriaString(nsString2 *aResult)
{
if (nsnull == aResult || !m_searchCriteriaString)
return NS_ERROR_NULL_POINTER;
NS_LOCK_INSTANCE();
aResult->Assign(m_searchCriteriaString);
NS_UNLOCK_INSTANCE();
return NS_OK;
}
NS_IMETHODIMP nsImapUrl::CreateListOfMessageIdsString(nsString2 *aResult)
{
if (nsnull == aResult || !m_listOfMessageIds)
return NS_ERROR_NULL_POINTER;
PRInt32 bytesToCopy = PL_strlen(m_listOfMessageIds);
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;
// 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(returnIdString, "/;section=");
if (wherepart)
*wherepart = 0;
}
*aResult = returnIdString;
// 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 = MIN(bytesToCopy, wherePart - m_listOfMessageIds);
aResult->Assign(m_listOfMessageIds, bytesToCopy);
NS_UNLOCK_INSTANCE();
return NS_OK;
@ -1371,6 +1381,21 @@ NS_IMETHODIMP nsImapUrl::CreateCanonicalSourceFolderPathString(char **result)
return (*result) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
NS_IMETHODIMP nsImapUrl::CreateServerDestinationFolderPathString(char **result)
{
nsresult rv = NS_OK;
if (!result)
return NS_ERROR_NULL_POINTER;
NS_LOCK_INSTANCE();
// its possible for the destination folder path to be the root
if (!m_destinationCanonicalFolderPathSubString)
*result = PL_strdup("");
else
rv = AllocateServerPath(m_destinationCanonicalFolderPathSubString, kOnlineHierarchySeparatorUnknown, result);
NS_UNLOCK_INSTANCE();
return (*result) ? rv : NS_ERROR_OUT_OF_MEMORY;
}
// for enabling or disabling mime parts on demand. Setting this to TRUE says we
// can use mime parts on demand, if we chose.

View File

@ -72,8 +72,10 @@ public:
NS_IMETHOD AllocateServerPath(const char * aCanonicalPath, char aOnlineDelimiter, char ** aAllocatedPath);
NS_IMETHOD CreateCanonicalSourceFolderPathString(char **result);
NS_IMETHOD CreateServerSourceFolderPathString(char **result) ;
NS_IMETHOD CreateServerDestinationFolderPathString(char **result);
NS_IMETHOD CreateListOfMessageIdsString(char **result) ;
NS_IMETHOD CreateSearchCriteriaString(nsString2 *aResult);
NS_IMETHOD CreateListOfMessageIdsString(nsString2 *result) ;
NS_IMETHOD MessageIdsAreUids(PRBool *result);
NS_IMETHOD GetMsgFlags(imapMessageFlagsType *result); // kAddMsgFlags or kSubtractMsgFlags only