diff --git a/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java b/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java
index cbeb56d60f2ecf2c14000f897ef145c849bea0c8..99cdce517842fcceb6ff98bc6b22b82921713388 100644
--- a/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java
+++ b/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java
@@ -55,6 +55,7 @@ import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
 import static org.briarproject.api.clients.ProtocolEngine.StateUpdate;
 import static org.briarproject.api.forum.ForumConstants.CONTACT_ID;
+import static org.briarproject.api.forum.ForumConstants.FORUM_ID;
 import static org.briarproject.api.forum.ForumConstants.FORUM_SALT_LENGTH;
 import static org.briarproject.api.forum.ForumConstants.IS_SHARER;
 import static org.briarproject.api.forum.ForumConstants.LOCAL;
@@ -67,6 +68,7 @@ import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_ACCEPT;
 import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_DECLINE;
 import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_INVITATION;
 import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_LEAVE;
+import static org.briarproject.api.forum.ForumConstants.STATE;
 import static org.briarproject.api.forum.ForumConstants.TASK_ADD_FORUM_TO_LIST_SHARED_WITH_US;
 import static org.briarproject.api.forum.ForumConstants.TASK_ADD_FORUM_TO_LIST_TO_BE_SHARED_BY_US;
 import static org.briarproject.api.forum.ForumConstants.TASK_ADD_SHARED_FORUM;
@@ -155,16 +157,18 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
 
 	@Override
 	public void removingContact(Transaction txn, Contact c) throws DbException {
+		// query for this contact c
+		BdfDictionary query = BdfDictionary.of(
+				new BdfEntry(CONTACT_ID, c.getId().getInt())
+		);
+
 		// clean up session states with that contact from localGroup
-		Long id = (long) c.getId().getInt();
 		try {
 			Map<MessageId, BdfDictionary> map = clientHelper
-					.getMessageMetadataAsDictionary(txn, localGroup.getId());
+					.getMessageMetadataAsDictionary(txn, localGroup.getId(),
+							query);
 			for (Map.Entry<MessageId, BdfDictionary> entry : map.entrySet()) {
-				BdfDictionary d = entry.getValue();
-				if (id.equals(d.getLong(CONTACT_ID))) {
-					deleteMessage(txn, entry.getKey());
-				}
+				deleteMessage(txn, entry.getKey());
 			}
 		} catch (FormatException e) {
 			if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
@@ -312,6 +316,11 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
 	public Collection<ForumInvitationMessage> getForumInvitationMessages(
 			ContactId contactId) throws DbException {
 
+		// query for all invitations
+		BdfDictionary query = BdfDictionary.of(
+				new BdfEntry(TYPE, SHARE_MSG_TYPE_INVITATION)
+		);
+
 		Transaction txn = db.startTransaction(false);
 		try {
 			Contact contact = db.getContact(txn, contactId);
@@ -320,13 +329,10 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
 			Collection<ForumInvitationMessage> list =
 					new ArrayList<ForumInvitationMessage>();
 			Map<MessageId, BdfDictionary> map = clientHelper
-					.getMessageMetadataAsDictionary(txn, group.getId());
+					.getMessageMetadataAsDictionary(txn, group.getId(), query);
 			for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) {
 				BdfDictionary d = m.getValue();
 				try {
-					if (d.getLong(TYPE) != SHARE_MSG_TYPE_INVITATION)
-						continue;
-
 					Invitation msg = Invitation.from(group.getId(), d);
 					MessageStatus status =
 							db.getMessageStatus(txn, contactId, m.getKey());
@@ -542,17 +548,25 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
 		try {
 			return getSessionStateForSharer(txn, sessionId);
 		} catch (NoSuchMessageException e) {
-			// State not found directly, so iterate over all states
-			// to find state for invitee
+			// State not found directly, so query for state for invitee
+			BdfDictionary query = BdfDictionary.of(
+					new BdfEntry(SESSION_ID, sessionId)
+			);
+
 			Map<MessageId, BdfDictionary> map = clientHelper
-					.getMessageMetadataAsDictionary(txn, localGroup.getId());
+					.getMessageMetadataAsDictionary(txn, localGroup.getId(),
+							query);
+
+			if (map.size() > 1 && LOG.isLoggable(WARNING)) {
+				LOG.warning(
+						"More than one session state found for message with session ID " +
+								Arrays.hashCode(sessionId.getBytes()));
+			}
+
 			for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) {
-				BdfDictionary state = m.getValue();
-				if (Arrays.equals(state.getRaw(SESSION_ID),
-						sessionId.getBytes())) {
-					return fromBdfDictionary(state);
-				}
+				return fromBdfDictionary(m.getValue());
 			}
+
 			if (warn && LOG.isLoggable(WARNING)) {
 				LOG.warning(
 						"No session state found for message with session ID " +
@@ -578,25 +592,36 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
 	private InviteeSessionState getSessionStateForResponse(Transaction txn,
 			Forum f) throws DbException, FormatException {
 
+		// query for invitee states for that forum in state await response
+		BdfDictionary query = BdfDictionary.of(
+				new BdfEntry(IS_SHARER, false),
+				new BdfEntry(FORUM_ID, f.getId()),
+				new BdfEntry(STATE,
+						InviteeSessionState.State.AWAIT_LOCAL_RESPONSE
+								.getValue())
+		);
+
 		Map<MessageId, BdfDictionary> map = clientHelper
-				.getMessageMetadataAsDictionary(txn, localGroup.getId());
+				.getMessageMetadataAsDictionary(txn, localGroup.getId(), query);
+
+		// TODO we might have been invited to the same forum from several people
+		// in different sessions, so we need to handle this (#391)
+		if (map.size() > 1 && LOG.isLoggable(WARNING)) {
+			LOG.warning(
+					"More than one session state found for forum with ID " +
+							Arrays.hashCode(f.getId().getBytes()) +
+							" in state AWAIT_LOCAL_RESPONSE");
+		}
+
 		for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) {
-			BdfDictionary d = m.getValue();
-			try {
-				ForumSharingSessionState s = fromBdfDictionary(d);
-				if (!(s instanceof InviteeSessionState)) continue;
-				if (!f.getId().equals(s.getForumId())) continue;
+			return (InviteeSessionState) fromBdfDictionary(m.getValue());
+		}
 
-				InviteeSessionState state = (InviteeSessionState) s;
-				if (state.getState() ==
-						InviteeSessionState.State.AWAIT_LOCAL_RESPONSE) {
-					// Note that there should always be only one session
-					// in this state for the same forum
-					return state;
-				}
-			} catch (FormatException e) {
-				if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
-			}
+		if (LOG.isLoggable(WARNING)) {
+			LOG.warning(
+					"No session state found for forum with ID " +
+							Arrays.hashCode(f.getId().getBytes()) +
+							" in state AWAIT_LOCAL_RESPONSE");
 		}
 		throw new DbException();
 	}
@@ -604,22 +629,17 @@ class ForumSharingManagerImpl extends BdfIncomingMessageHook
 	private ForumSharingSessionState getSessionStateForLeaving(Transaction txn,
 			Forum f, ContactId c) throws DbException, FormatException {
 
+		BdfDictionary query = BdfDictionary.of(
+				new BdfEntry(CONTACT_ID, c.getInt()),
+				new BdfEntry(FORUM_ID, f.getId())
+		);
 		Map<MessageId, BdfDictionary> map = clientHelper
-				.getMessageMetadataAsDictionary(txn, localGroup.getId());
+				.getMessageMetadataAsDictionary(txn, localGroup.getId(), query);
 		for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) {
 			BdfDictionary d = m.getValue();
 			try {
 				ForumSharingSessionState s = fromBdfDictionary(d);
 
-				// check that this session is with the right contact
-				if (!c.equals(s.getContactId())) continue;
-
-				// check that this state actually concerns this forum
-				if (!s.getForumName().equals(f.getName()) ||
-						!Arrays.equals(s.getForumSalt(), f.getSalt())) {
-					continue;
-				}
-
 				// check that a forum get be left in current session
 				if (s instanceof SharerSessionState) {
 					SharerSessionState state = (SharerSessionState) s;