Bug 583677 - Fix so custom tags (keywords) are visble to all users. r=jorgk

See Bug 583677 comment 85 for basic description of the fix.
This commit is contained in:
Gene Smith 2018-12-18 15:55:57 -05:00
Родитель 6bf07a5bdf
Коммит b81da8a541
7 изменённых файлов: 145 добавлений и 24 удалений

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

@ -70,5 +70,7 @@ interface nsIImapFlagAndUidState : nsISupports
*/
ACString getCustomAttribute(in unsigned long aUid,
in ACString aCustomAttributeName);
void setOtherKeywords(in unsigned short index, in AUTF8String otherKeyword);
AUTF8String getOtherKeywords(in unsigned short index);
};

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

@ -110,6 +110,27 @@ nsImapFlagAndUidState::GetSupportedUserFlags(uint16_t *aFlags)
return NS_OK;
}
NS_IMETHODIMP
nsImapFlagAndUidState::SetOtherKeywords(uint16_t index, const nsACString &otherKeyword)
{
if (index == 0)
fOtherKeywords.Clear();
nsAutoCString flag(otherKeyword);
ToLowerCase(flag);
fOtherKeywords.AppendElement(flag);
return NS_OK;
}
NS_IMETHODIMP
nsImapFlagAndUidState::GetOtherKeywords(uint16_t index, nsACString &aKeyword)
{
if (index < fOtherKeywords.Length())
aKeyword = fOtherKeywords[index];
else
aKeyword = EmptyCString();
return NS_OK;
}
// we need to reset our flags, (re-read all) but chances are the memory allocation needed will be
// very close to what we were already using

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

@ -51,6 +51,8 @@ private:
bool fPartialUIDFetch;
uint32_t fNumAdded;
bool fStartCapture;
// Keywords (aka, tags) in FLAGS response to SELECT defined by other clients
nsTArray<nsCString> fOtherKeywords;
mozilla::Mutex mLock;
};

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

@ -100,6 +100,7 @@ static NS_DEFINE_CID(kCImapHostSessionList, NS_IIMAPHOSTSESSIONLIST_CID);
extern mozilla::LazyLogModule gAutoSyncLog; // defined in nsAutoSyncManager.cpp
extern mozilla::LazyLogModule IMAP; // defined in nsImapProtocol.cpp
extern mozilla::LazyLogModule IMAP_CS; // For CONDSTORE, defined in nsImapProtocol.cpp
mozilla::LazyLogModule IMAP_KW("IMAP_KW"); // for logging keyword (tag) processing
#define MAILNEWS_CUSTOM_HEADERS "mailnews.customHeaders"
@ -4440,7 +4441,7 @@ void nsImapMailFolder::TweakHeaderFlags(nsIImapProtocol* aProtocol, nsIMsgDBHdr
if (newFlags)
tweakMe->OrFlags(newFlags, &dbHdrFlags);
if (!customFlags.IsEmpty())
(void) HandleCustomFlags(m_curMsgUid, tweakMe, userFlags, customFlags);
(void) HandleCustomFlags(m_curMsgUid, tweakMe, userFlags, customFlags, nullptr);
}
}
}
@ -4751,7 +4752,8 @@ nsImapMailFolder::BeginMessageUpload()
nsresult nsImapMailFolder::HandleCustomFlags(nsMsgKey uidOfMessage,
nsIMsgDBHdr *dbHdr,
uint16_t userFlags,
nsCString &keywords)
nsCString &keywords,
nsIImapFlagAndUidState *flagState)
{
nsresult rv = GetDatabase();
NS_ENSURE_SUCCESS(rv, rv);
@ -4785,6 +4787,71 @@ nsresult nsImapMailFolder::HandleCustomFlags(nsMsgKey uidOfMessage,
if (existingProperty.IsEmpty())
dbHdr->SetStringProperty("junkscoreorigin", "imapflag");
}
if (flagState && !(userFlags & kImapMsgSupportUserFlag))
{
nsCString localKeywords;
if (!(userFlags & kImapMsgSupportUserFlag))
{
dbHdr->GetStringProperty("keywords", getter_Copies(localKeywords));
MOZ_LOG(IMAP_KW, mozilla::LogLevel::Debug, ("UID=%" PRIu32 ", localKeywords=|%s| rcvdKeyword=|%s|",
uidOfMessage, localKeywords.get(), keywords.get()));
}
nsTArray<nsCString> localKeywordArray;
nsTArray<nsCString> rcvdKeywordArray;
ParseString(localKeywords, ' ', localKeywordArray);
ParseString(keywords, ' ', rcvdKeywordArray);
nsAutoCString mozLogDefinedKWs;
if (MOZ_LOG_TEST(IMAP_KW, mozilla::LogLevel::Debug))
mozLogDefinedKWs.AppendLiteral("Defined keywords = |");
uint32_t i = 0;
while (true)
{
nsAutoCString definedKeyword;
flagState->GetOtherKeywords(i++, definedKeyword);
if (definedKeyword.IsEmpty())
{
if (MOZ_LOG_TEST(IMAP_KW, mozilla::LogLevel::Debug))
{
mozLogDefinedKWs.Append('|');
MOZ_LOG(IMAP_KW, mozilla::LogLevel::Debug, ("%s", mozLogDefinedKWs.get()));
}
break;
}
if (MOZ_LOG_TEST(IMAP_KW, mozilla::LogLevel::Debug))
{
mozLogDefinedKWs.Append(definedKeyword.get());
mozLogDefinedKWs.Append(' ');
}
bool inLocal = localKeywordArray.Contains(definedKeyword);
bool inRcvd = rcvdKeywordArray.Contains(definedKeyword);
if (inLocal && inRcvd)
rcvdKeywordArray.RemoveElement(definedKeyword);
if (inLocal && !inRcvd)
localKeywordArray.RemoveElement(definedKeyword);
}
// Combine local and rcvd keyword arrays into a single string
// so it can be passed to SetStringProperty(). If element of
// local already in rcvd, avoid duplicates in combined string.
nsAutoCString combinedKeywords;
for (i = 0; i < localKeywordArray.Length(); i++)
{
if (!rcvdKeywordArray.Contains(localKeywordArray[i]))
{
combinedKeywords.Append(localKeywordArray[i]);
combinedKeywords.Append(' ');
}
}
for (i = 0; i < rcvdKeywordArray.Length(); i++)
{
combinedKeywords.Append(rcvdKeywordArray[i]);
combinedKeywords.Append(' ');
}
return dbHdr->SetStringProperty("keywords", combinedKeywords.get());
}
return (userFlags & kImapMsgSupportUserFlag) ?
dbHdr->SetStringProperty("keywords", keywords.get()) : NS_OK;
}
@ -4830,7 +4897,7 @@ nsresult nsImapMailFolder::SyncFlags(nsIImapFlagAndUidState *flagState)
nsCString keywords;
if (NS_SUCCEEDED(flagState->GetCustomFlags(uidOfMessage, getter_Copies(keywords))))
HandleCustomFlags(uidOfMessage, dbHdr, supportedUserFlags, keywords);
HandleCustomFlags(uidOfMessage, dbHdr, supportedUserFlags, keywords, flagState);
NotifyMessageFlagsFromHdr(dbHdr, uidOfMessage, flags);
}
@ -4935,7 +5002,7 @@ nsImapMailFolder::NotifyMessageFlags(uint32_t aFlags,
GetSupportedUserFlags(&supportedUserFlags);
NotifyMessageFlagsFromHdr(dbHdr, aMsgKey, aFlags);
nsCString keywords(aKeywords);
HandleCustomFlags(aMsgKey, dbHdr, supportedUserFlags, keywords);
HandleCustomFlags(aMsgKey, dbHdr, supportedUserFlags, keywords, nullptr);
}
}
return NS_OK;

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

@ -354,7 +354,8 @@ protected:
nsresult SyncFlags(nsIImapFlagAndUidState *flagState);
nsresult HandleCustomFlags(nsMsgKey uidOfMessage, nsIMsgDBHdr *dbHdr,
uint16_t userFlags, nsCString& keywords);
uint16_t userFlags, nsCString& keywords,
nsIImapFlagAndUidState *flagState);
nsresult NotifyMessageFlagsFromHdr(nsIMsgDBHdr *dbHdr, nsMsgKey msgKey,
uint32_t flags);

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

@ -782,7 +782,7 @@ void nsImapServerResponseParser::mailbox_data()
if (fGotPermanentFlags)
skip_to_CRLF();
else
parse_folder_flags();
parse_folder_flags(true);
}
else if (!PL_strcasecmp(fNextToken, "LIST") ||
!PL_strcasecmp(fNextToken, "XLIST"))
@ -1850,20 +1850,19 @@ void nsImapServerResponseParser::text()
skip_to_CRLF();
}
void nsImapServerResponseParser::parse_folder_flags()
void nsImapServerResponseParser::parse_folder_flags(bool calledForFlags)
{
uint16_t labelFlags = 0;
bool storeUserFlags = !(fSupportsUserDefinedFlags & kImapMsgSupportUserFlag) &&
calledForFlags && fFlagState;
uint16_t numOtherKeywords = 0;
do
{
AdvanceToNextToken();
if (*fNextToken == '(')
fNextToken++;
if (!PL_strncasecmp(fNextToken, "$MDNSent", 8))
fSupportsUserDefinedFlags |= kImapMsgSupportMDNSentFlag;
else if (!PL_strncasecmp(fNextToken, "$Forwarded", 10))
fSupportsUserDefinedFlags |= kImapMsgSupportForwardedFlag;
else if (!PL_strncasecmp(fNextToken, "\\Seen", 5))
if (!PL_strncasecmp(fNextToken, "\\Seen", 5))
fSettablePermanentFlags |= kImapMsgSeenFlag;
else if (!PL_strncasecmp(fNextToken, "\\Answered", 9))
fSettablePermanentFlags |= kImapMsgAnsweredFlag;
@ -1873,23 +1872,52 @@ void nsImapServerResponseParser::parse_folder_flags()
fSettablePermanentFlags |= kImapMsgDeletedFlag;
else if (!PL_strncasecmp(fNextToken, "\\Draft", 6))
fSettablePermanentFlags |= kImapMsgDraftFlag;
else if (!PL_strncasecmp(fNextToken, "$Label1", 7))
labelFlags |= 1;
else if (!PL_strncasecmp(fNextToken, "$Label2", 7))
labelFlags |= 2;
else if (!PL_strncasecmp(fNextToken, "$Label3", 7))
labelFlags |= 4;
else if (!PL_strncasecmp(fNextToken, "$Label4", 7))
labelFlags |= 8;
else if (!PL_strncasecmp(fNextToken, "$Label5", 7))
labelFlags |= 16;
else if (!PL_strncasecmp(fNextToken, "\\*", 2))
{
// User defined and special keywords (tags) can be defined and set for
// mailbox. Should only occur in PERMANENTFLAGS response.
fSupportsUserDefinedFlags |= kImapMsgSupportUserFlag;
fSupportsUserDefinedFlags |= kImapMsgSupportForwardedFlag;
fSupportsUserDefinedFlags |= kImapMsgSupportMDNSentFlag;
fSupportsUserDefinedFlags |= kImapMsgLabelFlags;
}
else
{
// Treat special and built-in $LabelX's as user defined if a
// save occurs below.
if (!PL_strncasecmp(fNextToken, "$MDNSent", 8))
fSupportsUserDefinedFlags |= kImapMsgSupportMDNSentFlag;
else if (!PL_strncasecmp(fNextToken, "$Forwarded", 10))
fSupportsUserDefinedFlags |= kImapMsgSupportForwardedFlag;
else if (!PL_strncasecmp(fNextToken, "$Label1", 7))
labelFlags |= 1;
else if (!PL_strncasecmp(fNextToken, "$Label2", 7))
labelFlags |= 2;
else if (!PL_strncasecmp(fNextToken, "$Label3", 7))
labelFlags |= 4;
else if (!PL_strncasecmp(fNextToken, "$Label4", 7))
labelFlags |= 8;
else if (!PL_strncasecmp(fNextToken, "$Label5", 7))
labelFlags |= 16;
// Save user keywords defined for mailbox, usually by other clients.
// But only do this for FLAGS response, not PERMANENTFLAGS response
// and if '\*' has not appeared in a PERMANENTFLAGS response.
if (storeUserFlags && *fNextToken != '\r')
{
if (*(fNextToken + strlen(fNextToken) - 1) != ')')
{
// Token doesn't end in ')' so save it as is.
fFlagState->SetOtherKeywords(numOtherKeywords++, nsDependentCString(fNextToken));
}
else
{
// Token ends in ')' so end of list. Change ')' to null and save.
fFlagState->SetOtherKeywords(numOtherKeywords++,
nsDependentCSubstring(fNextToken, strlen(fNextToken) - 1));
}
}
}
} while (!fAtEndOfLine && ContinueParse());
if (labelFlags == 31)
@ -1947,7 +1975,7 @@ void nsImapServerResponseParser::resp_text_code()
uint32_t saveSettableFlags = fSettablePermanentFlags;
fSupportsUserDefinedFlags = 0; // assume no unless told
fSettablePermanentFlags = 0; // assume none, unless told otherwise.
parse_folder_flags();
parse_folder_flags(false);
// if the server tells us there are no permanent flags, we're
// just going to pretend that the FLAGS response flags, if any, are
// permanent in case the server is broken. This will allow us

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

@ -137,7 +137,7 @@ protected:
virtual void resp_cond_state(bool isTagged);
virtual void text_mime2();
virtual void text();
virtual void parse_folder_flags();
virtual void parse_folder_flags(bool calledForFlags);
virtual void enable_data();
virtual void language_data();
virtual void authChallengeResponse_data();