JAMES-2186 Move right function to RightManager
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/010f4ef9 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/010f4ef9 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/010f4ef9 Branch: refs/heads/master Commit: 010f4ef905313fd516f732ff50b6bc7a7dac25cb Parents: 2649a5c Author: Matthieu Baechler <[email protected]> Authored: Wed Oct 25 15:20:03 2017 +0200 Committer: Raphael Ouazana <[email protected]> Committed: Wed Oct 25 17:40:11 2017 +0200 ---------------------------------------------------------------------- .../org/apache/james/mailbox/RightManager.java | 127 +++++++++++++++++++ .../mailbox/store/StoreMailboxManager.java | 112 ++++++---------- .../mailbox/store/StoreMessageManager.java | 24 +--- 3 files changed, 169 insertions(+), 94 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/010f4ef9/mailbox/api/src/main/java/org/apache/james/mailbox/RightManager.java ---------------------------------------------------------------------- diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/RightManager.java b/mailbox/api/src/main/java/org/apache/james/mailbox/RightManager.java new file mode 100644 index 0000000..cd64cd6 --- /dev/null +++ b/mailbox/api/src/main/java/org/apache/james/mailbox/RightManager.java @@ -0,0 +1,127 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.mailbox; + +import org.apache.james.mailbox.exception.MailboxException; +import org.apache.james.mailbox.model.MailboxACL; +import org.apache.james.mailbox.model.MailboxACL.Right; +import org.apache.james.mailbox.model.MailboxId; +import org.apache.james.mailbox.model.MailboxPath; +import org.apache.james.mime4j.dom.address.Mailbox; + +import javax.mail.Flags; + +public interface RightManager { + /** + * Tells whether the given {@link MailboxSession}'s user has the given + * {@link MailboxACL.Right} for this {@link MessageManager}'s mailbox. + * + * @param mailboxPath MailboxPath of the mailbox we want to check + * @param right Right we want to check. + * @param session Session of the user we want to check this right against. + * @return true if the given {@link MailboxSession}'s user has the given + * {@link MailboxACL.Right} for this {@link MessageManager}'s + * mailbox; false otherwise. + * @throws MailboxException in case of unknown mailbox or unsupported right + */ + boolean hasRight(MailboxPath mailboxPath, Right right, MailboxSession session) throws MailboxException; + + /** + * Computes a result suitable for the LISTRIGHTS IMAP command. The result is + * computed for this mailbox and the given {@code identifier}. + * + * From RFC 4314 section 3.7: + * The first element of the resulting array contains the (possibly empty) + * set of rights the identifier will always be granted in the mailbox. + * Following this are zero or more right sets the identifier can be granted + * in the mailbox. Rights mentioned in the same set are tied together. The + * server MUST either grant all tied rights to the identifier in the mailbox + * or grant none. + * + * The same right MUST NOT be listed more than once in the LISTRIGHTS + * command. + * + * @param mailboxPath Path of the mailbox you want to get the rights list. + * @param identifier + * the identifier from the LISTRIGHTS command. + * @param session Right of the user performing the request. + * @return result suitable for the LISTRIGHTS IMAP command + * @throws MailboxException in case of unknown mailbox or unsupported right + */ + MailboxACL.Rfc4314Rights[] listRigths(MailboxPath mailboxPath, MailboxACL.EntryKey identifier, MailboxSession session) throws MailboxException; + + /** + * Returns the rights applicable to the user who has sent the current + * request on the mailbox designated by this mailboxPath. + * + * @param mailboxPath Path of the mailbox you want to get your rights on. + * @param session The session used to determine the user we should retrieve the rights of. + * @return the rights applicable to the user who has sent the request, + * returns {@link MailboxACL#NO_RIGHTS} if + * {@code session.getUser()} is null. + * @throws MailboxException in case of unknown mailbox or unsupported right + */ + MailboxACL.Rfc4314Rights myRights(MailboxPath mailboxPath, MailboxSession session) throws MailboxException; + + + /** + * Returns the rights applicable to the user who has sent the current + * request on the mailbox designated by this mailboxPath. + * + * @param mailboxId Id of the mailbox you want to get your rights on. + * @param session The session used to determine the user we should retrieve the rights of. + * @return the rights applicable to the user who has sent the request, + * returns {@link MailboxACL#NO_RIGHTS} if + * {@code session.getUser()} is null. + * @throws MailboxException in case of unknown mailbox or unsupported right + */ + MailboxACL.Rfc4314Rights myRights(MailboxId mailboxId, MailboxSession session) throws MailboxException; + + /** + * Update the Mailbox ACL of the designated mailbox. We can either ADD REPLACE or REMOVE entries. + * + * @param mailboxPath Path of the mailbox you want to apply rights on. + * @param mailboxACLCommand Update to perform. + * @param session The session used to determine the user used to apply rights. + * @throws MailboxException in case of unknown mailbox or unsupported right + */ + void applyRightsCommand(MailboxPath mailboxPath, MailboxACL.ACLCommand mailboxACLCommand, MailboxSession session) throws MailboxException; + + /** + * Reset the Mailbox ACL of the designated mailbox. + * + * @param mailboxPath Path of the mailbox you want to set the rights. + * @param mailboxACL New ACL value + * @param session The session used to determine the user used to set rights. + * @throws MailboxException in case of unknown mailbox or unsupported right + */ + void setRights(MailboxPath mailboxPath, MailboxACL mailboxACL, MailboxSession session) throws MailboxException; + + + /** + * Reset the Mailbox ACL of the designated mailbox. + * + * @param mailboxId Id of the mailbox you want to set the rights. + * @param mailboxACL New ACL value + * @param session The session used to determine the user used to set rights. + * @throws MailboxException in case of unknown mailbox or unsupported right + */ + void setRights(MailboxId mailboxId, MailboxACL mailboxACL, MailboxSession session) throws MailboxException; +} http://git-wip-us.apache.org/repos/asf/james-project/blob/010f4ef9/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java ---------------------------------------------------------------------- diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java index 691a56e..de7424b 100644 --- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java +++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java @@ -40,15 +40,12 @@ import org.apache.james.mailbox.MailboxSessionIdGenerator; import org.apache.james.mailbox.MessageManager; import org.apache.james.mailbox.RequestAware; import org.apache.james.mailbox.StandardMailboxMetaDataComparator; -import org.apache.james.mailbox.acl.GroupMembershipResolver; -import org.apache.james.mailbox.acl.MailboxACLResolver; import org.apache.james.mailbox.exception.AnnotationException; import org.apache.james.mailbox.exception.BadCredentialsException; import org.apache.james.mailbox.exception.MailboxException; import org.apache.james.mailbox.exception.MailboxExistsException; import org.apache.james.mailbox.exception.MailboxNotFoundException; import org.apache.james.mailbox.exception.NotAdminException; -import org.apache.james.mailbox.exception.UnsupportedRightException; import org.apache.james.mailbox.exception.UserDoesNotExistException; import org.apache.james.mailbox.model.MailboxACL; import org.apache.james.mailbox.model.MailboxACL.Rfc4314Rights; @@ -115,9 +112,7 @@ public class StoreMailboxManager implements MailboxManager { private Authorizator authorizator; - private final MailboxACLResolver aclResolver; - - private final GroupMembershipResolver groupMembershipResolver; + private final StoreRightManager storeRightManager; private final static Random RANDOM = new Random(); @@ -150,43 +145,40 @@ public class StoreMailboxManager implements MailboxManager { @Inject public StoreMailboxManager(MailboxSessionMapperFactory mailboxSessionMapperFactory, Authenticator authenticator, Authorizator authorizator, - MailboxPathLocker locker, MailboxACLResolver aclResolver, GroupMembershipResolver groupMembershipResolver, - MessageParser messageParser, MessageId.Factory messageIdFactory, MailboxEventDispatcher mailboxEventDispatcher, - DelegatingMailboxListener delegatingListener) { - this(mailboxSessionMapperFactory, authenticator, authorizator, locker, aclResolver, groupMembershipResolver, messageParser, messageIdFactory, - MailboxConstants.DEFAULT_LIMIT_ANNOTATIONS_ON_MAILBOX, MailboxConstants.DEFAULT_LIMIT_ANNOTATION_SIZE, mailboxEventDispatcher, delegatingListener); + MailboxPathLocker locker, MessageParser messageParser, MessageId.Factory messageIdFactory, MailboxEventDispatcher mailboxEventDispatcher, + DelegatingMailboxListener delegatingListener, StoreRightManager storeRightManager) { + this(mailboxSessionMapperFactory, authenticator, authorizator, locker, messageParser, messageIdFactory, + MailboxConstants.DEFAULT_LIMIT_ANNOTATIONS_ON_MAILBOX, MailboxConstants.DEFAULT_LIMIT_ANNOTATION_SIZE, mailboxEventDispatcher, + delegatingListener, storeRightManager); } public StoreMailboxManager(MailboxSessionMapperFactory mailboxSessionMapperFactory, Authenticator authenticator, Authorizator authorizator, - MailboxPathLocker locker, MailboxACLResolver aclResolver, GroupMembershipResolver groupMembershipResolver, - MessageParser messageParser, MessageId.Factory messageIdFactory) { - this(mailboxSessionMapperFactory, authenticator, authorizator, locker, aclResolver, groupMembershipResolver, messageParser, messageIdFactory, - MailboxConstants.DEFAULT_LIMIT_ANNOTATIONS_ON_MAILBOX, MailboxConstants.DEFAULT_LIMIT_ANNOTATION_SIZE); + MailboxPathLocker locker, MessageParser messageParser, MessageId.Factory messageIdFactory, StoreRightManager storeRightManager) { + this(mailboxSessionMapperFactory, authenticator, authorizator, locker, messageParser, messageIdFactory, + MailboxConstants.DEFAULT_LIMIT_ANNOTATIONS_ON_MAILBOX, MailboxConstants.DEFAULT_LIMIT_ANNOTATION_SIZE, storeRightManager); } public StoreMailboxManager(MailboxSessionMapperFactory mailboxSessionMapperFactory, Authenticator authenticator, Authorizator authorizator, - MailboxACLResolver aclResolver, GroupMembershipResolver groupMembershipResolver, MessageParser messageParser, - MessageId.Factory messageIdFactory, int limitOfAnnotations, int limitAnnotationSize) { - this(mailboxSessionMapperFactory, authenticator, authorizator, new JVMMailboxPathLocker(), aclResolver, groupMembershipResolver, messageParser, messageIdFactory, - limitOfAnnotations, limitAnnotationSize); + MessageParser messageParser, MessageId.Factory messageIdFactory, int limitOfAnnotations, int limitAnnotationSize, StoreRightManager storeRightManager) { + this(mailboxSessionMapperFactory, authenticator, authorizator, new JVMMailboxPathLocker(), messageParser, messageIdFactory, + limitOfAnnotations, limitAnnotationSize, storeRightManager); } public StoreMailboxManager(MailboxSessionMapperFactory mailboxSessionMapperFactory, Authenticator authenticator, Authorizator authorizator, - MailboxPathLocker locker, MailboxACLResolver aclResolver, GroupMembershipResolver groupMembershipResolver, MessageParser messageParser, - MessageId.Factory messageIdFactory, int limitOfAnnotations, int limitAnnotationSize) { - this(mailboxSessionMapperFactory, authenticator, authorizator, locker, aclResolver, groupMembershipResolver, messageParser, messageIdFactory, - limitOfAnnotations, limitAnnotationSize, null, null); + MailboxPathLocker locker, MessageParser messageParser, + MessageId.Factory messageIdFactory, int limitOfAnnotations, int limitAnnotationSize, StoreRightManager storeRightManager) { + this(mailboxSessionMapperFactory, authenticator, authorizator, locker, messageParser, messageIdFactory, + limitOfAnnotations, limitAnnotationSize, null, null, storeRightManager); } public StoreMailboxManager(MailboxSessionMapperFactory mailboxSessionMapperFactory, Authenticator authenticator, Authorizator authorizator, - MailboxPathLocker locker, MailboxACLResolver aclResolver, GroupMembershipResolver groupMembershipResolver, MessageParser messageParser, - MessageId.Factory messageIdFactory, int limitOfAnnotations, int limitAnnotationSize, MailboxEventDispatcher mailboxEventDispatcher, DelegatingMailboxListener delegatingListener) { + MailboxPathLocker locker, MessageParser messageParser, + MessageId.Factory messageIdFactory, int limitOfAnnotations, int limitAnnotationSize, MailboxEventDispatcher mailboxEventDispatcher, + DelegatingMailboxListener delegatingListener, StoreRightManager storeRightManager) { this.authenticator = authenticator; this.authorizator = authorizator; this.locker = locker; this.mailboxSessionMapperFactory = mailboxSessionMapperFactory; - this.aclResolver = aclResolver; - this.groupMembershipResolver = groupMembershipResolver; this.messageParser = messageParser; this.messageIdFactory = messageIdFactory; this.limitOfAnnotations = limitOfAnnotations; @@ -194,6 +186,7 @@ public class StoreMailboxManager implements MailboxManager { this.delegatingListener = delegatingListener; this.dispatcher = mailboxEventDispatcher; this.immutableMailboxMessageFactory = new ImmutableMailboxMessage.Factory(this); + this.storeRightManager = storeRightManager; } protected Factory getMessageIdFactory() { @@ -347,12 +340,8 @@ public class StoreMailboxManager implements MailboxManager { return locker; } - public MailboxACLResolver getAclResolver() { - return aclResolver; - } - - public GroupMembershipResolver getGroupMembershipResolver() { - return groupMembershipResolver; + public StoreRightManager getStoreRightManager() { + return storeRightManager; } public MessageParser getMessageParser() { @@ -476,8 +465,9 @@ public class StoreMailboxManager implements MailboxManager { */ protected StoreMessageManager createMessageManager(Mailbox mailbox, MailboxSession session) throws MailboxException { return new StoreMessageManager(getMapperFactory(), getMessageSearchIndex(), getEventDispatcher(), - getLocker(), mailbox, getAclResolver(), getGroupMembershipResolver(), getQuotaManager(), - getQuotaRootResolver(), getMessageParser(), getMessageIdFactory(), getBatchSizes(), getImmutableMailboxMessageFactory()); + getLocker(), mailbox, getQuotaManager(), + getQuotaRootResolver(), getMessageParser(), getMessageIdFactory(), getBatchSizes(), + getImmutableMailboxMessageFactory(), getStoreRightManager()); } /** @@ -540,7 +530,7 @@ public class StoreMailboxManager implements MailboxManager { } private boolean userHasLookupRightsOn(Mailbox mailbox, MailboxSession session) throws MailboxException { - return hasRight(mailbox, Right.Lookup, session); + return storeRightManager.hasRight(mailbox, Right.Lookup, session); } @Override @@ -691,7 +681,7 @@ public class StoreMailboxManager implements MailboxManager { List<Mailbox> mailboxes = Stream.concat(baseMailboxes, delegatedMailboxes) .distinct() - .filter(Throwing.predicate(mailbox -> hasRight(mailbox, right, session))) + .filter(Throwing.predicate(mailbox -> storeRightManager.hasRight(mailbox, right, session))) .collect(Guavate.toImmutableList()); return mailboxes @@ -832,69 +822,39 @@ public class StoreMailboxManager implements MailboxManager { @Override public boolean hasRight(MailboxPath mailboxPath, Right right, MailboxSession session) throws MailboxException { - MailboxMapper mapper = mailboxSessionMapperFactory.getMailboxMapper(session); - Mailbox mailbox = mapper.findMailboxByPath(mailboxPath); - return hasRight(mailbox, right, session); - } - - private boolean hasRight(Mailbox mailbox, Right right, MailboxSession session) throws MailboxException { - MailboxSession.User user = session.getUser(); - String userName = user != null ? user.getUserName() : null; - return aclResolver.hasRight(userName, groupMembershipResolver, right, mailbox.getACL(), mailbox.getUser(), new GroupFolderResolver(session).isGroupFolder(mailbox)); + return storeRightManager.hasRight(mailboxPath, right, session); } @Override public Rfc4314Rights myRights(MailboxPath mailboxPath, MailboxSession session) throws MailboxException { - MailboxMapper mapper = mailboxSessionMapperFactory.getMailboxMapper(session); - Mailbox mailbox = mapper.findMailboxByPath(mailboxPath); - return myRights(session, mailbox); + return storeRightManager.myRights(mailboxPath, session); } @Override public Rfc4314Rights myRights(MailboxId mailboxId, MailboxSession session) throws MailboxException { - MailboxMapper mapper = mailboxSessionMapperFactory.getMailboxMapper(session); - Mailbox mailbox = mapper.findMailboxById(mailboxId); - return myRights(session, mailbox); - } - - private Rfc4314Rights myRights(MailboxSession session, Mailbox mailbox) throws UnsupportedRightException { - MailboxSession.User user = session.getUser(); - if (user != null) { - return aclResolver.resolveRights(user.getUserName(), groupMembershipResolver, mailbox.getACL(), mailbox.getUser(), new GroupFolderResolver(session).isGroupFolder(mailbox)); - } else { - return MailboxACL.NO_RIGHTS; - } + return storeRightManager.myRights(mailboxId, session); } + @Override public Rfc4314Rights[] listRigths(MailboxPath mailboxPath, MailboxACL.EntryKey key, MailboxSession session) throws MailboxException { - MailboxMapper mapper = mailboxSessionMapperFactory.getMailboxMapper(session); - Mailbox mailbox = mapper.findMailboxByPath(mailboxPath); - return aclResolver.listRights(key, groupMembershipResolver, mailbox.getUser(), new GroupFolderResolver(session).isGroupFolder(mailbox)); + return storeRightManager.listRigths(mailboxPath, key, session); } @Override public void applyRightsCommand(MailboxPath mailboxPath, MailboxACL.ACLCommand mailboxACLCommand, MailboxSession session) throws MailboxException { - MailboxMapper mapper = mailboxSessionMapperFactory.getMailboxMapper(session); - Mailbox mailbox = mapper.findMailboxByPath(mailboxPath); - mapper.execute(Mapper.toTransaction(() -> mapper.updateACL(mailbox, mailboxACLCommand))); + storeRightManager.applyRightsCommand(mailboxPath, mailboxACLCommand, session); } - + @Override public void setRights(MailboxPath mailboxPath, MailboxACL mailboxACL, MailboxSession session) throws MailboxException { - MailboxMapper mapper = mailboxSessionMapperFactory.getMailboxMapper(session); - Mailbox mailbox = mapper.findMailboxByPath(mailboxPath); - setRights(mailbox, mailboxACL, mapper); + storeRightManager.setRights(mailboxPath, mailboxACL, session); } @Override public void setRights(MailboxId mailboxId, MailboxACL mailboxACL, MailboxSession session) throws MailboxException { MailboxMapper mapper = mailboxSessionMapperFactory.getMailboxMapper(session); Mailbox mailbox = mapper.findMailboxById(mailboxId); - setRights(mailbox, mailboxACL, mapper); - } - - public void setRights(Mailbox mailbox, MailboxACL mailboxACL, MailboxMapper mapper) throws MailboxException { - mapper.execute(Mapper.toTransaction(() -> mapper.setACL(mailbox, mailboxACL))); + storeRightManager.setRights(mailbox.generateAssociatedPath(), mailboxACL, session); } @Override http://git-wip-us.apache.org/repos/asf/james-project/blob/010f4ef9/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java ---------------------------------------------------------------------- diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java index d903f3d..64a0bad 100644 --- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java +++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java @@ -142,9 +142,7 @@ public class StoreMessageManager implements org.apache.james.mailbox.MessageMana private final MessageSearchIndex index; - private final MailboxACLResolver aclResolver; - - private final GroupMembershipResolver groupMembershipResolver; + private final StoreRightManager storeRightManager; private final QuotaManager quotaManager; @@ -161,23 +159,22 @@ public class StoreMessageManager implements org.apache.james.mailbox.MessageMana private final ImmutableMailboxMessage.Factory immutableMailboxMessageFactory; public StoreMessageManager(MailboxSessionMapperFactory mapperFactory, MessageSearchIndex index, MailboxEventDispatcher dispatcher, - MailboxPathLocker locker, Mailbox mailbox, MailboxACLResolver aclResolver, GroupMembershipResolver groupMembershipResolver, + MailboxPathLocker locker, Mailbox mailbox, QuotaManager quotaManager, QuotaRootResolver quotaRootResolver, MessageParser messageParser, MessageId.Factory messageIdFactory, BatchSizes batchSizes, - ImmutableMailboxMessage.Factory immutableMailboxMessageFactory) + ImmutableMailboxMessage.Factory immutableMailboxMessageFactory, StoreRightManager storeRightManager) throws MailboxException { this.mailbox = mailbox; this.dispatcher = dispatcher; this.mapperFactory = mapperFactory; this.index = index; this.locker = locker; - this.aclResolver = aclResolver; - this.groupMembershipResolver = groupMembershipResolver; this.quotaManager = quotaManager; this.quotaRootResolver = quotaRootResolver; this.messageParser = messageParser; this.messageIdFactory = messageIdFactory; this.batchSizes = batchSizes; this.immutableMailboxMessageFactory = immutableMailboxMessageFactory; + this.storeRightManager = storeRightManager; } protected Factory getMessageIdFactory() { @@ -467,7 +464,7 @@ public class StoreMessageManager implements org.apache.james.mailbox.MessageMana * @throws MailboxException */ public boolean isWriteable(MailboxSession session) throws MailboxException { - return aclResolver.isReadWrite(myRights(session), getSharedPermanentFlags(session)); + return storeRightManager.isReadWrite(session, mailbox, getSharedPermanentFlags(session)); } @Override @@ -796,15 +793,6 @@ public class StoreMessageManager implements org.apache.james.mailbox.MessageMana return messageMapper.findFirstUnseenMessageUid(getMailboxEntity()); } - private Rfc4314Rights myRights(MailboxSession session) throws MailboxException { - User user = session.getUser(); - if (user != null) { - return aclResolver.resolveRights(user.getUserName(), groupMembershipResolver, mailbox.getACL(), mailbox.getUser(), new GroupFolderResolver(session).isGroupFolder(mailbox)); - } else { - return MailboxACL.NO_RIGHTS; - } - } - /** * Applies the global ACL (if there are any) to the mailbox ACL. * @@ -814,7 +802,7 @@ public class StoreMessageManager implements org.apache.james.mailbox.MessageMana * @throws UnsupportedRightException */ protected MailboxACL getResolvedMailboxACL(MailboxSession mailboxSession) throws UnsupportedRightException { - return filteredForSession(mailbox, aclResolver.applyGlobalACL(mailbox.getACL(), new GroupFolderResolver(mailboxSession).isGroupFolder(mailbox)), mailboxSession); + return StoreRightManager.filteredForSession(mailbox, mailbox.getACL(), mailboxSession); } /** --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
