JAMES-2161 Keywords lenient factory was inconsistent upon various representation

Sanitizing of invalid keyword value, for instance containing "&" was
only done for flags, but not for strings


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/2a65542b
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/2a65542b
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/2a65542b

Branch: refs/heads/master
Commit: 2a65542b458afbff5e30e11e4421526ae4a8979f
Parents: 6a0715d
Author: Benoit Tellier <btell...@linagora.com>
Authored: Fri Nov 23 10:52:37 2018 +0700
Committer: Benoit Tellier <btell...@linagora.com>
Committed: Tue Nov 27 09:01:54 2018 +0700

----------------------------------------------------------------------
 .../org/apache/james/jmap/model/Keywords.java   | 46 +++++++++++++-------
 .../apache/james/jmap/model/KeywordsTest.java   | 20 +++++++++
 2 files changed, 51 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/2a65542b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Keywords.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Keywords.java 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Keywords.java
index 9eeb9c6..4a3b6a4 100644
--- 
a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Keywords.java
+++ 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/Keywords.java
@@ -22,6 +22,7 @@ package org.apache.james.jmap.model;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import java.util.function.Predicate;
 import java.util.stream.Stream;
@@ -29,6 +30,7 @@ import java.util.stream.Stream;
 import javax.mail.Flags;
 
 import org.apache.james.mailbox.FlagsBuilder;
+import org.apache.james.util.OptionalUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -71,12 +73,32 @@ public class Keywords {
             KeywordFilter KEEP_ALL = keyword -> true;
         }
 
+        @FunctionalInterface
+        interface ToKeyword {
+            ToKeyword STRICT = value -> Optional.of(Keyword.of(value));
+            ToKeyword LENIENT = value -> {
+                Optional<Keyword> result = Keyword.parse(value);
+                if (!result.isPresent()) {
+                    LOGGER.warn("Fail to parse {} flag", value);
+                }
+                return result;
+            };
+
+            Optional<Keyword> toKeyword(String value);
+
+            default Stream<Keyword> asKeywordStream(String value) {
+                return OptionalUtils.toStream(toKeyword(value));
+            }
+        }
+
         private final KeywordsValidator validator;
         private final Predicate<Keyword> filter;
+        private final ToKeyword toKeyword;
 
-        public KeywordsFactory(KeywordsValidator validator, Predicate<Keyword> 
filter) {
+        public KeywordsFactory(KeywordsValidator validator, Predicate<Keyword> 
filter, ToKeyword toKeyword) {
             this.validator = validator;
             this.filter = filter;
+            this.toKeyword = toKeyword;
         }
 
         public Keywords fromSet(Set<Keyword> setKeywords) {
@@ -94,7 +116,7 @@ public class Keywords {
 
         public Keywords fromList(List<String> keywords) {
             return fromSet(keywords.stream()
-                    .map(Keyword::of)
+                    .flatMap(toKeyword::asKeywordStream)
                     .collect(Guavate.toImmutableSet()));
         }
 
@@ -103,9 +125,10 @@ public class Keywords {
             Preconditions.checkArgument(mapKeywords.values()
                 .stream()
                 .allMatch(keywordValue -> keywordValue), "Keyword must be 
true");
+
             Set<Keyword> setKeywords = mapKeywords.keySet()
                 .stream()
-                .map(Keyword::of)
+                .flatMap(toKeyword::asKeywordStream)
                 .collect(Guavate.toImmutableSet());
 
             return fromSet(setKeywords);
@@ -114,30 +137,23 @@ public class Keywords {
         public Keywords fromFlags(Flags flags) {
             return fromSet(Stream.concat(
                         Stream.of(flags.getUserFlags())
-                            .flatMap(this::asKeyword),
+                            .flatMap(toKeyword::asKeywordStream),
                         Stream.of(flags.getSystemFlags())
                             .map(Keyword::fromFlag))
                     .collect(Guavate.toImmutableSet()));
         }
-
-        private Stream<Keyword> asKeyword(String flagName) {
-            try {
-                return Stream.of(Keyword.of(flagName));
-            } catch (IllegalArgumentException e) {
-                LOGGER.warn("Fail to parse {} flag", flagName, e);
-                return Stream.of();
-            }
-        }
     }
 
     public static KeywordsFactory strictFactory() {
         return new 
KeywordsFactory(KeywordsFactory.KeywordsValidator.THROW_ON_IMAP_NON_EXPOSED_KEYWORDS,
-            KeywordsFactory.KeywordFilter.KEEP_ALL);
+            KeywordsFactory.KeywordFilter.KEEP_ALL,
+            KeywordsFactory.ToKeyword.STRICT);
     }
 
     public static KeywordsFactory lenientFactory() {
         return new 
KeywordsFactory(KeywordsFactory.KeywordsValidator.IGNORE_NON_EXPOSED_IMAP_KEYWORDS,
-            KeywordsFactory.KeywordFilter.FILTER_IMAP_NON_EXPOSED_KEYWORDS);
+            KeywordsFactory.KeywordFilter.FILTER_IMAP_NON_EXPOSED_KEYWORDS,
+            KeywordsFactory.ToKeyword.LENIENT);
     }
 
     private final ImmutableSet<Keyword> keywords;

http://git-wip-us.apache.org/repos/asf/james-project/blob/2a65542b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/KeywordsTest.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/KeywordsTest.java
 
b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/KeywordsTest.java
index 0c5162d..b8940a8 100644
--- 
a/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/KeywordsTest.java
+++ 
b/server/protocols/jmap/src/test/java/org/apache/james/jmap/model/KeywordsTest.java
@@ -185,4 +185,24 @@ public class KeywordsTest {
         assertThat(keywords.getKeywords())
             .containsOnly(Keyword.ANSWERED, Keyword.FLAGGED);
     }
+
+    @Test
+    public void fromListShouldNotThrowOnInvalidKeywordForLenientFactory() {
+        assertThat(Keywords.lenientFactory()
+            .fromList(ImmutableList.of("in&valid")))
+            .isEqualTo(Keywords.DEFAULT_VALUE);
+    }
+
+    @Test
+    public void fromMapShouldNotThrowOnInvalidKeywordForLenientFactory() {
+        assertThat(Keywords.lenientFactory()
+            .fromMap(ImmutableMap.of("in&valid", true)))
+            .isEqualTo(Keywords.DEFAULT_VALUE);
+    }
+    @Test
+    public void fromFlagsShouldNotThrowOnInvalidKeywordForLenientFactory() {
+        assertThat(Keywords.lenientFactory()
+            .fromFlags(new Flags("in&valid")))
+            .isEqualTo(Keywords.DEFAULT_VALUE);
+    }
 }
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org
For additional commands, e-mail: server-dev-h...@james.apache.org

Reply via email to