Bug 1260059 - Allow setting/resetting junk marking by user for yahoo/aol to stick. r=jorgk DONTBUILD
authorGene Smith <gds@chartertn.net>
Fri, 01 Mar 2019 23:25:16 -0500
changeset 25992 85404debffdeecc7bdf30abb7630fd72993329aa
parent 25991 da0380b3b4b06e83466d6a79d006feb8f1900975
child 25993 838dbfa07a7b68d929876edb5f88aa7a05262d88
push id15600
push usermozilla@jorgk.com
push dateSat, 02 Mar 2019 09:05:52 +0000
treeherdercomm-central@85404debffde [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorgk
bugs1260059
Bug 1260059 - Allow setting/resetting junk marking by user for yahoo/aol to stick. r=jorgk DONTBUILD
mailnews/imap/src/nsImapProtocol.cpp
mailnews/imap/src/nsImapServerResponseParser.cpp
mailnews/imap/src/nsImapServerResponseParser.h
--- a/mailnews/imap/src/nsImapProtocol.cpp
+++ b/mailnews/imap/src/nsImapProtocol.cpp
@@ -2882,37 +2882,72 @@ void nsImapProtocol::ProcessSelectedStat
 
           m_runningUrl->GetCustomAttributeToFetch(attribute);
           m_runningUrl->GetListOfMessageIds(messageIdString);
           FetchMsgAttribute(messageIdString, attribute);
         }
         break;
       case nsIImapUrl::nsImapMsgStoreCustomKeywords:
         {
-          // if the server doesn't support user defined flags, don't try to set them.
-          uint16_t userFlags;
+          // If the server doesn't support user defined flags, don't try to
+          // define/set new ones. But if this is an attempt by TB to set or
+          // reset flags "Junk" or "NonJunk", change "Junk" or "NonJunk" to
+          // "$Junk" or "$NotJunk" respectively and store the modified flag
+          // name if the server doesn't support storing user defined flags
+          // and the server does allow storing the almost-standard flag names
+          // "$Junk" and "$NotJunk". Yahoo imap server is an example of this.
+          uint16_t userFlags = 0;
           GetSupportedUserFlags(&userFlags);
-          if (! (userFlags & kImapMsgSupportUserFlag))
-            break;
+          bool userDefinedSettable = userFlags & kImapMsgSupportUserFlag;
+          bool stdJunkOk = GetServerStateParser().IsStdJunkNotJunkUseOk();
+
           nsCString messageIdString;
           nsCString addFlags;
           nsCString subtractFlags;
 
           m_runningUrl->GetListOfMessageIds(messageIdString);
           m_runningUrl->GetCustomAddFlags(addFlags);
           m_runningUrl->GetCustomSubtractFlags(subtractFlags);
           if (!addFlags.IsEmpty())
           {
+            if (!userDefinedSettable)
+            {
+              if (stdJunkOk)
+              {
+                if (addFlags.EqualsIgnoreCase("junk"))
+                  addFlags = "$Junk";
+                else if (addFlags.EqualsIgnoreCase("nonjunk"))
+                  addFlags = "$NotJunk";
+                else
+                  break;
+              }
+              else
+                break;
+            }
             nsAutoCString storeString("+FLAGS (");
             storeString.Append(addFlags);
             storeString.Append(')');
             Store(messageIdString, storeString.get(), true);
           }
           if (!subtractFlags.IsEmpty())
           {
+            if (!userDefinedSettable)
+            {
+              if (stdJunkOk)
+              {
+                if (subtractFlags.EqualsIgnoreCase("junk"))
+                  subtractFlags = "$Junk";
+                else if (subtractFlags.EqualsIgnoreCase("nonjunk"))
+                  subtractFlags = "$NotJunk";
+                else
+                  break;
+              }
+              else
+                break;
+            }
             nsAutoCString storeString("-FLAGS (");
             storeString.Append(subtractFlags);
             storeString.Append(')');
             Store(messageIdString, storeString.get(), true);
           }
         }
         break;
       case nsIImapUrl::nsImapDeleteMsg:
--- a/mailnews/imap/src/nsImapServerResponseParser.cpp
+++ b/mailnews/imap/src/nsImapServerResponseParser.cpp
@@ -53,16 +53,17 @@ nsImapServerResponseParser::nsImapServer
   fHighestModSeq = 0;
   fAuthChallenge = nullptr;
   fStatusUnseenMessages = 0;
   fStatusRecentMessages = 0;
   fStatusNextUID = nsMsgKey_None;
   fStatusExistingMessages = 0;
   fReceivedHeaderOrSizeForUID = nsMsgKey_None;
   fCondStoreEnabled = false;
+  fStdJunkNotJunkUseOk = false;
 }
 
 nsImapServerResponseParser::~nsImapServerResponseParser()
 {
   PR_Free( fCurrentCommandTag );
   delete fSearchResults;
   PR_Free( fFolderAdminUrl );
   PR_Free( fNetscapeServerVersionString );
@@ -1848,18 +1849,18 @@ void nsImapServerResponseParser::text_mi
 void nsImapServerResponseParser::text()
 {
   skip_to_CRLF();
 }
 
 void nsImapServerResponseParser::parse_folder_flags(bool calledForFlags)
 {
   uint16_t labelFlags = 0;
-  bool storeUserFlags = !(fSupportsUserDefinedFlags & kImapMsgSupportUserFlag) &&
-                        calledForFlags && fFlagState;
+  uint16_t junkNotJunkFlags = 0;
+  bool storeUserFlags = calledForFlags && fFlagState;
   uint16_t numOtherKeywords = 0;
 
   do
   {
     AdvanceToNextToken();
     if (*fNextToken == '(')
       fNextToken++;
     if (!PL_strncasecmp(fNextToken, "\\Seen", 5))
@@ -1879,57 +1880,70 @@ void nsImapServerResponseParser::parse_f
       fSupportsUserDefinedFlags |= kImapMsgSupportUserFlag;
       fSupportsUserDefinedFlags |= kImapMsgSupportForwardedFlag;
       fSupportsUserDefinedFlags |= kImapMsgSupportMDNSentFlag;
       fSupportsUserDefinedFlags |= kImapMsgLabelFlags;
     }
     else
     {
       // Treat special and built-in $LabelX's as user defined if a
-      // save occurs below.
+      // store occurs below. Include $Junk/$NotJunk in this too.
       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;
+      else if (!PL_strncasecmp(fNextToken, "$Junk", 5))
+        junkNotJunkFlags |= 1;
+      else if (!PL_strncasecmp(fNextToken, "$NotJunk", 8))
+        junkNotJunkFlags |= 2;
 
-      // 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.
+      // Store user keywords defined for mailbox, usually by other clients.
+      // But only do this for FLAGS response, not PERMANENTFLAGS response.
+      // This is only needed if '\*' does not appear in a PERMANENTFLAGS
+      // response indicating the user defined keywords are not allowed. But this
+      // is not known until this function is called for PERMANENTFLAGS which
+      // typically occurs after FLAGS, so must store them regardless.
       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.
+          // Token ends in ')' so end of list. Save all but ending ')'.
           fFlagState->SetOtherKeywords(numOtherKeywords++,
                                        nsDependentCSubstring(fNextToken, strlen(fNextToken) - 1));
         }
       }
     }
   } while (!fAtEndOfLine && ContinueParse());
 
   if (labelFlags == 31)
     fSupportsUserDefinedFlags |= kImapMsgLabelFlags;
 
   if (fFlagState)
     fFlagState->OrSupportedUserFlags(fSupportsUserDefinedFlags);
+
+  if (storeUserFlags)
+  {
+    // Set true if both "$Junk" and "$NotJunk" appear in FLAGS.
+    fStdJunkNotJunkUseOk = (junkNotJunkFlags == 3);
+  }
 }
 /*
   resp_text_code  ::= ("ALERT" / "PARSE" /
                               "PERMANENTFLAGS" SPACE "(" #(flag / "\*") ")" /
                               "READ-ONLY" / "READ-WRITE" / "TRYCREATE" /
                               "UIDVALIDITY" SPACE nz_number /
                               "UNSEEN" SPACE nz_number /
                               "HIGHESTMODSEQ" SPACE nz_number /
--- a/mailnews/imap/src/nsImapServerResponseParser.h
+++ b/mailnews/imap/src/nsImapServerResponseParser.h
@@ -46,16 +46,17 @@ public:
         kNonAuthenticated,
         kAuthenticated,
         kFolderSelected
     } ;
 
   virtual eIMAPstate GetIMAPstate();
   virtual bool WaitingForMoreClientInput() { return fWaitingForMoreClientInput; }
   const char *GetSelectedMailboxName();   // can be NULL
+  bool IsStdJunkNotJunkUseOk() { return fStdJunkNotJunkUseOk; }
 
   // if we get a PREAUTH greeting from the server, initialize the parser to begin in
   // the kAuthenticated state
   void PreauthSetAuthenticatedState();
 
   // these functions represent the state of the currently selected
   // folder
   bool       CurrentFolderReadOnly();
@@ -193,16 +194,17 @@ private:
   bool            fCurrentLineContainedFlagInfo;
   bool            fFetchingAllFlags;
   bool            fWaitingForMoreClientInput;
   // Is the server a Netscape 3.x Messaging Server?
   bool            fServerIsNetscape3xServer;
   bool            fDownloadingHeaders;
   bool            fCurrentCommandIsSingleMessageFetch;
   bool            fGotPermanentFlags;
+  bool            fStdJunkNotJunkUseOk;
   imapMessageFlagsType   fSavedFlagInfo;
   nsTArray<nsCString> fCustomFlags;
 
   uint16_t  fSupportsUserDefinedFlags;
   uint16_t  fSettablePermanentFlags;
 
   int32_t           fFolderUIDValidity;
   int32_t           fNumberOfUnseenMessages;