You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2022/12/07 10:40:00 UTC
[james-project] 03/08: JAMES-3754 RFC-8440 IMAP4 Extension for Returning MYRIGHTS Information in Extended LIST
This is an automated email from the ASF dual-hosted git repository.
btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 3179b3bbc6eb36b60fb929c7eaf990139ac14fe4
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu Nov 24 18:11:34 2022 +0700
JAMES-3754 RFC-8440 IMAP4 Extension for Returning MYRIGHTS Information in Extended LIST
---
.../org/apache/james/imap/scripts/ListPlus.test | 7 +++++
.../imap/decode/parser/ListCommandParser.java | 15 ++++++++++
.../james/imap/message/request/ListRequest.java | 4 ++-
.../apache/james/imap/processor/ListProcessor.java | 33 ++++++++++++++++++----
.../pages/architecture/implemented-standards.adoc | 1 +
src/site/xdoc/protocols/imap4.xml | 1 +
6 files changed, 54 insertions(+), 7 deletions(-)
diff --git a/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/ListPlus.test b/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/ListPlus.test
index cda476cbf0..2265856c5a 100644
--- a/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/ListPlus.test
+++ b/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/ListPlus.test
@@ -49,6 +49,13 @@ S: \* LIST \(\\HasChildren\) \"\.\" \"funny\"
}
S: a1 OK LIST completed.
+C: a1 LIST "" "listtest" RETURN (MYRIGHTS)
+SUB {
+S: \* LIST \(\\HasChildren\) \"\.\" "listtest"
+S: \* MYRIGHTS "listtest" "aeiklprstwx"
+}
+S: a1 OK LIST completed.
+
C: a2 list "" funny.%
SUB {
S: \* LIST \(\\HasChildren\) \"\.\" \"funny.name with gaps\"
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ListCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ListCommandParser.java
index 95d23e1cd9..c913e12b4c 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ListCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ListCommandParser.java
@@ -229,6 +229,9 @@ public class ListCommandParser extends AbstractUidCommandParser {
if (c == 's' || c == 'S') {
return readS(request);
}
+ if (c == 'm' || c == 'M') {
+ return Pair.of(readMyRight(request), Optional.empty());
+ }
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS,
"Unknown return option: '" + request.consumeWord(ImapRequestLineReader.NoopCharValidator.INSTANCE) + "'");
}
@@ -245,6 +248,18 @@ public class ListCommandParser extends AbstractUidCommandParser {
return ListReturnOption.CHILDREN;
}
+ private ListReturnOption readMyRight(ImapRequestLineReader request) throws DecodingException {
+ assertChar(request, 'M', 'm');
+ assertChar(request, 'Y', 'y');
+ assertChar(request, 'R', 'r');
+ assertChar(request, 'I', 'i');
+ assertChar(request, 'G', 'g');
+ assertChar(request, 'H', 'h');
+ assertChar(request, 'T', 't');
+ assertChar(request, 'S', 's');
+ return ListReturnOption.MYRIGHTS;
+ }
+
private ListReturnOption readReturnSubscribed(ImapRequestLineReader request) throws DecodingException {
consumeSubscribed(request);
return ListReturnOption.SUBSCRIBED;
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/message/request/ListRequest.java b/protocols/imap/src/main/java/org/apache/james/imap/message/request/ListRequest.java
index fb1e18e794..37045a001c 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/message/request/ListRequest.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/message/request/ListRequest.java
@@ -42,7 +42,9 @@ public class ListRequest extends AbstractImapRequest {
CHILDREN,
SUBSCRIBED,
// https://www.rfc-editor.org/rfc/rfc5819.html LIST STATUS
- STATUS
+ STATUS,
+ // https://www.rfc-editor.org/rfc/rfc8440.html
+ MYRIGHTS
}
private final String baseReferenceName;
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/ListProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/ListProcessor.java
index 9ed9551e89..2e69aa0d44 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/ListProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/ListProcessor.java
@@ -31,6 +31,7 @@ import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.commons.lang3.tuple.Pair;
+import org.apache.commons.lang3.tuple.Triple;
import org.apache.james.imap.api.display.HumanReadableText;
import org.apache.james.imap.api.display.ModifiedUtf7;
import org.apache.james.imap.api.message.Capability;
@@ -41,10 +42,12 @@ import org.apache.james.imap.api.process.MailboxType;
import org.apache.james.imap.main.PathConverter;
import org.apache.james.imap.message.request.ListRequest;
import org.apache.james.imap.message.response.ListResponse;
+import org.apache.james.imap.message.response.MyRightsResponse;
import org.apache.james.mailbox.MailboxManager;
import org.apache.james.mailbox.MailboxSession;
import org.apache.james.mailbox.SubscriptionManager;
import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.MailboxACL;
import org.apache.james.mailbox.model.MailboxConstants;
import org.apache.james.mailbox.model.MailboxMetaData;
import org.apache.james.mailbox.model.MailboxPath;
@@ -67,7 +70,7 @@ public class ListProcessor<T extends ListRequest> extends AbstractMailboxProcess
public static final boolean RETURN_SUBSCRIBED = true;
public static final boolean RETURN_NON_EXISTENT = true;
private static final Logger LOGGER = LoggerFactory.getLogger(ListProcessor.class);
- private static final List<Capability> CAPA = ImmutableList.of(Capability.of("LIST-EXTENDED"), Capability.of("LIST-STATUS"));
+ private static final List<Capability> CAPA = ImmutableList.of(Capability.of("LIST-EXTENDED"), Capability.of("LIST-STATUS"), Capability.of("LIST-MYRIGHTS"));
private final SubscriptionManager subscriptionManager;
private final StatusProcessor statusProcessor;
@@ -195,6 +198,7 @@ public class ListProcessor<T extends ListRequest> extends AbstractMailboxProcess
mailboxName(isRelative, metaData.getPath(), metaData.getHierarchyDelimiter()),
metaData.getHierarchyDelimiter(),
getMailboxType(session, metaData.getPath()))))
+ .doOnNext(metaData -> respondMyRights(request, responder, mailboxSession, metaData))
.flatMap(metaData -> request.getStatusDataItems().map(statusDataItems -> statusProcessor.sendStatus(metaData.getPath(), statusDataItems, responder, session, mailboxSession)).orElse(Mono.empty()))
.then();
}
@@ -205,23 +209,25 @@ public class ListProcessor<T extends ListRequest> extends AbstractMailboxProcess
Flux.from(Throwing.supplier(() -> subscriptionManager.subscriptionsReactive(mailboxSession)).get()).collectList())
.map(tuple -> getListResponseForSelectSubscribed(tuple.getT1(), tuple.getT2(), request, mailboxSession, isRelative, mailboxQuery))
.flatMapIterable(list -> list)
- .doOnNext(pathAndResponse -> responder.respond(pathAndResponse.getRight()))
+ .doOnNext(pathAndResponse -> responder.respond(pathAndResponse.getMiddle()))
+ .doOnNext(pathAndResponse -> pathAndResponse.getRight().ifPresent(mailboxMetaData -> respondMyRights(request, responder, mailboxSession, mailboxMetaData)))
.flatMap(pathAndResponse -> request.getStatusDataItems().map(statusDataItems -> statusProcessor.sendStatus(pathAndResponse.getLeft(), statusDataItems, responder, session, mailboxSession)).orElse(Mono.empty()))
.then();
}
- private List<Pair<MailboxPath, ListResponse>> getListResponseForSelectSubscribed(Map<MailboxPath, MailboxMetaData> searchedResultMap, List<MailboxPath> allSubscribedSearch,
+ private List<Triple<MailboxPath, ListResponse, Optional<MailboxMetaData>>> getListResponseForSelectSubscribed(Map<MailboxPath, MailboxMetaData> searchedResultMap, List<MailboxPath> allSubscribedSearch,
ListRequest listRequest, MailboxSession mailboxSession, boolean relative, MailboxQuery mailboxQuery) {
- ImmutableList.Builder<Pair<MailboxPath, ListResponse>> responseBuilders = ImmutableList.builder();
+ ImmutableList.Builder<Triple<MailboxPath, ListResponse, Optional<MailboxMetaData>>> responseBuilders = ImmutableList.builder();
List<Pair<MailboxPath, ListResponse>> listRecursiveMatch = listRecursiveMatch(searchedResultMap, allSubscribedSearch, mailboxSession, relative, listRequest);
- responseBuilders.addAll(listRecursiveMatch);
+
+ listRecursiveMatch.forEach(pair -> responseBuilders.add(Triple.of(pair.getLeft(), pair.getRight(), Optional.ofNullable(searchedResultMap.get(pair.getLeft())))));
Set<MailboxPath> listRecursiveMatchPath = listRecursiveMatch.stream().map(Pair::getKey).collect(Collectors.toUnmodifiableSet());
allSubscribedSearch.stream()
.filter(subscribed -> !listRecursiveMatchPath.contains(subscribed))
.filter(mailboxQuery::isPathMatch)
.map(subscribed -> buildListResponse(searchedResultMap, mailboxSession, relative, subscribed))
- .forEach(responseBuilders::add);
+ .forEach(pair -> responseBuilders.add(Triple.of(pair.getLeft(), pair.getRight(), Optional.ofNullable(searchedResultMap.get(pair.getLeft())))));
return responseBuilders.build();
}
@@ -263,6 +269,21 @@ public class ListProcessor<T extends ListRequest> extends AbstractMailboxProcess
.collect(Collectors.toList());
}
+ private void respondMyRights(T request, Responder responder, MailboxSession mailboxSession, MailboxMetaData metaData) {
+ if (request.getReturnOptions().contains(ListRequest.ListReturnOption.MYRIGHTS)) {
+ MyRightsResponse myRightsResponse = new MyRightsResponse(metaData.getPath().getName(), getRfc4314Rights(mailboxSession, metaData));
+ responder.respond(myRightsResponse);
+ }
+ }
+
+ private MailboxACL.Rfc4314Rights getRfc4314Rights(MailboxSession mailboxSession, MailboxMetaData metaData) {
+ if (metaData.getPath().belongsTo(mailboxSession)) {
+ return MailboxACL.FULL_RIGHTS;
+ }
+ MailboxACL.EntryKey entryKey = MailboxACL.EntryKey.createUserEntryKey(mailboxSession.getUser());
+ return metaData.getResolvedAcls().getEntries().get(entryKey);
+ }
+
private MailboxQuery mailboxQuery(MailboxPath basePath, String mailboxName, MailboxSession mailboxSession) {
if (basePath.getNamespace().equals(MailboxConstants.USER_NAMESPACE)
&& basePath.getUser().equals(mailboxSession.getUser())
diff --git a/server/apps/distributed-app/docs/modules/ROOT/pages/architecture/implemented-standards.adoc b/server/apps/distributed-app/docs/modules/ROOT/pages/architecture/implemented-standards.adoc
index 44fd222004..398180a13a 100644
--- a/server/apps/distributed-app/docs/modules/ROOT/pages/architecture/implemented-standards.adoc
+++ b/server/apps/distributed-app/docs/modules/ROOT/pages/architecture/implemented-standards.adoc
@@ -70,6 +70,7 @@ The following IMAP specifications are implemented:
- link:https://datatracker.ietf.org/doc/html/rfc8438.html[RFC-8438] IMAP Extension for STATUS=SIZE
- link:https://www.rfc-editor.org/rfc/rfc5258.html[RFC-5258] IMAP LIST Command Extensions
- link:https://www.rfc-editor.org/rfc/rfc5819.html[RFC-5819] IMAP4 Extension for Returning STATUS Information in Extended LIST
+ - link:https://www.rfc-editor.org/rfc/rfc8440.html[RFC-8440] IMAP4 Extension for Returning MYRIGHTS Information in Extended LIST
Partially implemented specifications:
diff --git a/src/site/xdoc/protocols/imap4.xml b/src/site/xdoc/protocols/imap4.xml
index fdcf0a1b36..1af6934fd2 100644
--- a/src/site/xdoc/protocols/imap4.xml
+++ b/src/site/xdoc/protocols/imap4.xml
@@ -65,6 +65,7 @@
<li>IMAP ID (https://www.rfc-editor.org/rfc/rfc2971.html)</li>
<li>IMAP LIST Command Extensions (link:https://www.rfc-editor.org/rfc/rfc5258.html)</li>
<li>IMAP4 Extension for Returning STATUS Information in Extended LIST (https://www.rfc-editor.org/rfc/rfc5819.html)</li>
+ <li>IMAP4 Extension for Returning MYRIGHTS Information in Extended LIST (https://www.rfc-editor.org/rfc/rfc8440.html)</li>
</ul>
<p>We follow RFC2683 recommendations for our implementations:</p>
<ul>
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org