diff --git a/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java
deleted file mode 100644
index b8c14d4a612ef36672952d429fe607af1e2a9989..0000000000000000000000000000000000000000
--- a/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java
+++ /dev/null
@@ -1,780 +0,0 @@
-package org.briarproject;
-
-import net.jodah.concurrentunit.Waiter;
-
-import org.briarproject.api.clients.MessageQueueManager;
-import org.briarproject.api.clients.PrivateGroupFactory;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Metadata;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.ForumInvitationReceivedEvent;
-import org.briarproject.api.event.ForumInvitationResponseReceivedEvent;
-import org.briarproject.api.event.MessageValidatedEvent;
-import org.briarproject.api.forum.Forum;
-import org.briarproject.api.forum.ForumInvitationMessage;
-import org.briarproject.api.forum.ForumManager;
-import org.briarproject.api.forum.ForumSharingManager;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.SyncSession;
-import org.briarproject.api.sync.SyncSessionFactory;
-import org.briarproject.api.system.Clock;
-import org.briarproject.contact.ContactModule;
-import org.briarproject.crypto.CryptoModule;
-import org.briarproject.forum.ForumModule;
-import org.briarproject.lifecycle.LifecycleModule;
-import org.briarproject.properties.PropertiesModule;
-import org.briarproject.sync.SyncModule;
-import org.briarproject.transport.TransportModule;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-import java.util.logging.Logger;
-
-import javax.inject.Inject;
-
-import static org.briarproject.TestPluginsModule.MAX_LATENCY;
-import static org.briarproject.api.forum.ForumConstants.FORUM_SALT_LENGTH;
-import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_INVITATION;
-import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class ForumSharingIntegrationTest extends BriarTestCase {
-
-	LifecycleManager lifecycleManager0, lifecycleManager1;
-	SyncSessionFactory sync0, sync1;
-	ForumManager forumManager0, forumManager1;
-	ContactManager contactManager0, contactManager1;
-	ContactId contactId0, contactId1;
-	IdentityManager identityManager0, identityManager1;
-	LocalAuthor author0, author1;
-	Forum forum0;
-	SharerListener listener0;
-	InviteeListener listener1;
-
-	@Inject
-	Clock clock;
-	@Inject
-	AuthorFactory authorFactory;
-
-	// objects accessed from background threads need to be volatile
-	private volatile ForumSharingManager forumSharingManager0;
-	private volatile ForumSharingManager forumSharingManager1;
-	private volatile Waiter eventWaiter;
-	private volatile Waiter msgWaiter;
-
-	private final File testDir = TestUtils.getTestDirectory();
-	private final SecretKey master = TestUtils.getSecretKey();
-	private final int TIMEOUT = 15000;
-	private final String SHARER = "Sharer";
-	private final String INVITEE = "Invitee";
-
-	private static final Logger LOG =
-			Logger.getLogger(ForumSharingIntegrationTest.class.getName());
-
-	private ForumSharingIntegrationTestComponent t0, t1;
-
-	@Rule
-	public ExpectedException thrown=ExpectedException.none();
-
-	@Before
-	public void setUp() {
-		ForumSharingIntegrationTestComponent component =
-				DaggerForumSharingIntegrationTestComponent.builder().build();
-		component.inject(this);
-		injectEagerSingletons(component);
-
-		assertTrue(testDir.mkdirs());
-		File t0Dir = new File(testDir, SHARER);
-		t0 = DaggerForumSharingIntegrationTestComponent.builder()
-				.testDatabaseModule(new TestDatabaseModule(t0Dir)).build();
-		injectEagerSingletons(t0);
-		File t1Dir = new File(testDir, INVITEE);
-		t1 = DaggerForumSharingIntegrationTestComponent.builder()
-				.testDatabaseModule(new TestDatabaseModule(t1Dir)).build();
-		injectEagerSingletons(t1);
-
-		identityManager0 = t0.getIdentityManager();
-		identityManager1 = t1.getIdentityManager();
-		contactManager0 = t0.getContactManager();
-		contactManager1 = t1.getContactManager();
-		forumManager0 = t0.getForumManager();
-		forumManager1 = t1.getForumManager();
-		forumSharingManager0 = t0.getForumSharingManager();
-		forumSharingManager1 = t1.getForumSharingManager();
-		sync0 = t0.getSyncSessionFactory();
-		sync1 = t1.getSyncSessionFactory();
-
-		// initialize waiters fresh for each test
-		eventWaiter = new Waiter();
-		msgWaiter = new Waiter();
-	}
-
-	@Test
-	public void testSuccessfulSharing() throws Exception {
-		startLifecycles();
-		try {
-			// initialize and let invitee accept all requests
-			defaultInit(true);
-
-			// send invitation
-			forumSharingManager0
-					.sendForumInvitation(forum0.getId(), contactId1, "Hi!");
-
-			// sync first request message
-			syncToInvitee();
-			eventWaiter.await(TIMEOUT, 1);
-			assertTrue(listener1.requestReceived);
-
-			// sync response back
-			syncToSharer();
-			eventWaiter.await(TIMEOUT, 1);
-			assertTrue(listener0.responseReceived);
-
-			// forum was added successfully
-			assertEquals(0, forumSharingManager0.getAvailableForums().size());
-			assertEquals(1, forumManager1.getForums().size());
-
-			// invitee has one invitation message from sharer
-			List<ForumInvitationMessage> list =
-					new ArrayList<>(forumSharingManager1
-							.getForumInvitationMessages(contactId0));
-			assertEquals(1, list.size());
-			// check other things are alright with the forum message
-			ForumInvitationMessage invitation = list.get(0);
-			assertFalse(invitation.isAvailable());
-			assertEquals(forum0.getName(), invitation.getForumName());
-			assertEquals(contactId1, invitation.getContactId());
-			assertEquals("Hi!", invitation.getMessage());
-			// sharer has own invitation message
-			assertEquals(1,
-					forumSharingManager0.getForumInvitationMessages(contactId1)
-							.size());
-			// forum can not be shared again
-			Contact c1 = contactManager0.getContact(contactId1);
-			assertFalse(forumSharingManager0.canBeShared(forum0.getId(), c1));
-			Contact c0 = contactManager1.getContact(contactId0);
-			assertFalse(forumSharingManager1.canBeShared(forum0.getId(), c0));
-		} finally {
-			stopLifecycles();
-		}
-	}
-
-	@Test
-	public void testDeclinedSharing() throws Exception {
-		startLifecycles();
-		try {
-			// initialize and let invitee accept all requests
-			defaultInit(false);
-
-			// send invitation
-			forumSharingManager0
-					.sendForumInvitation(forum0.getId(), contactId1, null);
-
-			// sync first request message
-			syncToInvitee();
-			eventWaiter.await(TIMEOUT, 1);
-			assertTrue(listener1.requestReceived);
-
-			// sync response back
-			syncToSharer();
-			eventWaiter.await(TIMEOUT, 1);
-			assertTrue(listener0.responseReceived);
-
-			// forum was not added
-			assertEquals(0, forumSharingManager0.getAvailableForums().size());
-			assertEquals(0, forumManager1.getForums().size());
-			// forum is no longer available to invitee who declined
-			assertEquals(0, forumSharingManager1.getAvailableForums().size());
-
-			// invitee has one invitation message from sharer
-			List<ForumInvitationMessage> list =
-					new ArrayList<>(forumSharingManager1
-							.getForumInvitationMessages(contactId0));
-			assertEquals(1, list.size());
-			// check other things are alright with the forum message
-			ForumInvitationMessage invitation = list.get(0);
-			assertFalse(invitation.isAvailable());
-			assertEquals(forum0.getName(), invitation.getForumName());
-			assertEquals(contactId1, invitation.getContactId());
-			assertEquals(null, invitation.getMessage());
-			// sharer has own invitation message
-			assertEquals(1,
-					forumSharingManager0.getForumInvitationMessages(contactId1)
-							.size());
-			// forum can be shared again
-			Contact c1 = contactManager0.getContact(contactId1);
-			assertTrue(forumSharingManager0.canBeShared(forum0.getId(), c1));
-		} finally {
-			stopLifecycles();
-		}
-	}
-
-	@Test
-	public void testInviteeLeavesAfterFinished() throws Exception {
-		startLifecycles();
-		try {
-			// initialize and let invitee accept all requests
-			defaultInit(true);
-
-			// send invitation
-			forumSharingManager0
-					.sendForumInvitation(forum0.getId(), contactId1, "Hi!");
-
-			// sync first request message
-			syncToInvitee();
-			eventWaiter.await(TIMEOUT, 1);
-			assertTrue(listener1.requestReceived);
-
-			// sync response back
-			syncToSharer();
-			eventWaiter.await(TIMEOUT, 1);
-			assertTrue(listener0.responseReceived);
-
-			// forum was added successfully
-			assertEquals(0, forumSharingManager0.getAvailableForums().size());
-			assertEquals(1, forumManager1.getForums().size());
-			assertTrue(forumManager1.getForums().contains(forum0));
-
-			// sharer shares forum with invitee
-			assertTrue(forumSharingManager0.getSharedWith(forum0.getId())
-					.contains(contactId1));
-			// invitee gets forum shared by sharer
-			Contact contact0 = contactManager1.getContact(contactId1);
-			assertTrue(forumSharingManager1.getSharedBy(forum0.getId())
-					.contains(contact0));
-
-			// invitee un-subscribes from forum
-			forumManager1.removeForum(forum0);
-
-			// send leave message to sharer
-			syncToSharer();
-
-			// forum is gone
-			assertEquals(0, forumSharingManager0.getAvailableForums().size());
-			assertEquals(0, forumManager1.getForums().size());
-
-			// sharer no longer shares forum with invitee
-			assertFalse(forumSharingManager0.getSharedWith(forum0.getId())
-					.contains(contactId1));
-			// invitee no longer gets forum shared by sharer
-			assertFalse(forumSharingManager1.getSharedBy(forum0.getId())
-					.contains(contact0));
-			// forum can be shared again
-			Contact c1 = contactManager0.getContact(contactId1);
-			assertTrue(forumSharingManager0.canBeShared(forum0.getId(), c1));
-			Contact c0 = contactManager1.getContact(contactId0);
-			assertTrue(forumSharingManager1.canBeShared(forum0.getId(), c0));
-		} finally {
-			stopLifecycles();
-		}
-	}
-
-	@Test
-	public void testSharerLeavesAfterFinished() throws Exception {
-		startLifecycles();
-		try {
-			// initialize and let invitee accept all requests
-			defaultInit(true);
-
-			// send invitation
-			forumSharingManager0
-					.sendForumInvitation(forum0.getId(), contactId1, null);
-
-			// sync first request message
-			syncToInvitee();
-			eventWaiter.await(TIMEOUT, 1);
-			assertTrue(listener1.requestReceived);
-
-			// sync response back
-			syncToSharer();
-			eventWaiter.await(TIMEOUT, 1);
-			assertTrue(listener0.responseReceived);
-
-			// forum was added successfully
-			assertEquals(0, forumSharingManager0.getAvailableForums().size());
-			assertEquals(1, forumManager1.getForums().size());
-			assertTrue(forumManager1.getForums().contains(forum0));
-
-			// sharer shares forum with invitee
-			assertTrue(forumSharingManager0.getSharedWith(forum0.getId())
-					.contains(contactId1));
-			// invitee gets forum shared by sharer
-			Contact contact0 = contactManager1.getContact(contactId1);
-			assertTrue(forumSharingManager1.getSharedBy(forum0.getId())
-					.contains(contact0));
-
-			// sharer un-subscribes from forum
-			forumManager0.removeForum(forum0);
-
-			// send leave message to invitee
-			syncToInvitee();
-
-			// forum is gone for sharer, but not invitee
-			assertEquals(0, forumManager0.getForums().size());
-			assertEquals(1, forumManager1.getForums().size());
-
-			// invitee no longer shares forum with sharer
-			assertFalse(forumSharingManager1.getSharedWith(forum0.getId())
-					.contains(contactId0));
-			// sharer no longer gets forum shared by invitee
-			assertFalse(forumSharingManager1.getSharedBy(forum0.getId())
-					.contains(contact0));
-			// forum can be shared again
-			Contact c0 = contactManager1.getContact(contactId0);
-			assertTrue(forumSharingManager1.canBeShared(forum0.getId(), c0));
-		} finally {
-			stopLifecycles();
-		}
-	}
-
-	@Test
-	public void testSharerLeavesBeforeResponse() throws Exception {
-		startLifecycles();
-		try {
-			// initialize and let invitee accept all requests
-			defaultInit(true);
-
-			// send invitation
-			forumSharingManager0
-					.sendForumInvitation(forum0.getId(), contactId1, null);
-
-			// sharer un-subscribes from forum
-			forumManager0.removeForum(forum0);
-
-			// from her on expect the response to fail with a DbException
-			thrown.expect(DbException.class);
-
-			// sync first request message and leave message
-			syncToInvitee();
-			eventWaiter.await(TIMEOUT, 1);
-			assertTrue(listener1.requestReceived);
-
-			// invitee has no forums available
-			assertEquals(0, forumSharingManager1.getAvailableForums().size());
-		} finally {
-			stopLifecycles();
-		}
-	}
-
-	@Test
-	public void testSessionIdReuse() throws Exception {
-		startLifecycles();
-		try {
-			// initialize and let invitee accept all requests
-			defaultInit(true);
-
-			// send invitation
-			forumSharingManager0
-					.sendForumInvitation(forum0.getId(), contactId1, "Hi!");
-
-			// sync first request message
-			syncToInvitee();
-			eventWaiter.await(TIMEOUT, 1);
-			assertTrue(listener1.requestReceived);
-
-			// sync response back
-			syncToSharer();
-			eventWaiter.await(TIMEOUT, 1);
-			assertTrue(listener0.responseReceived);
-
-			// forum was added successfully
-			assertEquals(1, forumManager1.getForums().size());
-
-			// reset event received state
-			listener1.requestReceived = false;
-
-			// get SessionId from invitation
-			List<ForumInvitationMessage> list = new ArrayList<>(
-					forumSharingManager1
-							.getForumInvitationMessages(contactId0));
-			assertEquals(1, list.size());
-			ForumInvitationMessage msg = list.get(0);
-			SessionId sessionId = msg.getSessionId();
-
-			// get all sorts of stuff needed to send a message
-			DatabaseComponent db = t0.getDatabaseComponent();
-			MessageQueueManager queue = t0.getMessageQueueManager();
-			Contact c1 = contactManager0.getContact(contactId1);
-			PrivateGroupFactory groupFactory = t0.getPrivateGroupFactory();
-			Group group = groupFactory
-					.createPrivateGroup(forumSharingManager0.getClientId(), c1);
-			long time = clock.currentTimeMillis();
-			BdfList bodyList = BdfList.of(SHARE_MSG_TYPE_INVITATION,
-					sessionId.getBytes(),
-					TestUtils.getRandomString(42),
-					TestUtils.getRandomBytes(FORUM_SALT_LENGTH)
-			);
-			byte[] body = t0.getClientHelper().toByteArray(bodyList);
-
-			// add the message to the queue
-			Transaction txn = db.startTransaction(false);
-			try {
-				queue.sendMessage(txn, group, time, body, new Metadata());
-				txn.setComplete();
-			} finally {
-				db.endTransaction(txn);
-			}
-
-			// actually send the message
-			syncToInvitee();
-			// make sure there was no new request received
-			assertFalse(listener1.requestReceived);
-		} finally {
-			stopLifecycles();
-		}
-	}
-
-	@Test
-	public void testSharingSameForumWithEachOther() throws Exception {
-		startLifecycles();
-		try {
-			// initialize and let invitee accept all requests
-			defaultInit(true);
-
-			// send invitation
-			forumSharingManager0
-					.sendForumInvitation(forum0.getId(), contactId1, "Hi!");
-
-			// sync first request message
-			syncToInvitee();
-			eventWaiter.await(TIMEOUT, 1);
-			assertTrue(listener1.requestReceived);
-
-			// sync response back
-			syncToSharer();
-			eventWaiter.await(TIMEOUT, 1);
-			assertTrue(listener0.responseReceived);
-
-			// forum was added successfully
-			assertEquals(1, forumManager1.getForums().size());
-
-			// invitee now shares same forum back
-			forumSharingManager1.sendForumInvitation(forum0.getId(), contactId0,
-					"I am re-sharing this forum with you.");
-
-			// sync re-share invitation
-			syncToSharer();
-
-			// make sure that no new request was received
-			assertFalse(listener0.requestReceived);
-			assertEquals(1,
-					forumSharingManager0.getForumInvitationMessages(contactId1)
-							.size());
-		} finally {
-			stopLifecycles();
-		}
-	}
-
-	@Test
-	public void testContactRemoved() throws Exception {
-		startLifecycles();
-		try {
-			// initialize and let invitee accept all requests
-			defaultInit(true);
-
-			// send invitation
-			forumSharingManager0
-					.sendForumInvitation(forum0.getId(), contactId1, "Hi!");
-
-			// sync first request message
-			syncToInvitee();
-			eventWaiter.await(TIMEOUT, 1);
-			assertTrue(listener1.requestReceived);
-
-			// sync response back
-			syncToSharer();
-			eventWaiter.await(TIMEOUT, 1);
-			assertTrue(listener0.responseReceived);
-
-			// forum was added successfully
-			assertEquals(1, forumManager1.getForums().size());
-			assertEquals(1,
-					forumSharingManager0.getSharedWith(forum0.getId()).size());
-
-			// remember SessionId from invitation
-			List<ForumInvitationMessage> list = new ArrayList<>(
-					forumSharingManager1
-							.getForumInvitationMessages(contactId0));
-			assertEquals(1, list.size());
-			ForumInvitationMessage msg = list.get(0);
-			SessionId sessionId = msg.getSessionId();
-
-			// contacts now remove each other
-			contactManager0.removeContact(contactId1);
-			contactManager1.removeContact(contactId0);
-
-			// make sure sharer does share the forum with nobody now
-			assertEquals(0,
-					forumSharingManager0.getSharedWith(forum0.getId()).size());
-
-			// contacts add each other again
-			addDefaultContacts();
-
-			// get all sorts of stuff needed to send a message
-			DatabaseComponent db = t0.getDatabaseComponent();
-			MessageQueueManager queue = t0.getMessageQueueManager();
-			Contact c1 = contactManager0.getContact(contactId1);
-			PrivateGroupFactory groupFactory = t0.getPrivateGroupFactory();
-			Group group = groupFactory
-					.createPrivateGroup(forumSharingManager0.getClientId(), c1);
-			long time = clock.currentTimeMillis();
-
-			// construct a new message re-using the old SessionId
-			BdfList bodyList = BdfList.of(SHARE_MSG_TYPE_INVITATION,
-					sessionId.getBytes(),
-					TestUtils.getRandomString(42),
-					TestUtils.getRandomBytes(FORUM_SALT_LENGTH)
-			);
-			byte[] body = t0.getClientHelper().toByteArray(bodyList);
-
-			// add the message to the queue
-			Transaction txn = db.startTransaction(false);
-			try {
-				queue.sendMessage(txn, group, time, body, new Metadata());
-				txn.setComplete();
-			} finally {
-				db.endTransaction(txn);
-			}
-
-			// actually send the message
-			syncToInvitee();
-			eventWaiter.await(TIMEOUT, 1);
-			// make sure the new request was received with the same sessionId
-			// as proof that the state got deleted along with contacts
-			assertTrue(listener1.requestReceived);
-		} finally {
-			stopLifecycles();
-		}
-	}
-
-
-	@After
-	public void tearDown() throws InterruptedException {
-		TestUtils.deleteTestDirectory(testDir);
-	}
-
-	private class SharerListener implements EventListener {
-
-		public volatile boolean requestReceived = false;
-		public volatile boolean responseReceived = false;
-
-		public void eventOccurred(Event e) {
-			if (e instanceof MessageValidatedEvent) {
-				MessageValidatedEvent event = (MessageValidatedEvent) e;
-				if (event.getClientId()
-						.equals(forumSharingManager0.getClientId()) &&
-						!event.isLocal()) {
-					LOG.info("TEST: Sharer received message in group " +
-							((MessageValidatedEvent) e).getMessage()
-									.getGroupId().hashCode());
-					msgWaiter.resume();
-				}
-			} else if (e instanceof ForumInvitationResponseReceivedEvent) {
-				ForumInvitationResponseReceivedEvent event =
-						(ForumInvitationResponseReceivedEvent) e;
-				eventWaiter.assertEquals(contactId1, event.getContactId());
-				responseReceived = true;
-				eventWaiter.resume();
-			}
-			// this is only needed for tests where a forum is re-shared
-			else if (e instanceof ForumInvitationReceivedEvent) {
-				ForumInvitationReceivedEvent event =
-						(ForumInvitationReceivedEvent) e;
-				eventWaiter.assertEquals(contactId1, event.getContactId());
-				requestReceived = true;
-				Forum f = event.getForum();
-				try {
-					forumSharingManager0.respondToInvitation(f, true);
-				} catch (DbException ex) {
-					eventWaiter.rethrow(ex);
-				} finally {
-					eventWaiter.resume();
-				}
-			}
-		}
-	}
-
-	private class InviteeListener implements EventListener {
-
-		public volatile boolean requestReceived = false;
-		public volatile boolean responseReceived = false;
-
-		private final boolean accept;
-
-		InviteeListener(boolean accept) {
-			this.accept = accept;
-		}
-
-		public void eventOccurred(Event e) {
-			if (e instanceof MessageValidatedEvent) {
-				MessageValidatedEvent event = (MessageValidatedEvent) e;
-				if (event.getClientId()
-						.equals(forumSharingManager1.getClientId()) &&
-						!event.isLocal()) {
-					LOG.info("TEST: Invitee received message in group " +
-							((MessageValidatedEvent) e).getMessage()
-									.getGroupId().hashCode());
-					msgWaiter.resume();
-				}
-			} else if (e instanceof ForumInvitationReceivedEvent) {
-				ForumInvitationReceivedEvent event =
-						(ForumInvitationReceivedEvent) e;
-				eventWaiter.assertEquals(contactId0, event.getContactId());
-				requestReceived = true;
-				Forum f = event.getForum();
-				// work-around because the forum does not contain the group
-				f = forumManager1.createForum(f.getName(), f.getSalt());
-				try {
-					forumSharingManager1.respondToInvitation(f, accept);
-				} catch (DbException ex) {
-					eventWaiter.rethrow(ex);
-				} finally {
-					eventWaiter.resume();
-				}
-			}
-			// this is only needed for tests where a forum is re-shared
-			else if (e instanceof ForumInvitationResponseReceivedEvent) {
-				ForumInvitationResponseReceivedEvent event =
-						(ForumInvitationResponseReceivedEvent) e;
-				eventWaiter.assertEquals(contactId0, event.getContactId());
-				responseReceived = true;
-				eventWaiter.resume();
-			}
-		}
-	}
-
-	private void startLifecycles() throws InterruptedException {
-		// Start the lifecycle manager and wait for it to finish
-		lifecycleManager0 = t0.getLifecycleManager();
-		lifecycleManager1 = t1.getLifecycleManager();
-		lifecycleManager0.startServices();
-		lifecycleManager1.startServices();
-		lifecycleManager0.waitForStartup();
-		lifecycleManager1.waitForStartup();
-	}
-
-	private void stopLifecycles() throws InterruptedException {
-		// Clean up
-		lifecycleManager0.stopServices();
-		lifecycleManager1.stopServices();
-		lifecycleManager0.waitForShutdown();
-		lifecycleManager1.waitForShutdown();
-	}
-
-	private void defaultInit(boolean accept) throws DbException {
-		addDefaultIdentities();
-		addDefaultContacts();
-		addForumForSharer();
-		listenToEvents(accept);
-	}
-
-	private void addDefaultIdentities() throws DbException {
-		author0 = authorFactory.createLocalAuthor(SHARER,
-				TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
-				TestUtils.getRandomBytes(123));
-		identityManager0.addLocalAuthor(author0);
-		author1 = authorFactory.createLocalAuthor(INVITEE,
-				TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
-				TestUtils.getRandomBytes(123));
-		identityManager1.addLocalAuthor(author1);
-	}
-
-	private void addDefaultContacts() throws DbException {
-		// sharer adds invitee as contact
-		contactId1 = contactManager0.addContact(author1,
-				author0.getId(), master, clock.currentTimeMillis(), true,
-				true
-		);
-		// invitee adds sharer back
-		contactId0 = contactManager1.addContact(author0,
-				author1.getId(), master, clock.currentTimeMillis(), true,
-				true
-		);
-	}
-
-	private void addForumForSharer() throws DbException {
-		// sharer creates forum
-		forum0 = forumManager0.createForum("Test Forum");
-		forumManager0.addForum(forum0);
-	}
-
-	private void listenToEvents(boolean accept) {
-		listener0 = new SharerListener();
-		t0.getEventBus().addListener(listener0);
-		listener1 = new InviteeListener(accept);
-		t1.getEventBus().addListener(listener1);
-	}
-
-	private void syncToInvitee() throws IOException, TimeoutException {
-		deliverMessage(sync0, contactId0, sync1, contactId1,
-				"Sharer to Invitee");
-	}
-
-	private void syncToSharer() throws IOException, TimeoutException {
-		deliverMessage(sync1, contactId1, sync0, contactId0,
-				"Invitee to Sharer");
-	}
-
-	private void deliverMessage(SyncSessionFactory fromSync, ContactId fromId,
-			SyncSessionFactory toSync, ContactId toId, String debug)
-			throws IOException, TimeoutException {
-
-		if (debug != null) LOG.info("TEST: Sending message from " + debug);
-
-		ByteArrayOutputStream out = new ByteArrayOutputStream();
-		// Create an outgoing sync session
-		SyncSession sessionFrom =
-				fromSync.createSimplexOutgoingSession(toId, MAX_LATENCY, out);
-		// Write whatever needs to be written
-		sessionFrom.run();
-		out.close();
-
-		ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
-		// Create an incoming sync session
-		SyncSession sessionTo = toSync.createIncomingSession(fromId, in);
-		// Read whatever needs to be read
-		sessionTo.run();
-		in.close();
-
-		// wait for message to actually arrive
-		msgWaiter.await(TIMEOUT, 1);
-	}
-
-	private void injectEagerSingletons(
-			ForumSharingIntegrationTestComponent component) {
-
-		component.inject(new LifecycleModule.EagerSingletons());
-		component.inject(new ForumModule.EagerSingletons());
-		component.inject(new CryptoModule.EagerSingletons());
-		component.inject(new ContactModule.EagerSingletons());
-		component.inject(new TransportModule.EagerSingletons());
-		component.inject(new SyncModule.EagerSingletons());
-		component.inject(new PropertiesModule.EagerSingletons());
-	}
-
-}
diff --git a/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTestComponent.java b/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTestComponent.java
deleted file mode 100644
index 55f3d8de82b117a6b2d415f03458c70210a8aa75..0000000000000000000000000000000000000000
--- a/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTestComponent.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package org.briarproject;
-
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.MessageQueueManager;
-import org.briarproject.api.clients.PrivateGroupFactory;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.forum.ForumManager;
-import org.briarproject.api.forum.ForumSharingManager;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.sync.SyncSessionFactory;
-import org.briarproject.clients.ClientsModule;
-import org.briarproject.contact.ContactModule;
-import org.briarproject.crypto.CryptoModule;
-import org.briarproject.data.DataModule;
-import org.briarproject.db.DatabaseModule;
-import org.briarproject.event.EventModule;
-import org.briarproject.forum.ForumModule;
-import org.briarproject.identity.IdentityModule;
-import org.briarproject.lifecycle.LifecycleModule;
-import org.briarproject.properties.PropertiesModule;
-import org.briarproject.sync.SyncModule;
-import org.briarproject.system.SystemModule;
-import org.briarproject.transport.TransportModule;
-
-import javax.inject.Singleton;
-
-import dagger.Component;
-
-@Singleton
-@Component(modules = {
-		TestDatabaseModule.class,
-		TestPluginsModule.class,
-		TestSeedProviderModule.class,
-		ClientsModule.class,
-		ContactModule.class,
-		CryptoModule.class,
-		DataModule.class,
-		DatabaseModule.class,
-		EventModule.class,
-		ForumModule.class,
-		IdentityModule.class,
-		LifecycleModule.class,
-		PropertiesModule.class,
-		SyncModule.class,
-		SystemModule.class,
-		TransportModule.class
-})
-public interface ForumSharingIntegrationTestComponent {
-
-	void inject(ForumSharingIntegrationTest testCase);
-
-	void inject(ContactModule.EagerSingletons init);
-
-	void inject(CryptoModule.EagerSingletons init);
-
-	void inject(ForumModule.EagerSingletons init);
-
-	void inject(LifecycleModule.EagerSingletons init);
-
-	void inject(PropertiesModule.EagerSingletons init);
-
-	void inject(SyncModule.EagerSingletons init);
-
-	void inject(TransportModule.EagerSingletons init);
-
-	LifecycleManager getLifecycleManager();
-
-	EventBus getEventBus();
-
-	IdentityManager getIdentityManager();
-
-	ContactManager getContactManager();
-
-	ForumSharingManager getForumSharingManager();
-
-	ForumManager getForumManager();
-
-	SyncSessionFactory getSyncSessionFactory();
-
-	/* the following methods are only needed to manually construct messages */
-
-	DatabaseComponent getDatabaseComponent();
-
-	PrivateGroupFactory getPrivateGroupFactory();
-
-	ClientHelper getClientHelper();
-
-	MessageQueueManager getMessageQueueManager();
-
-}
diff --git a/briar-android-tests/src/test/java/org/briarproject/MessageSizeIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/MessageSizeIntegrationTest.java
index 5e5b877cc86364d8fefdffcefac2c0fd6647426d..80cd166b45cd48d439c9b8a6c944cd2b61f65904 100644
--- a/briar-android-tests/src/test/java/org/briarproject/MessageSizeIntegrationTest.java
+++ b/briar-android-tests/src/test/java/org/briarproject/MessageSizeIntegrationTest.java
@@ -2,11 +2,6 @@ package org.briarproject;
 
 import org.briarproject.api.UniqueId;
 import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.PrivateKey;
-import org.briarproject.api.forum.ForumConstants;
-import org.briarproject.api.forum.ForumPost;
-import org.briarproject.api.forum.ForumPostFactory;
-import org.briarproject.api.identity.Author;
 import org.briarproject.api.identity.AuthorFactory;
 import org.briarproject.api.messaging.MessagingConstants;
 import org.briarproject.api.messaging.PrivateMessage;
@@ -18,9 +13,6 @@ import org.junit.Test;
 
 import javax.inject.Inject;
 
-import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
-import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
-import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
 import static org.briarproject.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
 import static org.briarproject.api.sync.SyncConstants.MAX_PACKET_PAYLOAD_LENGTH;
 import static org.junit.Assert.assertTrue;
@@ -33,8 +25,6 @@ public class MessageSizeIntegrationTest extends BriarTestCase {
 	AuthorFactory authorFactory;
 	@Inject
 	PrivateMessageFactory privateMessageFactory;
-	@Inject
-	ForumPostFactory forumPostFactory;
 
 	public MessageSizeIntegrationTest() throws Exception {
 		MessageSizeIntegrationTestComponent component =
@@ -61,30 +51,4 @@ public class MessageSizeIntegrationTest extends BriarTestCase {
 				+ MAX_PRIVATE_MESSAGE_BODY_LENGTH);
 		assertTrue(length <= MAX_PACKET_PAYLOAD_LENGTH);
 	}
-
-	@Test
-	public void testForumPostFitsIntoPacket() throws Exception {
-		// Create a maximum-length author
-		String authorName = TestUtils.getRandomString(
-				MAX_AUTHOR_NAME_LENGTH);
-		byte[] authorPublic = new byte[MAX_PUBLIC_KEY_LENGTH];
-		Author author = authorFactory.createAuthor(authorName, authorPublic);
-		// Create a maximum-length forum post
-		GroupId groupId = new GroupId(TestUtils.getRandomId());
-		long timestamp = Long.MAX_VALUE;
-		MessageId parent = new MessageId(TestUtils.getRandomId());
-		String contentType = TestUtils.getRandomString(
-				ForumConstants.MAX_CONTENT_TYPE_LENGTH);
-		byte[] body = new byte[MAX_FORUM_POST_BODY_LENGTH];
-		PrivateKey privateKey = crypto.generateSignatureKeyPair().getPrivate();
-		ForumPost post = forumPostFactory.createPseudonymousPost(groupId,
-				timestamp, parent, author, contentType, body, privateKey);
-		// Check the size of the serialised message
-		int length = post.getMessage().getRaw().length;
-		assertTrue(length > UniqueId.LENGTH + 8 + UniqueId.LENGTH
-				+ MAX_AUTHOR_NAME_LENGTH + MAX_PUBLIC_KEY_LENGTH
-				+ ForumConstants.MAX_CONTENT_TYPE_LENGTH
-				+ MAX_FORUM_POST_BODY_LENGTH);
-		assertTrue(length <= MAX_PACKET_PAYLOAD_LENGTH);
-	}
 }
diff --git a/briar-android-tests/src/test/java/org/briarproject/MessageSizeIntegrationTestComponent.java b/briar-android-tests/src/test/java/org/briarproject/MessageSizeIntegrationTestComponent.java
index fe530464065456a4d633f83621d6a2bacf40eb87..d82fbc6795369406b0f12c0811aaa8eb42bd2aea 100644
--- a/briar-android-tests/src/test/java/org/briarproject/MessageSizeIntegrationTestComponent.java
+++ b/briar-android-tests/src/test/java/org/briarproject/MessageSizeIntegrationTestComponent.java
@@ -5,7 +5,6 @@ import org.briarproject.crypto.CryptoModule;
 import org.briarproject.data.DataModule;
 import org.briarproject.db.DatabaseModule;
 import org.briarproject.event.EventModule;
-import org.briarproject.forum.ForumModule;
 import org.briarproject.identity.IdentityModule;
 import org.briarproject.messaging.MessagingModule;
 import org.briarproject.sync.SyncModule;
@@ -25,7 +24,6 @@ import dagger.Component;
 		DataModule.class,
 		DatabaseModule.class,
 		EventModule.class,
-		ForumModule.class,
 		IdentityModule.class,
 		MessagingModule.class,
 		SyncModule.class,
diff --git a/briar-android/AndroidManifest.xml b/briar-android/AndroidManifest.xml
index bce061cefdfd28eb77a1bc1ceb67ce0de0df07f2..c773cbb3397f4ac960659f3865c9bd954d1be000 100644
--- a/briar-android/AndroidManifest.xml
+++ b/briar-android/AndroidManifest.xml
@@ -98,68 +98,6 @@
 				/>
 		</activity>
 
-		<activity
-			android:name=".android.forum.AvailableForumsActivity"
-			android:label="@string/available_forums_title"
-			android:parentActivityName=".android.NavDrawerActivity">
-			<meta-data
-				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.NavDrawerActivity"
-				/>
-		</activity>
-
-		<activity
-			android:name=".android.forum.CreateForumActivity"
-			android:label="@string/create_forum_title"
-			android:parentActivityName=".android.NavDrawerActivity"
-			android:windowSoftInputMode="stateVisible">
-			<meta-data
-				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.NavDrawerActivity"
-				/>
-		</activity>
-
-		<activity
-			android:name=".android.forum.ForumActivity"
-			android:label="@string/app_name"
-			android:parentActivityName=".android.NavDrawerActivity">
-			<meta-data
-				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.NavDrawerActivity"
-				/>
-		</activity>
-
-		<activity
-			android:name=".android.forum.ReadForumPostActivity"
-			android:label="@string/app_name"
-			android:parentActivityName=".android.NavDrawerActivity">
-			<meta-data
-				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.NavDrawerActivity"
-				/>
-		</activity>
-
-		<activity
-			android:name=".android.forum.ShareForumActivity"
-			android:label="@string/forums_share_toolbar_header"
-			android:parentActivityName=".android.forum.ForumActivity">
-			<meta-data
-				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.forum.ForumActivity"
-				/>
-		</activity>
-
-		<activity
-			android:name=".android.forum.WriteForumPostActivity"
-			android:label="@string/app_name"
-			android:parentActivityName=".android.NavDrawerActivity"
-			android:windowSoftInputMode="stateVisible">
-			<meta-data
-				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.NavDrawerActivity"
-				/>
-		</activity>
-
 		<activity
 			android:name=".android.identity.CreateIdentityActivity"
 			android:label="@string/new_identity_title"
diff --git a/briar-android/res/drawable/forum_item_create_white.xml b/briar-android/res/drawable/forum_item_create_white.xml
deleted file mode 100644
index 2a963d9abab1e68b4f0bfe009ead011584165c07..0000000000000000000000000000000000000000
--- a/briar-android/res/drawable/forum_item_create_white.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportHeight="24.0"
-        android:viewportWidth="24.0">
-	<path
-		android:fillColor="#FFFFFFFF"
-		android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
-</vector>
diff --git a/briar-android/res/layout/activity_available_forums.xml b/briar-android/res/layout/activity_available_forums.xml
deleted file mode 100644
index 7177fe175f97b59be6996a4e1ad6df6983f9d197..0000000000000000000000000000000000000000
--- a/briar-android/res/layout/activity_available_forums.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<org.briarproject.android.util.BriarRecyclerView
-	android:id="@+id/availableForumsView"
-	xmlns:android="http://schemas.android.com/apk/res/android"
-	android:layout_width="match_parent"
-	android:layout_height="match_parent"/>
diff --git a/briar-android/res/layout/activity_create_forum.xml b/briar-android/res/layout/activity_create_forum.xml
deleted file mode 100644
index b48bce90fac407609c4b4ad898636fe057e43563..0000000000000000000000000000000000000000
--- a/briar-android/res/layout/activity_create_forum.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout
-	xmlns:android="http://schemas.android.com/apk/res/android"
-	android:orientation="vertical"
-	android:layout_width="match_parent"
-	android:layout_height="match_parent"
-	android:gravity="center_horizontal"
-	android:padding="20dp" >
-
-	<TextView
-		android:layout_width="wrap_content"
-		android:layout_height="wrap_content"
-		android:gravity="center"
-		android:textSize="@dimen/text_size_medium"
-		android:text="@string/choose_forum_name" />
-
-	<EditText
-		android:layout_width="match_parent"
-		android:layout_height="wrap_content"
-		android:id="@+id/createForumNameEntry"
-		android:maxLines="1"
-		android:inputType="text|textCapSentences" />
-
-	<TextView
-		android:layout_width="wrap_content"
-		android:layout_height="wrap_content"
-		android:id="@+id/createForumFeedback"
-		android:gravity="center"
-		android:paddingLeft="50dp"
-		android:paddingRight="50dp" />
-
-	<Button
-		style="@style/BriarButton"
-		android:id="@+id/createForumButton"
-		android:layout_width="wrap_content"
-		android:layout_height="wrap_content"
-		android:layout_centerHorizontal="true"
-		android:text="@string/create_forum_button" />
-
-	<ProgressBar
-		android:id="@+id/createForumProgressBar"
-		android:layout_height="wrap_content"
-		android:layout_width="wrap_content"
-		android:indeterminate="true"
-		android:layout_centerHorizontal="true"
-		android:visibility="gone" />
-
-
-</LinearLayout>
diff --git a/briar-android/res/layout/activity_share_forum.xml b/briar-android/res/layout/activity_share_forum.xml
deleted file mode 100644
index b91e96f00b0299104a5145334361b4b9d310df55..0000000000000000000000000000000000000000
--- a/briar-android/res/layout/activity_share_forum.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<FrameLayout
-	android:id="@+id/shareForumContainer"
-	xmlns:android="http://schemas.android.com/apk/res/android"
-	android:layout_width="match_parent"
-	android:layout_height="match_parent"/>
\ No newline at end of file
diff --git a/briar-android/res/layout/fragment_forum_list.xml b/briar-android/res/layout/fragment_forum_list.xml
deleted file mode 100644
index 31d90c085f9ea01aa62fb3094cdbf01689bda2df..0000000000000000000000000000000000000000
--- a/briar-android/res/layout/fragment_forum_list.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<android.support.design.widget.CoordinatorLayout
-	android:id="@+id/coordinatorLayout"
-	xmlns:android="http://schemas.android.com/apk/res/android"
-	xmlns:app="http://schemas.android.com/apk/res-auto"
-	android:layout_width="match_parent"
-	android:layout_height="match_parent">
-
-	<org.briarproject.android.util.BriarRecyclerView
-		android:id="@+id/forumList"
-		xmlns:android="http://schemas.android.com/apk/res/android"
-		android:layout_width="match_parent"
-		android:layout_height="match_parent"
-		app:layout_behavior="org.briarproject.android.util.BriarRecyclerViewBehavior"/>
-
-</android.support.design.widget.CoordinatorLayout>
diff --git a/briar-android/res/layout/list_item_available_forum.xml b/briar-android/res/layout/list_item_available_forum.xml
deleted file mode 100644
index ca9158af1b6c9e13ce67eadf78023c75d4a7c703..0000000000000000000000000000000000000000
--- a/briar-android/res/layout/list_item_available_forum.xml
+++ /dev/null
@@ -1,71 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout
-	xmlns:android="http://schemas.android.com/apk/res/android"
-	xmlns:tools="http://schemas.android.com/tools"
-	android:layout_width="match_parent"
-	android:layout_height="wrap_content"
-	android:layout_marginLeft="@dimen/listitem_horizontal_margin"
-	android:layout_marginStart="@dimen/listitem_horizontal_margin"
-	android:paddingTop="@dimen/listitem_horizontal_margin"
-	android:background="?attr/selectableItemBackground">
-
-	<org.briarproject.android.util.TextAvatarView
-		android:id="@+id/avatarView"
-		android:layout_width="@dimen/avatar_forum_size"
-		android:layout_height="@dimen/avatar_forum_size"
-		android:layout_alignParentLeft="true"
-		android:layout_alignParentStart="true"
-		android:layout_marginRight="@dimen/listitem_horizontal_margin"
-		/>
-
-	<TextView
-		android:id="@+id/forumNameView"
-		android:layout_width="wrap_content"
-		android:layout_height="wrap_content"
-		android:layout_toEndOf="@+id/avatarView"
-		android:layout_toRightOf="@+id/avatarView"
-		android:maxLines="2"
-		android:textColor="@android:color/primary_text_light"
-		android:textSize="@dimen/text_size_medium"
-		tools:text="This is a name of a forum that is available"/>
-
-	<TextView
-		android:id="@+id/sharedByView"
-		android:layout_width="wrap_content"
-		android:layout_height="wrap_content"
-		android:layout_below="@+id/forumNameView"
-		android:layout_marginBottom="-8dp"
-		android:layout_toEndOf="@+id/avatarView"
-		android:layout_toRightOf="@+id/avatarView"
-		android:paddingTop="@dimen/margin_medium"
-		android:textColor="@android:color/secondary_text_light"
-		android:textSize="@dimen/text_size_small"
-		tools:text="Shared by Megalox"/>
-
-	<Button
-		android:id="@+id/acceptButton"
-		style="@style/BriarButtonFlat.Positive"
-		android:layout_width="wrap_content"
-		android:layout_height="wrap_content"
-		android:text="@string/dialog_button_accept"
-		android:layout_below="@+id/sharedByView"
-		android:layout_alignParentRight="true"
-		android:layout_alignParentEnd="true"/>
-
-	<Button
-		android:id="@+id/declineButton"
-		style="@style/BriarButtonFlat.Negative"
-		android:layout_width="wrap_content"
-		android:layout_height="wrap_content"
-		android:text="@string/dialog_button_decline"
-		android:layout_below="@+id/sharedByView"
-		android:layout_toLeftOf="@+id/acceptButton"
-		android:layout_toStartOf="@+id/acceptButton"/>
-
-	<View style="@style/Divider.ForumList"
-	      android:layout_below="@+id/acceptButton"
-	      android:layout_alignParentLeft="true"
-	      android:layout_alignParentStart="true"/>
-
-</RelativeLayout>
-
diff --git a/briar-android/res/layout/list_item_forum.xml b/briar-android/res/layout/list_item_forum.xml
deleted file mode 100644
index b513972e1150604698108435cbb43aef8633cd75..0000000000000000000000000000000000000000
--- a/briar-android/res/layout/list_item_forum.xml
+++ /dev/null
@@ -1,68 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout
-	xmlns:android="http://schemas.android.com/apk/res/android"
-	xmlns:app="http://schemas.android.com/apk/res-auto"
-	xmlns:tools="http://schemas.android.com/tools"
-	android:layout_width="match_parent"
-	android:layout_height="wrap_content"
-	android:layout_marginLeft="@dimen/listitem_horizontal_margin"
-	android:layout_marginStart="@dimen/listitem_horizontal_margin"
-	android:paddingTop="@dimen/listitem_horizontal_margin"
-	android:background="?attr/selectableItemBackground">
-
-	<org.briarproject.android.util.TextAvatarView
-		android:id="@+id/avatarView"
-		android:layout_height="@dimen/avatar_forum_size"
-		android:layout_width="@dimen/avatar_forum_size"
-		android:layout_marginRight="@dimen/listitem_horizontal_margin"
-		android:layout_alignParentLeft="true"
-		android:layout_alignParentStart="true"
-		/>
-
-	<TextView
-		android:id="@+id/forumNameView"
-		android:layout_width="wrap_content"
-		android:layout_height="wrap_content"
-		android:maxLines="2"
-		android:textColor="@color/briar_text_primary"
-		android:textSize="@dimen/text_size_medium"
-		tools:text="This is a name of a forum"
-		android:layout_alignParentTop="true"
-		android:layout_toRightOf="@+id/avatarView"
-		android:layout_toEndOf="@+id/avatarView"/>
-
-	<TextView
-		android:id="@+id/unreadView"
-		android:layout_width="wrap_content"
-		android:layout_height="wrap_content"
-		android:paddingTop="@dimen/margin_medium"
-		android:paddingBottom="@dimen/listitem_horizontal_margin"
-		android:textColor="@color/briar_text_secondary"
-		android:textSize="@dimen/text_size_small"
-		android:text="@string/no_unread_posts"
-		android:layout_below="@+id/forumNameView"
-		android:layout_toRightOf="@+id/avatarView"
-		android:layout_toEndOf="@+id/avatarView"/>
-
-	<TextView
-		android:id="@+id/dateView"
-		android:layout_width="wrap_content"
-		android:layout_height="wrap_content"
-		android:layout_alignParentRight="true"
-		android:layout_alignParentEnd="true"
-		android:layout_below="@+id/forumNameView"
-		android:paddingTop="@dimen/margin_medium"
-		android:paddingBottom="@dimen/listitem_horizontal_margin"
-		android:layout_marginRight="@dimen/listitem_horizontal_margin"
-		android:layout_marginEnd="@dimen/listitem_horizontal_margin"
-		android:textColor="@color/briar_text_secondary"
-		android:textSize="@dimen/text_size_small"
-		tools:text="Dec 24"/>
-
-	<View style="@style/Divider.ForumList"
-	      android:layout_below="@+id/unreadView"
-	      android:layout_alignParentLeft="true"
-	      android:layout_alignParentStart="true"/>
-
-</RelativeLayout>
-
diff --git a/briar-android/res/layout/list_item_forum_invitation_in.xml b/briar-android/res/layout/list_item_forum_invitation_in.xml
deleted file mode 100644
index c6881437b392b42a675d5d84c52b9b5f8e0c03e8..0000000000000000000000000000000000000000
--- a/briar-android/res/layout/list_item_forum_invitation_in.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout
-	xmlns:android="http://schemas.android.com/apk/res/android"
-	xmlns:tools="http://schemas.android.com/tools"
-	android:layout_width="match_parent"
-	android:layout_height="wrap_content"
-	android:orientation="vertical">
-
-	<include
-		android:id="@+id/messageLayout"
-		layout="@layout/list_item_msg_in"/>
-
-	<RelativeLayout
-		android:id="@+id/introductionLayout"
-		android:layout_width="wrap_content"
-		android:layout_height="wrap_content"
-		android:layout_gravity="left|start"
-		android:background="@drawable/notice_in"
-		android:layout_marginLeft="@dimen/message_bubble_margin_tail"
-		android:layout_marginRight="@dimen/message_bubble_margin_non_tail">
-
-		<TextView
-			android:id="@+id/introductionText"
-			android:layout_width="wrap_content"
-			android:layout_height="wrap_content"
-			android:minWidth="80dp"
-			android:textIsSelectable="true"
-			android:textSize="@dimen/text_size_medium"
-			android:textStyle="italic"
-			tools:text="@string/forum_invitation_received"/>
-
-		<TextView
-			android:id="@+id/introductionTime"
-			android:layout_width="wrap_content"
-			android:layout_height="wrap_content"
-			android:layout_marginTop="@dimen/message_bubble_timestamp_margin"
-			android:layout_alignEnd="@+id/introductionText"
-			android:layout_alignRight="@+id/introductionText"
-			android:layout_below="@+id/showForumsButton"
-			android:textColor="@color/private_message_date"
-			android:textSize="@dimen/text_size_tiny"
-			tools:text="Dec 24, 13:37"/>
-
-		<Button
-			android:id="@+id/showForumsButton"
-			style="@style/BriarButtonFlat.Positive"
-			android:layout_width="wrap_content"
-			android:layout_height="wrap_content"
-			android:layout_marginBottom="-15dp"
-			android:layout_alignEnd="@+id/introductionText"
-			android:layout_alignRight="@+id/introductionText"
-			android:layout_below="@+id/introductionText"
-			android:text="@string/forum_show_available"/>
-
-	</RelativeLayout>
-
-</LinearLayout>
\ No newline at end of file
diff --git a/briar-android/res/layout/list_item_forum_invitation_out.xml b/briar-android/res/layout/list_item_forum_invitation_out.xml
deleted file mode 100644
index 88070ea669ea57ab6402247f6c18cebae68eecb9..0000000000000000000000000000000000000000
--- a/briar-android/res/layout/list_item_forum_invitation_out.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout
-	xmlns:android="http://schemas.android.com/apk/res/android"
-	xmlns:tools="http://schemas.android.com/tools"
-	android:layout_width="match_parent"
-	android:layout_height="wrap_content"
-	android:orientation="vertical">
-
-	<include
-		android:id="@+id/messageLayout"
-		layout="@layout/list_item_msg_out"/>
-
-	<RelativeLayout
-		android:id="@+id/introductionLayout"
-		android:layout_width="wrap_content"
-		android:layout_height="wrap_content"
-		android:layout_gravity="right|end"
-		android:background="@drawable/notice_out"
-		android:layout_marginLeft="@dimen/message_bubble_margin_non_tail"
-		android:layout_marginRight="@dimen/message_bubble_margin_tail">
-
-		<TextView
-			android:id="@+id/introductionText"
-			android:layout_width="wrap_content"
-			android:layout_height="wrap_content"
-			android:textIsSelectable="true"
-			android:textSize="@dimen/text_size_medium"
-			android:textStyle="italic"
-			tools:text="@string/introduction_request_received"/>
-
-		<TextView
-			android:id="@+id/introductionTime"
-			android:layout_width="wrap_content"
-			android:layout_height="wrap_content"
-			android:layout_marginTop="@dimen/message_bubble_timestamp_margin"
-			android:layout_alignParentLeft="true"
-			android:layout_alignParentStart="true"
-			android:layout_below="@+id/introductionText"
-			android:textColor="@color/private_message_date"
-			android:textSize="@dimen/text_size_tiny"
-			tools:text="Dec 24, 13:37"/>
-
-		<ImageView
-			android:id="@+id/introductionStatus"
-			android:layout_width="wrap_content"
-			android:layout_height="wrap_content"
-			android:layout_toEndOf="@+id/introductionTime"
-			android:layout_toRightOf="@+id/introductionTime"
-			android:layout_alignBottom="@+id/introductionTime"
-			android:layout_marginLeft="@dimen/margin_medium"
-			tools:ignore="ContentDescription"
-			tools:src="@drawable/message_delivered"/>
-
-	</RelativeLayout>
-
-</LinearLayout>
\ No newline at end of file
diff --git a/briar-android/res/layout/navigation_menu.xml b/briar-android/res/layout/navigation_menu.xml
index f605fcbf73b21e8c6711d1c7b097fb9bbcb93afa..5497e52d4f72e32b71e63b62004beed6a2d26ab4 100644
--- a/briar-android/res/layout/navigation_menu.xml
+++ b/briar-android/res/layout/navigation_menu.xml
@@ -46,21 +46,6 @@
 				android:layout_height="@dimen/nav_separator_height"
 				android:layout_marginLeft="@dimen/margin_large"/>
 
-			<android.support.v7.widget.AppCompatButton
-				android:id="@+id/nav_btn_forums"
-				style="@style/NavMenuButton"
-				android:layout_width="match_parent"
-				android:layout_height="wrap_content"
-				android:drawableLeft="@drawable/social_chat"
-				android:onClick="onNavigationClick"
-				android:text="@string/forums_button"/>
-
-			<View
-				style="@style/Divider"
-				android:layout_width="match_parent"
-				android:layout_height="@dimen/margin_separator"
-				android:layout_marginLeft="@dimen/margin_large"/>
-
 			<android.support.v7.widget.AppCompatButton
 				android:id="@+id/nav_btn_settings"
 				style="@style/NavMenuButton"
diff --git a/briar-android/res/layout/share_forum_message.xml b/briar-android/res/layout/share_forum_message.xml
deleted file mode 100644
index 64a027914890b9d91afd500921f8e36b3cbc67fb..0000000000000000000000000000000000000000
--- a/briar-android/res/layout/share_forum_message.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<android.support.v4.widget.NestedScrollView
-	xmlns:android="http://schemas.android.com/apk/res/android"
-	android:layout_width="match_parent"
-	android:layout_height="match_parent"
-	android:fillViewport="true">
-
-	<LinearLayout
-		android:layout_width="match_parent"
-		android:layout_height="match_parent"
-		android:padding="@dimen/margin_activity_horizontal"
-		android:orientation="vertical">
-
-		<TextView
-			android:id="@+id/introductionText"
-			android:layout_width="match_parent"
-			android:layout_height="0dp"
-			android:layout_marginTop="@dimen/margin_medium"
-			android:layout_weight="1"
-			android:gravity="top"
-			android:textSize="@dimen/text_size_medium"
-			android:text="@string/forum_share_message"/>
-
-		<EditText
-			android:id="@+id/invitationMessageView"
-			android:layout_width="match_parent"
-			android:layout_height="wrap_content"
-			android:layout_marginTop="@dimen/margin_medium"
-			android:gravity="bottom"
-			android:hint="@string/introduction_message_hint"
-			android:inputType="text|textMultiLine|textCapSentences"/>
-
-		<Button
-			android:id="@+id/shareForumButton"
-			style="@style/BriarButton"
-			android:layout_width="match_parent"
-			android:layout_height="wrap_content"
-			android:text="@string/forum_share_button"
-			/>
-
-	</LinearLayout>
-
-</android.support.v4.widget.NestedScrollView>
\ No newline at end of file
diff --git a/briar-android/res/layout/text_avatar_view.xml b/briar-android/res/layout/text_avatar_view.xml
deleted file mode 100644
index a154d9d4a1f810996677cafd3fc5bd8754713d73..0000000000000000000000000000000000000000
--- a/briar-android/res/layout/text_avatar_view.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<merge
-	xmlns:android="http://schemas.android.com/apk/res/android"
-	xmlns:tools="http://schemas.android.com/tools"
-	xmlns:app="http://schemas.android.com/apk/res-auto">
-
-	<de.hdodenhof.circleimageview.CircleImageView
-		android:id="@+id/avatarBackground"
-		android:layout_width="@dimen/avatar_forum_size"
-		android:layout_height="@dimen/avatar_forum_size"
-		android:layout_gravity="center"
-		android:src="@android:color/transparent"
-		app:civ_fill_color="@color/briar_button_positive"
-		app:civ_border_color="@color/briar_primary"
-		app:civ_border_width="@dimen/avatar_border_width"/>
-
-	<android.support.v7.widget.AppCompatTextView
-		android:id="@+id/textAvatarView"
-		android:layout_width="wrap_content"
-		android:layout_height="wrap_content"
-		android:layout_gravity="center"
-		android:maxLength="1"
-		android:shadowColor="@color/forum_avatar_shadow"
-		android:shadowDx="0"
-		android:shadowDy="1.5"
-		android:shadowRadius="1.5"
-		android:textColor="@color/briar_text_primary_inverse"
-		android:textSize="30sp"
-		tools:text="T"/>
-
-</merge>
-
diff --git a/briar-android/res/menu/forum_actions.xml b/briar-android/res/menu/forum_actions.xml
deleted file mode 100644
index 292fe2b9cb42442520d3c08dd2f1ab542ffe98f0..0000000000000000000000000000000000000000
--- a/briar-android/res/menu/forum_actions.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<menu
-	xmlns:android="http://schemas.android.com/apk/res/android"
-	xmlns:app="http://schemas.android.com/apk/res-auto">
-
-	<item
-		android:id="@+id/action_forum_compose_post"
-		android:icon="@drawable/forum_item_create_white"
-		android:title="@string/forum_compose_post"
-		app:showAsAction="ifRoom"/>
-
-	<item
-		android:id="@+id/action_forum_share"
-		android:icon="@drawable/social_share_white"
-		android:title="@string/forum_share_button"
-		app:showAsAction="ifRoom"/>
-
-	<item
-		android:id="@+id/action_forum_delete"
-		android:icon="@drawable/action_delete_white"
-		android:title="@string/forum_leave"
-		app:showAsAction="never"/>
-
-</menu>
\ No newline at end of file
diff --git a/briar-android/res/menu/forum_list_actions.xml b/briar-android/res/menu/forum_list_actions.xml
deleted file mode 100644
index ddc26364ec5e04e757a2ede7ba482ac268e36497..0000000000000000000000000000000000000000
--- a/briar-android/res/menu/forum_list_actions.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<menu
-	xmlns:android="http://schemas.android.com/apk/res/android"
-	xmlns:app="http://schemas.android.com/apk/res-auto">
-
-	<item
-		android:id="@+id/action_create_forum"
-		android:icon="@drawable/ic_add_white"
-		android:title="@string/create_forum_button"
-		app:showAsAction="ifRoom"/>
-
-</menu>
\ No newline at end of file
diff --git a/briar-android/res/menu/forum_share_actions.xml b/briar-android/res/menu/forum_share_actions.xml
deleted file mode 100644
index a3d6c154774c13dfe9d370c6eec048fc38dcb7b0..0000000000000000000000000000000000000000
--- a/briar-android/res/menu/forum_share_actions.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<menu
-	xmlns:android="http://schemas.android.com/apk/res/android"
-	xmlns:app="http://schemas.android.com/apk/res-auto">
-
-	<item
-		android:id="@+id/action_share_forum"
-		android:icon="@drawable/ic_check_white"
-		android:title="@string/forum_share_action"
-		app:showAsAction="always"/>
-
-</menu>
\ No newline at end of file
diff --git a/briar-android/res/values/color.xml b/briar-android/res/values/color.xml
index 7fa718ebda375ea5f5eea125634f407c5d732e81..5a54608d5d032394ebff09168a015a0b7a7805ef 100644
--- a/briar-android/res/values/color.xml
+++ b/briar-android/res/values/color.xml
@@ -16,9 +16,7 @@
 	<color name="private_message_date_inverse">#e0e0e0</color>
 	<color name="unread_background">#FFFFFF</color>
 	<color name="horizontal_border">#CCCCCC</color>
-	<color name="forums_available_background">@color/briar_gold</color>
 	<color name="no_private_messages">#AAAAAA</color>
-	<color name="forum_avatar_shadow">#b3b3b3</color>
 
 	<color name="briar_primary">@color/briar_blue</color>
 	<color name="briar_primary_dark">@color/briar_blue_dark</color>
diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml
index 447d3dc6a3373dfc330fac4167d2f3c4601780cc..131941aff5877fbcbc06ebc615f330f3d203889b 100644
--- a/briar-android/res/values/strings.xml
+++ b/briar-android/res/values/strings.xml
@@ -35,7 +35,6 @@
 	<string name="contact_list_button">Contacts</string>
 	<string name="delete_contact">Delete contact</string>
 	<string name="contact_deleted_toast">Contact deleted</string>
-	<string name="forums_button">Forums</string>
 	<string name="settings_button">Settings</string>
 	<string name="sign_out_button">Sign Out</string>
 	<string name="contact_list_title">Contacts</string>
@@ -66,63 +65,26 @@
 	<string name="qr_code_invalid">The QR code is invalid</string>
 	<string name="connecting_to_device">Connecting to device\u2026</string>
 	<string name="authenticating_with_device">Authenticating with device\u2026</string>
-	<string name="connection_aborted_local">Connection aborted by us! This could mean that someone is trying to interfere with your connection</string>
-	<string name="connection_aborted_remote">Connection aborted by your contact! This could mean that someone is trying to interfere with your connection</string>
+	<string name="connection_aborted_local">Connection failed</string>
+	<string name="connection_aborted_remote">Connection failed</string>
 	<string name="no_private_messages">No messages</string>
 	<string name="private_message_hint">Type message</string>
 	<string name="message_sent_toast">Message sent</string>
-	<string name="forums_title">Forums</string>
-	<string name="no_forums">You don\'t have any forums.\n\nWhy don\'t you create a new one yourself or ask your contacts to share one with you?</string>
-	<plurals name="forums_shared">
-		<item quantity="one">%d forum shared by contacts</item>
-		<item quantity="other">%d forums shared by contacts</item>
-	</plurals>
-	<string name="show_forums">Show</string>
-	<string name="forum_leave">Leave Forum</string>
-	<string name="forum_left_toast">Left Forum</string>
-	<string name="no_forum_posts">No posts</string>
-	<string name="no_unread_posts">no unread posts</string>
-	<plurals name="unread_posts">
-		<item quantity="one">%d unread post</item>
-		<item quantity="other">%d unread posts</item>
-	</plurals>
-	<string name="create_forum_title">New Forum</string>
-	<string name="choose_forum_name">Choose a name for your forum:</string>
-	<string name="create_forum_button">Create Forum</string>
-	<string name="forum_created_toast">Forum created</string>
-	<string name="forum_share_action">Share this forum with chosen contacts</string>
-	<string name="forum_share_button">Share Forum</string>
-	<string name="forum_shared_snackbar">Forum shared with chosen contacts</string>
-	<string name="forum_share_message">You may compose an optional invitation message that will be sent to the selected contacts.</string>
-	<string name="forum_invitation_received">%1$s has shared the forum \"%2$s\" with you.</string>
-	<string name="forum_invitation_sent">You have shared the forum \"%1$s\" with %2$s.</string>
-	<string name="forum_show_available">Show Available Forums</string>
-	<string name="forum_compose_post">New Forum Post</string>
-	<string name="from">From:</string>
 	<string name="anonymous">Anonymous</string>
 	<string name="new_identity_item">New identity\u2026</string>
 	<string name="new_identity_title">New Identity</string>
 	<string name="create_identity_button">Create Identity</string>
 	<string name="identity_created_toast">Identity created</string>
-	<string name="forum_post_hint">Type forum post</string>
-	<string name="available_forums_title">Available Forums</string>
-	<string name="forum_joined_toast">Joined Forum</string>
-	<string name="forum_declined_toast">Forum Invitation Declined</string>
 	<string name="shared_by_format">Shared by %s</string>
 	<string name="no_contacts_prompt">You don\'t have any contacts. Add a contact now?</string>
 	<string name="add_button">Add</string>
 	<string name="cancel_button">Cancel</string>
 	<string name="done_button">Done</string>
 	<string name="delete_button">Delete</string>
-	<string name="post_sent_toast">Forum post sent</string>
 	<plurals name="private_message_notification_text">
 		<item quantity="one">New private message.</item>
 		<item quantity="other">%d new private messages.</item>
 	</plurals>
-	<plurals name="forum_post_notification_text">
-		<item quantity="one">New forum post.</item>
-		<item quantity="other">%d new forum posts.</item>
-	</plurals>
 
 	<!-- Settings -->
 	<string name="settings_title">Settings</string>
@@ -138,7 +100,6 @@
 	<string name="panic_setting_hint">Configure how Briar will react when you use a panic button app</string>
 	<string name="notification_settings_title">Notifications</string>
 	<string name="notify_private_messages_setting">Show alerts for private messages</string>
-	<string name="notify_forum_posts_setting">Show alerts for forum posts</string>
 	<string name="notify_vibration_setting">Vibrate</string>
 	<string name="notify_sound_setting">Sound</string>
 	<string name="notify_sound_setting_default">Default ringtone</string>
@@ -205,8 +166,6 @@
 	<string name="dialog_welcome_message">Add a contact to start communicating securely or press the icon in the upper left corner of the screen for more options.</string>
 	<string name="dialog_title_share_crash_report">Briar has crashed</string>
 	<string name="dialog_message_share_crash_report">Would you like to review the crash report and send it to the developers? It will be stored encrypted on your device until the next time you log into Briar, and then sent securely to the developers.</string>
-	<string name="dialog_title_leave_forum">Confirm Leaving Forum</string>
-	<string name="dialog_message_leave_forum">Are you sure that you want to leave this forum? Contacts you have shared this forum with might get cut off from receiving updates for this forum.</string>
 	<string name="dialog_button_ok">OK</string>
 	<string name="dialog_button_leave">Leave</string>
 	<string name="dialog_button_introduce">Introduce</string>
@@ -216,8 +175,6 @@
 	<string name="dashboard_toolbar_header">Briar</string>
 	<string name="settings_toolbar_header">Settings</string>
 	<string name="contacts_toolbar_header">Contacts</string>
-	<string name="forums_toolbar_header">Forums</string>
-	<string name="forums_share_toolbar_header">Choose Contacts</string>
 	<!-- Progress titles -->
 	<string name="progress_title_logout">Signing out of Briar..</string>
 	<string name="progress_title_please_wait">Please wait..</string>
diff --git a/briar-android/res/xml/settings.xml b/briar-android/res/xml/settings.xml
index 7ee104ad2beb6b6060923fb9529f186382c9e2ac..b17bf8607a2c9af87c042bf7a27088838b8023e7 100644
--- a/briar-android/res/xml/settings.xml
+++ b/briar-android/res/xml/settings.xml
@@ -49,12 +49,6 @@
 			android:persistent="false"
 			android:title="@string/notify_private_messages_setting"/>
 
-		<CheckBoxPreference
-			android:defaultValue="true"
-			android:key="pref_key_notify_forum_posts"
-			android:persistent="false"
-			android:title="@string/notify_forum_posts_setting"/>
-
 		<CheckBoxPreference
 			android:defaultValue="true"
 			android:key="pref_key_notify_vibration"
diff --git a/briar-android/src/org/briarproject/android/ActivityComponent.java b/briar-android/src/org/briarproject/android/ActivityComponent.java
index 6fec172b40ffe8ee4922ca850502f2d9c30fbed5..541bc677011459355954653dcd80f22a0da6d104 100644
--- a/briar-android/src/org/briarproject/android/ActivityComponent.java
+++ b/briar-android/src/org/briarproject/android/ActivityComponent.java
@@ -3,14 +3,6 @@ package org.briarproject.android;
 import android.app.Activity;
 
 import org.briarproject.android.contact.ConversationActivity;
-import org.briarproject.android.forum.AvailableForumsActivity;
-import org.briarproject.android.forum.ContactSelectorFragment;
-import org.briarproject.android.forum.CreateForumActivity;
-import org.briarproject.android.forum.ForumActivity;
-import org.briarproject.android.forum.ReadForumPostActivity;
-import org.briarproject.android.forum.ShareForumActivity;
-import org.briarproject.android.forum.ShareForumMessageFragment;
-import org.briarproject.android.forum.WriteForumPostActivity;
 import org.briarproject.android.fragment.BaseFragment;
 import org.briarproject.android.identity.CreateIdentityActivity;
 import org.briarproject.android.introduction.IntroductionActivity;
@@ -51,18 +43,6 @@ public interface ActivityComponent {
 
 	void inject(CreateIdentityActivity activity);
 
-	void inject(AvailableForumsActivity activity);
-
-	void inject(WriteForumPostActivity activity);
-
-	void inject(CreateForumActivity activity);
-
-	void inject(ShareForumActivity activity);
-
-	void inject(ReadForumPostActivity activity);
-
-	void inject(ForumActivity activity);
-
 	void inject(SettingsActivity activity);
 
 	void inject(IntroductionActivity activity);
@@ -70,9 +50,6 @@ public interface ActivityComponent {
 	@Named("ContactListFragment")
 	BaseFragment newContactListFragment();
 
-	@Named("ForumListFragment")
-	BaseFragment newForumListFragment();
-
 	@Named("ChooseIdentityFragment")
 	BaseFragment newChooseIdentityFragment();
 
@@ -82,12 +59,6 @@ public interface ActivityComponent {
 	@Named("ContactChooserFragment")
 	BaseFragment newContactChooserFragment();
 
-	@Named("ContactSelectorFragment")
-	ContactSelectorFragment newContactSelectorFragment();
-
-	@Named("ShareForumMessageFragment")
-	ShareForumMessageFragment newShareForumMessageFragment();
-
 	@Named("IntroductionMessageFragment")
 	IntroductionMessageFragment newIntroductionMessageFragment();
 }
diff --git a/briar-android/src/org/briarproject/android/ActivityModule.java b/briar-android/src/org/briarproject/android/ActivityModule.java
index 0e13fbd0d7aa59311bf86b0b664a8afd6bfc5f46..893435083c7c927678722b5dca3156e8cf6aff5b 100644
--- a/briar-android/src/org/briarproject/android/ActivityModule.java
+++ b/briar-android/src/org/briarproject/android/ActivityModule.java
@@ -19,9 +19,6 @@ import org.briarproject.android.controller.PasswordControllerImpl;
 import org.briarproject.android.controller.SetupController;
 import org.briarproject.android.controller.SetupControllerImpl;
 import org.briarproject.android.controller.TransportStateListener;
-import org.briarproject.android.forum.ContactSelectorFragment;
-import org.briarproject.android.forum.ForumListFragment;
-import org.briarproject.android.forum.ShareForumMessageFragment;
 import org.briarproject.android.fragment.BaseFragment;
 import org.briarproject.android.introduction.ContactChooserFragment;
 import org.briarproject.android.introduction.IntroductionMessageFragment;
@@ -116,13 +113,6 @@ public class ActivityModule {
 		return new BriarServiceConnection();
 	}
 
-	@Provides
-	@Named("ForumListFragment")
-	BaseFragment provideForumListFragment(ForumListFragment fragment) {
-		fragment.setArguments(new Bundle());
-		return fragment;
-	}
-
 	@Provides
 	@Named("ContactListFragment")
 	BaseFragment provideContactListFragment(ContactListFragment fragment) {
@@ -153,22 +143,6 @@ public class ActivityModule {
 		return fragment;
 	}
 
-	@Provides
-	@Named("ContactSelectorFragment")
-	ContactSelectorFragment provideContactSelectorFragment(
-			ContactSelectorFragment fragment) {
-		fragment.setArguments(new Bundle());
-		return fragment;
-	}
-
-	@Provides
-	@Named("ShareForumMessageFragment")
-	ShareForumMessageFragment provideShareForumMessageFragment(
-			ShareForumMessageFragment fragment) {
-		fragment.setArguments(new Bundle());
-		return fragment;
-	}
-
 	@Provides
 	@Named("IntroductionMessageFragment")
 	IntroductionMessageFragment provideIntroductionMessageFragment(
diff --git a/briar-android/src/org/briarproject/android/AndroidComponent.java b/briar-android/src/org/briarproject/android/AndroidComponent.java
index 92a4e8ccb64341964e0d66c0db33b26b0b0c7a78..e7637754a7bf15cba6fe060591d62064172a2e45 100644
--- a/briar-android/src/org/briarproject/android/AndroidComponent.java
+++ b/briar-android/src/org/briarproject/android/AndroidComponent.java
@@ -14,9 +14,6 @@ import org.briarproject.api.crypto.PasswordStrengthEstimator;
 import org.briarproject.api.db.DatabaseConfig;
 import org.briarproject.api.db.DatabaseExecutor;
 import org.briarproject.api.event.EventBus;
-import org.briarproject.api.forum.ForumManager;
-import org.briarproject.api.forum.ForumPostFactory;
-import org.briarproject.api.forum.ForumSharingManager;
 import org.briarproject.api.identity.AuthorFactory;
 import org.briarproject.api.identity.IdentityManager;
 import org.briarproject.api.introduction.IntroductionManager;
@@ -89,12 +86,6 @@ public interface AndroidComponent extends CoreEagerSingletons {
 
 	TransportPropertyManager transportPropertyManager();
 
-	ForumManager forumManager();
-
-	ForumSharingManager forumSharingManager();
-
-	ForumPostFactory forumPostFactory();
-
 	SettingsManager settingsManager();
 
 	ContactExchangeTask contactExchangeTask();
diff --git a/briar-android/src/org/briarproject/android/AndroidNotificationManagerImpl.java b/briar-android/src/org/briarproject/android/AndroidNotificationManagerImpl.java
index 166c8e84fb05ba68632d9d2921fe321bdc43fbf6..18af095f69c79125283ec2e9bab931df1248bc37 100644
--- a/briar-android/src/org/briarproject/android/AndroidNotificationManagerImpl.java
+++ b/briar-android/src/org/briarproject/android/AndroidNotificationManagerImpl.java
@@ -13,20 +13,17 @@ import org.briarproject.R;
 import org.briarproject.android.api.AndroidExecutor;
 import org.briarproject.android.api.AndroidNotificationManager;
 import org.briarproject.android.contact.ConversationActivity;
-import org.briarproject.android.forum.ForumActivity;
 import org.briarproject.api.contact.Contact;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.db.DatabaseExecutor;
 import org.briarproject.api.db.DbException;
 import org.briarproject.api.event.Event;
 import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.ForumInvitationReceivedEvent;
 import org.briarproject.api.event.IntroductionRequestReceivedEvent;
 import org.briarproject.api.event.IntroductionResponseReceivedEvent;
 import org.briarproject.api.event.IntroductionSucceededEvent;
 import org.briarproject.api.event.MessageValidatedEvent;
 import org.briarproject.api.event.SettingsUpdatedEvent;
-import org.briarproject.api.forum.ForumManager;
 import org.briarproject.api.lifecycle.Service;
 import org.briarproject.api.lifecycle.ServiceException;
 import org.briarproject.api.messaging.MessagingManager;
@@ -54,7 +51,6 @@ import static android.content.Context.NOTIFICATION_SERVICE;
 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
 import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
 import static android.support.v4.app.NotificationCompat.CATEGORY_MESSAGE;
-import static android.support.v4.app.NotificationCompat.CATEGORY_SOCIAL;
 import static android.support.v4.app.NotificationCompat.VISIBILITY_SECRET;
 import static java.util.logging.Level.WARNING;
 import static org.briarproject.android.BriarActivity.GROUP_ID;
@@ -64,12 +60,9 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 		Service, EventListener {
 
 	private static final int PRIVATE_MESSAGE_NOTIFICATION_ID = 3;
-	private static final int FORUM_POST_NOTIFICATION_ID = 4;
 	private static final int INTRODUCTION_SUCCESS_NOTIFICATION_ID = 5;
 	private static final String CONTACT_URI =
 			"content://org.briarproject/contact";
-	private static final String FORUM_URI =
-			"content://org.briarproject/forum";
 
 	private static final Logger LOG =
 			Logger.getLogger(AndroidNotificationManagerImpl.class.getName());
@@ -77,16 +70,14 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 	private final Executor dbExecutor;
 	private final SettingsManager settingsManager;
 	private final MessagingManager messagingManager;
-	private final ForumManager forumManager;
 	private final AndroidExecutor androidExecutor;
 	private final Context appContext;
 
 	// The following must only be accessed on the main UI thread
 	private final Map<GroupId, Integer> contactCounts = new HashMap<>();
-	private final Map<GroupId, Integer> forumCounts = new HashMap<>();
 	private final AtomicBoolean used = new AtomicBoolean(false);
 
-	private int contactTotal = 0, forumTotal = 0;
+	private int contactTotal = 0;
 	private int nextRequestId = 0;
 	private GroupId visibleGroup = null;
 
@@ -95,12 +86,10 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 	@Inject
 	public AndroidNotificationManagerImpl(@DatabaseExecutor Executor dbExecutor,
 			SettingsManager settingsManager, MessagingManager messagingManager,
-			ForumManager forumManager, AndroidExecutor androidExecutor,
-			Application app) {
+			AndroidExecutor androidExecutor, Application app) {
 		this.dbExecutor = dbExecutor;
 		this.settingsManager = settingsManager;
 		this.messagingManager = messagingManager;
-		this.forumManager = forumManager;
 		this.androidExecutor = androidExecutor;
 		appContext = app.getApplicationContext();
 	}
@@ -121,7 +110,6 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 			@Override
 			public Void call() {
 				clearPrivateMessageNotification();
-				clearForumPostNotification();
 				clearIntroductionSuccessNotification();
 				return null;
 			}
@@ -139,12 +127,6 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 		nm.cancel(PRIVATE_MESSAGE_NOTIFICATION_ID);
 	}
 
-	private void clearForumPostNotification() {
-		Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
-		NotificationManager nm = (NotificationManager) o;
-		nm.cancel(FORUM_POST_NOTIFICATION_ID);
-	}
-
 	private void clearIntroductionSuccessNotification() {
 		Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
 		NotificationManager nm = (NotificationManager) o;
@@ -162,8 +144,6 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 				ClientId c = m.getClientId();
 				if (c.equals(messagingManager.getClientId()))
 					showPrivateMessageNotification(m.getMessage().getGroupId());
-				else if (c.equals(forumManager.getClientId()))
-					showForumPostNotification(m.getMessage().getGroupId());
 			}
 		} else if (e instanceof IntroductionRequestReceivedEvent) {
 			ContactId c = ((IntroductionRequestReceivedEvent) e).getContactId();
@@ -174,9 +154,6 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 		} else if (e instanceof IntroductionSucceededEvent) {
 			Contact c = ((IntroductionSucceededEvent) e).getContact();
 			showIntroductionSucceededNotification(c);
-		} else if (e instanceof ForumInvitationReceivedEvent) {
-			ContactId c = ((ForumInvitationReceivedEvent) e).getContactId();
-			showNotificationForPrivateConversation(c);
 		}
 	}
 
@@ -282,82 +259,6 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 		return defaults;
 	}
 
-	@Override
-	public void showForumPostNotification(final GroupId g) {
-		androidExecutor.execute(new Runnable() {
-			@Override
-			public void run() {
-				Integer count = forumCounts.get(g);
-				if (count == null) forumCounts.put(g, 1);
-				else forumCounts.put(g, count + 1);
-				forumTotal++;
-				if (!g.equals(visibleGroup))
-					updateForumPostNotification();
-			}
-		});
-	}
-
-	@Override
-	public void clearForumPostNotification(final GroupId g) {
-		androidExecutor.execute(new Runnable() {
-			@Override
-			public void run() {
-				Integer count = forumCounts.remove(g);
-				if (count == null) return; // Already cleared
-				forumTotal -= count;
-				// FIXME: If the notification isn't showing, this may show it
-				updateForumPostNotification();
-			}
-		});
-	}
-
-	private void updateForumPostNotification() {
-		if (forumTotal == 0) {
-			clearForumPostNotification();
-		} else if (settings.getBoolean("notifyForumPosts", true)) {
-			NotificationCompat.Builder b =
-					new NotificationCompat.Builder(appContext);
-			b.setSmallIcon(R.drawable.message_notification_icon);
-			b.setContentTitle(appContext.getText(R.string.app_name));
-			b.setContentText(appContext.getResources().getQuantityString(
-					R.plurals.forum_post_notification_text, forumTotal,
-					forumTotal));
-			String ringtoneUri = settings.get("notifyRingtoneUri");
-			if (!StringUtils.isNullOrEmpty(ringtoneUri))
-				b.setSound(Uri.parse(ringtoneUri));
-			b.setDefaults(getDefaults());
-			b.setOnlyAlertOnce(true);
-			b.setAutoCancel(true);
-			if (forumCounts.size() == 1) {
-				Intent i = new Intent(appContext, ForumActivity.class);
-				GroupId g = forumCounts.keySet().iterator().next();
-				i.putExtra(GROUP_ID, g.getBytes());
-				String idHex = StringUtils.toHexString(g.getBytes());
-				i.setData(Uri.parse(FORUM_URI + "/" + idHex));
-				i.setFlags(FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP);
-				TaskStackBuilder t = TaskStackBuilder.create(appContext);
-				t.addParentStack(ForumActivity.class);
-				t.addNextIntent(i);
-				b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
-			} else {
-				Intent i = new Intent(appContext, NavDrawerActivity.class);
-				i.putExtra(NavDrawerActivity.INTENT_FORUMS, true);
-				i.setFlags(FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP);
-				TaskStackBuilder t = TaskStackBuilder.create(appContext);
-				t.addParentStack(NavDrawerActivity.class);
-				t.addNextIntent(i);
-				b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
-			}
-			if (Build.VERSION.SDK_INT >= 21) {
-				b.setCategory(CATEGORY_SOCIAL);
-				b.setVisibility(VISIBILITY_SECRET);
-			}
-			Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
-			NotificationManager nm = (NotificationManager) o;
-			nm.notify(FORUM_POST_NOTIFICATION_ID, b.build());
-		}
-	}
-
 	@Override
 	public void blockNotification(final GroupId g) {
 		androidExecutor.execute(new Runnable() {
@@ -423,5 +324,4 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 			}
 		});
 	}
-
 }
diff --git a/briar-android/src/org/briarproject/android/BriarFragmentActivity.java b/briar-android/src/org/briarproject/android/BriarFragmentActivity.java
index dddc8a003892ebbceb6b50148011e9cfd6111d12..430360b92931ba0bfc90f1e432b00d7c31ecf66e 100644
--- a/briar-android/src/org/briarproject/android/BriarFragmentActivity.java
+++ b/briar-android/src/org/briarproject/android/BriarFragmentActivity.java
@@ -8,7 +8,6 @@ import android.support.v7.app.AlertDialog;
 
 import org.briarproject.R;
 import org.briarproject.android.contact.ContactListFragment;
-import org.briarproject.android.forum.ForumListFragment;
 import org.briarproject.android.fragment.BaseFragment;
 
 /**
@@ -24,8 +23,6 @@ public abstract class BriarFragmentActivity extends BriarActivity {
 
 		if (fragmentTag.equals(ContactListFragment.TAG)) {
 			actionBar.setTitle(R.string.contacts_toolbar_header);
-		} else if (fragmentTag.equals(ForumListFragment.TAG)) {
-			actionBar.setTitle(R.string.forums_toolbar_header);
 		}
 	}
 
diff --git a/briar-android/src/org/briarproject/android/NavDrawerActivity.java b/briar-android/src/org/briarproject/android/NavDrawerActivity.java
index 3c61bbf4883ae8fe5754c69c8d6cbb89b6750cb6..327729ed1c827cb8527acca7c63d6c066df032e1 100644
--- a/briar-android/src/org/briarproject/android/NavDrawerActivity.java
+++ b/briar-android/src/org/briarproject/android/NavDrawerActivity.java
@@ -43,7 +43,6 @@ public class NavDrawerActivity extends BriarFragmentActivity implements
 	public final static String PREF_SEEN_WELCOME_MESSAGE = "welcome_message";
 
 	public static final String INTENT_CONTACTS = "intent_contacts";
-	public static final String INTENT_FORUMS = "intent_forums";
 
 	private static final String KEY_CURRENT_FRAGMENT_ID = "key_current_id";
 
@@ -70,9 +69,7 @@ public class NavDrawerActivity extends BriarFragmentActivity implements
 		exitIfStartupFailed(intent);
 		checkAuthorHandle(intent);
 		clearBackStack();
-		if (intent.getBooleanExtra(INTENT_FORUMS, false))
-			startFragment(activityComponent.newForumListFragment());
-		else if (intent.getBooleanExtra(INTENT_CONTACTS, false))
+		if (intent.getBooleanExtra(INTENT_CONTACTS, false))
 			startFragment(activityComponent.newContactListFragment());
 	}
 
@@ -171,9 +168,6 @@ public class NavDrawerActivity extends BriarFragmentActivity implements
 			case R.id.nav_btn_contacts:
 				startFragment(activityComponent.newContactListFragment());
 				break;
-			case R.id.nav_btn_forums:
-				startFragment(activityComponent.newForumListFragment());
-				break;
 			case R.id.nav_btn_settings:
 				startActivity(new Intent(this, SettingsActivity.class));
 				break;
diff --git a/briar-android/src/org/briarproject/android/api/AndroidNotificationManager.java b/briar-android/src/org/briarproject/android/api/AndroidNotificationManager.java
index 33177e1b8c42aee32ca58196a75a175cbed64c46..b8f629db65d36bd22dbc2a3e993f29e5a783be6e 100644
--- a/briar-android/src/org/briarproject/android/api/AndroidNotificationManager.java
+++ b/briar-android/src/org/briarproject/android/api/AndroidNotificationManager.java
@@ -2,17 +2,13 @@ package org.briarproject.android.api;
 
 import org.briarproject.api.sync.GroupId;
 
-/** Manages notifications for private messages and forum posts. */
+/** Manages notifications for private messages and introductions. */
 public interface AndroidNotificationManager {
 
 	void showPrivateMessageNotification(GroupId g);
 
 	void clearPrivateMessageNotification(GroupId g);
 
-	void showForumPostNotification(GroupId g);
-
-	void clearForumPostNotification(GroupId g);
-
 	void blockNotification(GroupId g);
 
 	void unblockNotification(GroupId g);
diff --git a/briar-android/src/org/briarproject/android/contact/ContactListFragment.java b/briar-android/src/org/briarproject/android/contact/ContactListFragment.java
index d01e6571dfb74052cea5ebb8e797bc10515ea8a3..01655086e8e6d9bbc20311bb213c9c2f036c7ad2 100644
--- a/briar-android/src/org/briarproject/android/contact/ContactListFragment.java
+++ b/briar-android/src/org/briarproject/android/contact/ContactListFragment.java
@@ -29,8 +29,6 @@ import org.briarproject.api.event.Event;
 import org.briarproject.api.event.EventBus;
 import org.briarproject.api.event.EventListener;
 import org.briarproject.api.event.MessageValidatedEvent;
-import org.briarproject.api.forum.ForumInvitationMessage;
-import org.briarproject.api.forum.ForumSharingManager;
 import org.briarproject.api.identity.IdentityManager;
 import org.briarproject.api.identity.LocalAuthor;
 import org.briarproject.api.introduction.IntroductionManager;
@@ -76,8 +74,6 @@ public class ContactListFragment extends BaseFragment implements EventListener {
 	protected volatile MessagingManager messagingManager;
 	@Inject
 	protected volatile IntroductionManager introductionManager;
-	@Inject
-	protected volatile ForumSharingManager forumSharingManager;
 
 	@Inject
 	public ContactListFragment() {
@@ -225,8 +221,7 @@ public class ContactListFragment extends BaseFragment implements EventListener {
 			MessageValidatedEvent m = (MessageValidatedEvent) e;
 			ClientId c = m.getClientId();
 			if (m.isValid() && (c.equals(messagingManager.getClientId()) ||
-					c.equals(introductionManager.getClientId()) ||
-					c.equals(forumSharingManager.getClientId()))) {
+					c.equals(introductionManager.getClientId()))) {
 				LOG.info("Message added, reloading");
 				reloadConversation(m.getMessage().getGroupId());
 			}
@@ -320,16 +315,6 @@ public class ContactListFragment extends BaseFragment implements EventListener {
 		if (LOG.isLoggable(INFO))
 			LOG.info("Loading introduction messages took " + duration + " ms");
 
-		now = System.currentTimeMillis();
-		Collection<ForumInvitationMessage> invitations =
-				forumSharingManager.getForumInvitationMessages(id);
-		for (ForumInvitationMessage i : invitations) {
-			messages.add(ConversationItem.from(i));
-		}
-		duration = System.currentTimeMillis() - now;
-		if (LOG.isLoggable(INFO))
-			LOG.info("Loading forum invitations took " + duration + " ms");
-
 		return messages;
 	}
 }
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
index 676273700d43043aba098a8ecb0d8075281075c3..ba95bf9553a91efa7d8fdb83d171fb08dd1fb9fb 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
+++ b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
@@ -43,14 +43,11 @@ import org.briarproject.api.event.ContactRemovedEvent;
 import org.briarproject.api.event.Event;
 import org.briarproject.api.event.EventBus;
 import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.ForumInvitationReceivedEvent;
 import org.briarproject.api.event.IntroductionRequestReceivedEvent;
 import org.briarproject.api.event.IntroductionResponseReceivedEvent;
 import org.briarproject.api.event.MessageValidatedEvent;
 import org.briarproject.api.event.MessagesAckedEvent;
 import org.briarproject.api.event.MessagesSentEvent;
-import org.briarproject.api.forum.ForumInvitationMessage;
-import org.briarproject.api.forum.ForumSharingManager;
 import org.briarproject.api.introduction.IntroductionManager;
 import org.briarproject.api.introduction.IntroductionMessage;
 import org.briarproject.api.introduction.IntroductionRequest;
@@ -122,8 +119,6 @@ public class ConversationActivity extends BriarActivity
 	protected volatile PrivateMessageFactory privateMessageFactory;
 	@Inject
 	protected volatile IntroductionManager introductionManager;
-	@Inject
-	protected volatile ForumSharingManager forumSharingManager;
 
 	private volatile GroupId groupId = null;
 	private volatile ContactId contactId = null;
@@ -297,13 +292,10 @@ public class ConversationActivity extends BriarActivity
 					Collection<IntroductionMessage> introductions =
 							introductionManager
 									.getIntroductionMessages(contactId);
-					Collection<ForumInvitationMessage> invitations =
-							forumSharingManager
-									.getForumInvitationMessages(contactId);
 					long duration = System.currentTimeMillis() - now;
 					if (LOG.isLoggable(INFO))
 						LOG.info("Loading headers took " + duration + " ms");
-					displayMessages(headers, introductions, invitations);
+					displayMessages(headers, introductions);
 				} catch (NoSuchContactException e) {
 					finishOnUiThread();
 				} catch (DbException e) {
@@ -315,14 +307,12 @@ public class ConversationActivity extends BriarActivity
 	}
 
 	private void displayMessages(final Collection<PrivateMessageHeader> headers,
-			final Collection<IntroductionMessage> introductions,
-			final Collection<ForumInvitationMessage> invitations) {
+			final Collection<IntroductionMessage> introductions) {
 		runOnUiThread(new Runnable() {
 			@Override
 			public void run() {
 				sendButton.setEnabled(true);
-				if (headers.isEmpty() && introductions.isEmpty() &&
-						invitations.isEmpty()) {
+				if (headers.isEmpty() && introductions.isEmpty()) {
 					// we have no messages,
 					// so let the list know to hide progress bar
 					list.showData();
@@ -350,10 +340,6 @@ public class ConversationActivity extends BriarActivity
 						}
 						items.add(item);
 					}
-					for (ForumInvitationMessage i : invitations) {
-						ConversationItem item = ConversationItem.from(i);
-						items.add(item);
-					}
 					adapter.addAll(items);
 					// Scroll to the bottom
 					list.scrollToPosition(adapter.getItemCount() - 1);
@@ -507,12 +493,6 @@ public class ConversationActivity extends BriarActivity
 						ConversationItem.from(this, contactName, ir);
 				addIntroduction(item);
 			}
-		} else if (e instanceof ForumInvitationReceivedEvent) {
-			ForumInvitationReceivedEvent event =
-					(ForumInvitationReceivedEvent) e;
-			if (event.getContactId().equals(contactId)) {
-				loadMessages();
-			}
 		}
 	}
 
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java b/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java
index acc6ca6ca21749e41102d1ac15eb7dcaa2e4b9d3..89f255d8ebbd8a5582f07c7f3c528d11a0b30c9d 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java
+++ b/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java
@@ -1,7 +1,6 @@
 package org.briarproject.android.contact;
 
 import android.content.Context;
-import android.content.Intent;
 import android.support.v7.util.SortedList;
 import android.support.v7.widget.RecyclerView;
 import android.text.format.DateUtils;
@@ -14,9 +13,7 @@ import android.widget.ImageView;
 import android.widget.TextView;
 
 import org.briarproject.R;
-import org.briarproject.android.forum.AvailableForumsActivity;
 import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.forum.ForumInvitationMessage;
 import org.briarproject.api.introduction.IntroductionRequest;
 import org.briarproject.api.messaging.PrivateMessageHeader;
 import org.briarproject.util.StringUtils;
@@ -25,8 +22,6 @@ import java.util.List;
 
 import static android.support.v7.util.SortedList.INVALID_POSITION;
 import static android.support.v7.widget.RecyclerView.ViewHolder;
-import static org.briarproject.android.contact.ConversationItem.FORUM_INVITATION_IN;
-import static org.briarproject.android.contact.ConversationItem.FORUM_INVITATION_OUT;
 import static org.briarproject.android.contact.ConversationItem.INTRODUCTION_IN;
 import static org.briarproject.android.contact.ConversationItem.INTRODUCTION_OUT;
 import static org.briarproject.android.contact.ConversationItem.IncomingItem;
@@ -87,14 +82,6 @@ class ConversationAdapter extends RecyclerView.Adapter {
 			v = LayoutInflater.from(viewGroup.getContext()).inflate(
 					R.layout.list_item_notice_out, viewGroup, false);
 			return new NoticeHolder(v, type);
-		} else if (type == FORUM_INVITATION_IN) {
-			v = LayoutInflater.from(viewGroup.getContext()).inflate(
-					R.layout.list_item_forum_invitation_in, viewGroup, false);
-			return new InvitationHolder(v, type);
-		} else if (type == FORUM_INVITATION_OUT) {
-			v = LayoutInflater.from(viewGroup.getContext()).inflate(
-					R.layout.list_item_forum_invitation_out, viewGroup, false);
-			return new InvitationHolder(v, type);
 		}
 		// incoming message (non-local)
 		else {
@@ -119,12 +106,6 @@ class ConversationAdapter extends RecyclerView.Adapter {
 			bindNotice((NoticeHolder) ui, (ConversationNoticeOutItem) item);
 		} else if (item instanceof ConversationNoticeInItem) {
 			bindNotice((NoticeHolder) ui, (ConversationNoticeInItem) item);
-		} else if (item instanceof ConversationForumInvitationOutItem) {
-			bindInvitation((InvitationHolder) ui,
-					(ConversationForumInvitationOutItem) item);
-		} else if (item instanceof ConversationForumInvitationInItem) {
-			bindInvitation((InvitationHolder) ui,
-					(ConversationForumInvitationInItem) item);
 		} else {
 			throw new IllegalArgumentException("Unhandled Conversation Item");
 		}
@@ -276,65 +257,6 @@ class ConversationAdapter extends RecyclerView.Adapter {
 		}
 	}
 
-	private void bindInvitation(InvitationHolder ui,
-			final ConversationForumInvitationItem item) {
-
-		ForumInvitationMessage fim = item.getForumInvitationMessage();
-
-		String message = fim.getMessage();
-		if (StringUtils.isNullOrEmpty(message)) {
-			ui.messageLayout.setVisibility(View.GONE);
-		} else {
-			ui.messageLayout.setVisibility(View.VISIBLE);
-			ui.message.body.setText(message);
-			ui.message.date.setText(
-					DateUtils.getRelativeTimeSpanString(ctx, item.getTime()));
-		}
-
-		// Outgoing Invitation
-		if (item instanceof ConversationForumInvitationOutItem) {
-			ui.text.setText(ctx.getString(R.string.forum_invitation_sent,
-					fim.getForumName(), contactName));
-			ConversationForumInvitationOutItem i =
-					(ConversationForumInvitationOutItem) item;
-			if (i.isSeen()) {
-				ui.status.setImageResource(R.drawable.message_delivered);
-				ui.message.status.setImageResource(
-						R.drawable.message_delivered_white);
-			} else if (i.isSent()) {
-				ui.status.setImageResource(R.drawable.message_sent);
-				ui.message.status.setImageResource(
-						R.drawable.message_sent_white);
-			} else {
-				ui.status.setImageResource(R.drawable.message_stored);
-				ui.message.status.setImageResource(
-						R.drawable.message_stored_white);
-			}
-		}
-		// Incoming Invitation
-		else {
-			ui.text.setText(ctx.getString(R.string.forum_invitation_received,
-					contactName, fim.getForumName()));
-
-			if (fim.isAvailable()) {
-				ui.showForumsButton.setVisibility(View.VISIBLE);
-				ui.showForumsButton
-						.setOnClickListener(new View.OnClickListener() {
-							@Override
-							public void onClick(View v) {
-								Intent intent = new Intent(ctx,
-										AvailableForumsActivity.class);
-								ctx.startActivity(intent);
-							}
-						});
-			} else {
-				ui.showForumsButton.setVisibility(View.GONE);
-			}
-		}
-		ui.date.setText(
-				DateUtils.getRelativeTimeSpanString(ctx, item.getTime()));
-	}
-
 	@Override
 	public int getItemCount() {
 		return items.size();
@@ -473,33 +395,6 @@ class ConversationAdapter extends RecyclerView.Adapter {
 		}
 	}
 
-	private static class InvitationHolder extends RecyclerView.ViewHolder {
-
-		private final View messageLayout;
-		private final MessageHolder message;
-		private final TextView text;
-		private final Button showForumsButton;
-		private final TextView date;
-		private final ImageView status;
-
-		public InvitationHolder(View v, int type) {
-			super(v);
-
-			messageLayout = v.findViewById(R.id.messageLayout);
-			message = new MessageHolder(messageLayout,
-					type == FORUM_INVITATION_IN ? MSG_IN : MSG_OUT);
-			text = (TextView) v.findViewById(R.id.introductionText);
-			showForumsButton = (Button) v.findViewById(R.id.showForumsButton);
-			date = (TextView) v.findViewById(R.id.introductionTime);
-
-			if (type == FORUM_INVITATION_OUT) {
-				status = (ImageView) v.findViewById(R.id.introductionStatus);
-			} else {
-				status = null;
-			}
-		}
-	}
-
 	private class ListCallbacks extends SortedList.Callback<ConversationItem> {
 
 		@Override
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationForumInvitationInItem.java b/briar-android/src/org/briarproject/android/contact/ConversationForumInvitationInItem.java
deleted file mode 100644
index b082fe4d6af5ce16614c6fce3ef084d4bf1ec79b..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/contact/ConversationForumInvitationInItem.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.briarproject.android.contact;
-
-import org.briarproject.api.forum.ForumInvitationMessage;
-
-// This class is not thread-safe
-public class ConversationForumInvitationInItem
-		extends ConversationForumInvitationItem
-		implements ConversationItem.IncomingItem {
-
-	private boolean read;
-
-	public ConversationForumInvitationInItem(ForumInvitationMessage fim) {
-		super(fim);
-
-		this.read = fim.isRead();
-	}
-
-	@Override
-	int getType() {
-		return FORUM_INVITATION_IN;
-	}
-
-	@Override
-	public boolean isRead() {
-		return read;
-	}
-
-	@Override
-	public void setRead(boolean read) {
-		this.read = read;
-	}
-}
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationForumInvitationItem.java b/briar-android/src/org/briarproject/android/contact/ConversationForumInvitationItem.java
deleted file mode 100644
index eb303d16b58e964efd36da5003d08a410765e086..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/contact/ConversationForumInvitationItem.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.briarproject.android.contact;
-
-import org.briarproject.api.forum.ForumInvitationMessage;
-
-abstract class ConversationForumInvitationItem extends ConversationItem {
-
-	private final ForumInvitationMessage fim;
-
-	public ConversationForumInvitationItem(ForumInvitationMessage fim) {
-		super(fim.getId(), fim.getTimestamp());
-
-		this.fim = fim;
-	}
-
-	public ForumInvitationMessage getForumInvitationMessage() {
-		return fim;
-	}
-}
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationForumInvitationOutItem.java b/briar-android/src/org/briarproject/android/contact/ConversationForumInvitationOutItem.java
deleted file mode 100644
index 202023dda2fd3dd68534f276fedc005c98dd8327..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/contact/ConversationForumInvitationOutItem.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.briarproject.android.contact;
-
-import org.briarproject.api.forum.ForumInvitationMessage;
-
-/**
- * This class is needed and can not be replaced by an ConversationNoticeOutItem,
- * because it carries the optional invitation message
- * to be displayed as a regular private message.
- * <p/>
- * This class is not thread-safe
- */
-public class ConversationForumInvitationOutItem
-		extends ConversationForumInvitationItem
-		implements ConversationItem.OutgoingItem {
-
-	private boolean sent, seen;
-
-	public ConversationForumInvitationOutItem(ForumInvitationMessage fim) {
-		super(fim);
-		this.sent = fim.isSent();
-		this.seen = fim.isSeen();
-	}
-
-	@Override
-	int getType() {
-		return FORUM_INVITATION_OUT;
-	}
-
-	@Override
-	public boolean isSent() {
-		return sent;
-	}
-
-	@Override
-	public void setSent(boolean sent) {
-		this.sent = sent;
-	}
-
-	@Override
-	public boolean isSeen() {
-		return seen;
-	}
-
-	@Override
-	public void setSeen(boolean seen) {
-		this.seen = seen;
-	}
-}
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationItem.java b/briar-android/src/org/briarproject/android/contact/ConversationItem.java
index 7b75cb13a61209323544f2ab6937c14177fd3b0c..e4b078f3a83d487ed4a84f07a5d269735a1fbd1a 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationItem.java
+++ b/briar-android/src/org/briarproject/android/contact/ConversationItem.java
@@ -3,7 +3,6 @@ package org.briarproject.android.contact;
 import android.content.Context;
 
 import org.briarproject.R;
-import org.briarproject.api.forum.ForumInvitationMessage;
 import org.briarproject.api.introduction.IntroductionMessage;
 import org.briarproject.api.introduction.IntroductionRequest;
 import org.briarproject.api.introduction.IntroductionResponse;
@@ -21,8 +20,6 @@ public abstract class ConversationItem {
 	final static int INTRODUCTION_OUT = 4;
 	final static int NOTICE_IN = 5;
 	final static int NOTICE_OUT = 6;
-	final static int FORUM_INVITATION_IN = 7;
-	final static int FORUM_INVITATION_OUT = 8;
 
 	private MessageId id;
 	private long time;
@@ -95,14 +92,6 @@ public abstract class ConversationItem {
 		}
 	}
 
-	public static ConversationItem from(ForumInvitationMessage fim) {
-		if (fim.isLocal()) {
-			return new ConversationForumInvitationOutItem(fim);
-		} else {
-			return new ConversationForumInvitationInItem(fim);
-		}
-	}
-
 	/**
 	 * This method should not be used to get user-facing objects,
 	 * Its purpose is to provider data for the contact list.
diff --git a/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java b/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java
deleted file mode 100644
index bcf39e8360766b1e722912f3a6c7faec994f4ceb..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java
+++ /dev/null
@@ -1,178 +0,0 @@
-package org.briarproject.android.forum;
-
-import android.os.Bundle;
-import android.support.v7.widget.LinearLayoutManager;
-import android.widget.Toast;
-
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.BriarActivity;
-import org.briarproject.android.util.BriarRecyclerView;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.NoSuchGroupException;
-import org.briarproject.api.event.ContactRemovedEvent;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.ForumInvitationReceivedEvent;
-import org.briarproject.api.event.GroupAddedEvent;
-import org.briarproject.api.event.GroupRemovedEvent;
-import org.briarproject.api.forum.Forum;
-import org.briarproject.api.forum.ForumManager;
-import org.briarproject.api.forum.ForumSharingManager;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.logging.Logger;
-
-import javax.inject.Inject;
-
-import static android.widget.Toast.LENGTH_SHORT;
-import static java.util.logging.Level.INFO;
-import static java.util.logging.Level.WARNING;
-import static org.briarproject.android.forum.AvailableForumsAdapter.AvailableForumClickListener;
-
-public class AvailableForumsActivity extends BriarActivity
-		implements EventListener, AvailableForumClickListener {
-
-	private static final Logger LOG =
-			Logger.getLogger(AvailableForumsActivity.class.getName());
-
-	private AvailableForumsAdapter adapter;
-
-	// Fields that are accessed from background threads must be volatile
-	@Inject
-	protected volatile ForumManager forumManager;
-	@Inject
-	protected volatile ForumSharingManager forumSharingManager;
-	@Inject
-	protected volatile EventBus eventBus;
-
-	@Override
-	public void onCreate(Bundle state) {
-		super.onCreate(state);
-
-		setContentView(R.layout.activity_available_forums);
-
-		adapter = new AvailableForumsAdapter(this, this);
-		BriarRecyclerView list =
-				(BriarRecyclerView) findViewById(R.id.availableForumsView);
-		list.setLayoutManager(new LinearLayoutManager(this));
-		list.setAdapter(adapter);
-	}
-
-	@Override
-	public void injectActivity(ActivityComponent component) {
-		component.inject(this);
-	}
-
-	@Override
-	public void onResume() {
-		super.onResume();
-		eventBus.addListener(this);
-		loadForums();
-	}
-
-	private void loadForums() {
-		runOnDbThread(new Runnable() {
-			@Override
-			public void run() {
-				try {
-					Collection<ForumContacts> available = new ArrayList<>();
-					long now = System.currentTimeMillis();
-					for (Forum f : forumSharingManager.getAvailableForums()) {
-						try {
-							Collection<Contact> c =
-									forumSharingManager.getSharedBy(f.getId());
-							available.add(new ForumContacts(f, c));
-						} catch (NoSuchGroupException e) {
-							// Continue
-						}
-					}
-					long duration = System.currentTimeMillis() - now;
-					if (LOG.isLoggable(INFO))
-						LOG.info("Load took " + duration + " ms");
-					displayForums(available);
-				} catch (DbException e) {
-					if (LOG.isLoggable(WARNING))
-						LOG.log(WARNING, e.toString(), e);
-				}
-			}
-		});
-	}
-
-	private void displayForums(final Collection<ForumContacts> available) {
-		runOnUiThread(new Runnable() {
-			@Override
-			public void run() {
-				if (available.isEmpty()) {
-					LOG.info("No forums available, finishing");
-					finish();
-				} else {
-					adapter.clear();
-					List<AvailableForumsItem> list =
-							new ArrayList<>(available.size());
-					for (ForumContacts f : available)
-						list.add(new AvailableForumsItem(f));
-					adapter.addAll(list);
-				}
-			}
-		});
-	}
-
-	@Override
-	public void onPause() {
-		super.onPause();
-		eventBus.removeListener(this);
-	}
-
-	@Override
-	public void eventOccurred(Event e) {
-		if (e instanceof ContactRemovedEvent) {
-			LOG.info("Contact removed, reloading");
-			loadForums();
-		} else if (e instanceof GroupAddedEvent) {
-			GroupAddedEvent g = (GroupAddedEvent) e;
-			if (g.getGroup().getClientId().equals(forumManager.getClientId())) {
-				LOG.info("Forum added, reloading");
-				loadForums();
-			}
-		} else if (e instanceof GroupRemovedEvent) {
-			GroupRemovedEvent g = (GroupRemovedEvent) e;
-			if (g.getGroup().getClientId().equals(forumManager.getClientId())) {
-				LOG.info("Forum removed, reloading");
-				loadForums();
-			}
-		} else if (e instanceof ForumInvitationReceivedEvent) {
-			LOG.info("Available forums updated, reloading");
-			loadForums();
-		}
-	}
-
-	@Override
-	public void onItemClick(AvailableForumsItem item, boolean accept) {
-		respondToInvitation(item.getForum(), accept);
-
-		// show toast
-		int res = R.string.forum_declined_toast;
-		if (accept) res = R.string.forum_joined_toast;
-		Toast.makeText(this, res, LENGTH_SHORT).show();
-	}
-
-	private void respondToInvitation(final Forum f, final boolean accept) {
-		runOnDbThread(new Runnable() {
-			@Override
-			public void run() {
-				try {
-					forumSharingManager.respondToInvitation(f, accept);
-				} catch (DbException e) {
-					if (LOG.isLoggable(WARNING))
-						LOG.log(WARNING, e.toString(), e);
-				}
-				loadForums();
-			}
-		});
-	}
-}
diff --git a/briar-android/src/org/briarproject/android/forum/AvailableForumsAdapter.java b/briar-android/src/org/briarproject/android/forum/AvailableForumsAdapter.java
deleted file mode 100644
index 8fc9caa399613d34f212fdf362fe7293ff0456ec..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/forum/AvailableForumsAdapter.java
+++ /dev/null
@@ -1,161 +0,0 @@
-package org.briarproject.android.forum;
-
-import android.content.Context;
-import android.support.v7.util.SortedList;
-import android.support.v7.widget.RecyclerView;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.TextView;
-
-import org.briarproject.R;
-import org.briarproject.android.util.TextAvatarView;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.util.StringUtils;
-
-import java.util.ArrayList;
-import java.util.Collection;
-
-class AvailableForumsAdapter extends
-		RecyclerView.Adapter<AvailableForumsAdapter.AvailableForumViewHolder> {
-
-	private final Context ctx;
-	private final AvailableForumClickListener listener;
-	private final SortedList<AvailableForumsItem> forums =
-			new SortedList<>(AvailableForumsItem.class,
-					new SortedListCallBacks());
-
-	AvailableForumsAdapter(Context ctx, AvailableForumClickListener listener) {
-		this.ctx = ctx;
-		this.listener = listener;
-	}
-
-	@Override
-	public AvailableForumViewHolder onCreateViewHolder(ViewGroup parent,
-			int viewType) {
-
-		View v = LayoutInflater.from(ctx)
-				.inflate(R.layout.list_item_available_forum, parent,  false);
-		return new AvailableForumViewHolder(v);
-	}
-
-	@Override
-	public void onBindViewHolder(AvailableForumViewHolder ui, int position) {
-		final AvailableForumsItem item = getItem(position);
-
-		ui.avatar.setText(item.getForum().getName().substring(0, 1));
-		ui.avatar.setBackgroundBytes(item.getForum().getId().getBytes());
-
-		ui.name.setText(item.getForum().getName());
-
-		Collection<String> names = new ArrayList<>();
-		for (Contact c : item.getContacts()) names.add(c.getAuthor().getName());
-		ui.sharedBy.setText(ctx.getString(R.string.shared_by_format,
-				StringUtils.join(names, ", ")));
-
-		ui.accept.setOnClickListener(new View.OnClickListener() {
-			@Override
-			public void onClick(View v) {
-				listener.onItemClick(item, true);
-			}
-		});
-		ui.decline.setOnClickListener(new View.OnClickListener() {
-			@Override
-			public void onClick(View v) {
-				listener.onItemClick(item, false);
-			}
-		});
-	}
-
-	@Override
-	public int getItemCount() {
-		return forums.size();
-	}
-
-	public AvailableForumsItem getItem(int position) {
-		return forums.get(position);
-	}
-
-	public void add(AvailableForumsItem item) {
-		forums.add(item);
-	}
-
-	public void addAll(Collection<AvailableForumsItem> list) {
-		forums.addAll(list);
-	}
-
-	public void clear() {
-		forums.clear();
-	}
-
-	protected static class AvailableForumViewHolder
-			extends RecyclerView.ViewHolder {
-
-		private final TextAvatarView avatar;
-		private final TextView name;
-		private final TextView sharedBy;
-		private final Button accept;
-		private final Button decline;
-
-		public AvailableForumViewHolder(View v) {
-			super(v);
-
-			avatar = (TextAvatarView) v.findViewById(R.id.avatarView);
-			name = (TextView) v.findViewById(R.id.forumNameView);
-			sharedBy = (TextView) v.findViewById(R.id.sharedByView);
-			accept = (Button) v.findViewById(R.id.acceptButton);
-			decline = (Button) v.findViewById(R.id.declineButton);
-		}
-	}
-
-	private class SortedListCallBacks
-			extends SortedList.Callback<AvailableForumsItem> {
-
-		@Override
-		public int compare(AvailableForumsItem o1,
-				AvailableForumsItem o2) {
-			return String.CASE_INSENSITIVE_ORDER
-					.compare(o1.getForum().getName(),
-							o2.getForum().getName());
-		}
-
-		@Override
-		public void onInserted(int position, int count) {
-			notifyItemRangeInserted(position, count);
-		}
-
-		@Override
-		public void onRemoved(int position, int count) {
-			notifyItemRangeRemoved(position, count);
-		}
-
-		@Override
-		public void onMoved(int fromPosition, int toPosition) {
-			notifyItemMoved(fromPosition, toPosition);
-		}
-
-		@Override
-		public void onChanged(int position, int count) {
-			notifyItemRangeChanged(position, count);
-		}
-
-		@Override
-		public boolean areContentsTheSame(AvailableForumsItem oldItem,
-				AvailableForumsItem newItem) {
-			return oldItem.getForum().equals(newItem.getForum()) &&
-					oldItem.getContacts().equals(newItem.getContacts());
-		}
-
-		@Override
-		public boolean areItemsTheSame(AvailableForumsItem oldItem,
-				AvailableForumsItem newItem) {
-			return oldItem.getForum().equals(newItem.getForum());
-		}
-	}
-
-
-	interface AvailableForumClickListener {
-		void onItemClick(AvailableForumsItem item, boolean accept);
-	}
-}
diff --git a/briar-android/src/org/briarproject/android/forum/AvailableForumsItem.java b/briar-android/src/org/briarproject/android/forum/AvailableForumsItem.java
deleted file mode 100644
index 7d8a91feb8b4fea845dde718d0594fae89b1d366..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/forum/AvailableForumsItem.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.briarproject.android.forum;
-
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.forum.Forum;
-
-import java.util.Collection;
-
-class AvailableForumsItem {
-
-	private final ForumContacts forumContacts;
-
-	AvailableForumsItem(ForumContacts forumContacts) {
-		this.forumContacts = forumContacts;
-	}
-
-	Forum getForum() {
-		return forumContacts.getForum();
-	}
-
-	Collection<Contact> getContacts() {
-		return forumContacts.getContacts();
-	}
-}
diff --git a/briar-android/src/org/briarproject/android/forum/ContactSelectorAdapter.java b/briar-android/src/org/briarproject/android/forum/ContactSelectorAdapter.java
deleted file mode 100644
index 23ef1e78cc0b1e7715fd43f2d2873d2d5204341c..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/forum/ContactSelectorAdapter.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package org.briarproject.android.forum;
-
-import android.content.Context;
-import android.graphics.Color;
-import android.graphics.ColorFilter;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
-import android.os.Build;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.CheckBox;
-
-import org.briarproject.R;
-import org.briarproject.android.contact.BaseContactListAdapter;
-import org.briarproject.android.contact.ContactListItem;
-import org.briarproject.api.contact.ContactId;
-
-import java.util.ArrayList;
-import java.util.Collection;
-
-public class ContactSelectorAdapter
-		extends BaseContactListAdapter<ContactSelectorAdapter.SelectableContactHolder> {
-
-	public ContactSelectorAdapter(Context context,
-			OnItemClickListener listener) {
-
-		super(context, listener);
-	}
-
-	@Override
-	public SelectableContactHolder onCreateViewHolder(ViewGroup viewGroup,
-			int i) {
-		View v = LayoutInflater.from(ctx).inflate(
-				R.layout.list_item_selectable_contact, viewGroup, false);
-
-		return new SelectableContactHolder(v);
-	}
-
-	@Override
-	public void onBindViewHolder(SelectableContactHolder ui, int position) {
-		super.onBindViewHolder(ui, position);
-
-		SelectableContactListItem item =
-				(SelectableContactListItem) getItem(position);
-
-		if (item.isSelected()) {
-			ui.checkBox.setChecked(true);
-		} else {
-			ui.checkBox.setChecked(false);
-		}
-
-		if (item.isDisabled()) {
-			// we share this forum already with that contact
-			ui.layout.setEnabled(false);
-			grayOutItem(ui);
-		}
-	}
-
-	public Collection<ContactId> getSelectedContactIds() {
-		Collection<ContactId> selected = new ArrayList<>();
-
-		for (int i = 0; i < contacts.size(); i++) {
-			SelectableContactListItem item =
-					(SelectableContactListItem) contacts.get(i);
-			if (item.isSelected()) selected.add(item.getContact().getId());
-		}
-
-		return selected;
-	}
-
-	protected static class SelectableContactHolder
-			extends BaseContactListAdapter.BaseContactHolder {
-
-		private final CheckBox checkBox;
-
-		public SelectableContactHolder(View v) {
-			super(v);
-
-			checkBox = (CheckBox) v.findViewById(R.id.checkBox);
-		}
-	}
-
-	@Override
-	public int compareContactListItems(ContactListItem c1, ContactListItem c2) {
-		return compareByName(c1, c2);
-	}
-
-	private void grayOutItem(final SelectableContactHolder ui) {
-		if (Build.VERSION.SDK_INT >= 11) {
-			float alpha = 0.25f;
-			ui.avatar.setAlpha(alpha);
-			ui.name.setAlpha(alpha);
-			ui.checkBox.setAlpha(alpha);
-		} else {
-			ColorFilter colorFilter = new PorterDuffColorFilter(Color.GRAY,
-					PorterDuff.Mode.MULTIPLY);
-			ui.avatar.setColorFilter(colorFilter);
-			ui.name.setEnabled(false);
-			ui.checkBox.setEnabled(false);
-		}
-	}
-}
diff --git a/briar-android/src/org/briarproject/android/forum/ContactSelectorFragment.java b/briar-android/src/org/briarproject/android/forum/ContactSelectorFragment.java
deleted file mode 100644
index 8cefe834f75e42d1b7f107b4f052c1054301a0c2..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/forum/ContactSelectorFragment.java
+++ /dev/null
@@ -1,239 +0,0 @@
-package org.briarproject.android.forum;
-
-import android.content.Context;
-import android.os.Build;
-import android.os.Bundle;
-import android.support.v7.widget.LinearLayoutManager;
-import android.transition.Fade;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-
-import org.briarproject.R;
-import org.briarproject.android.contact.BaseContactListAdapter;
-import org.briarproject.android.contact.ContactListItem;
-import org.briarproject.android.fragment.BaseFragment;
-import org.briarproject.android.util.BriarRecyclerView;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.forum.ForumSharingManager;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.sync.GroupId;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.logging.Logger;
-
-import javax.inject.Inject;
-
-import static java.util.logging.Level.INFO;
-import static java.util.logging.Level.WARNING;
-import static org.briarproject.android.forum.ShareForumActivity.CONTACTS;
-import static org.briarproject.android.forum.ShareForumActivity.getContactsFromIds;
-import static org.briarproject.api.forum.ForumConstants.GROUP_ID;
-
-public class ContactSelectorFragment extends BaseFragment implements
-		BaseContactListAdapter.OnItemClickListener {
-
-	public final static String TAG = "ContactSelectorFragment";
-
-	private static final Logger LOG =
-			Logger.getLogger(ContactSelectorFragment.class.getName());
-
-	private ShareForumActivity shareForumActivity;
-	private Menu menu;
-	private BriarRecyclerView list;
-	private ContactSelectorAdapter adapter;
-	private Collection<ContactId> selectedContacts;
-
-	// Fields that are accessed from background threads must be volatile
-	@Inject
-	protected volatile ContactManager contactManager;
-	@Inject
-	protected volatile IdentityManager identityManager;
-	@Inject
-	protected volatile ForumSharingManager forumSharingManager;
-
-	protected volatile GroupId groupId;
-
-	public void initBundle(GroupId groupId) {
-		Bundle bundle = new Bundle();
-		bundle.putByteArray(GROUP_ID, groupId.getBytes());
-		setArguments(bundle);
-	}
-
-	@Inject
-	public ContactSelectorFragment() {
-
-	}
-
-	@Override
-	public void onAttach(Context context) {
-		super.onAttach(context);
-		try {
-			shareForumActivity = (ShareForumActivity) context;
-		} catch (ClassCastException e) {
-			throw new InstantiationError(
-					"This fragment is only meant to be attached to the ShareForumActivity");
-		}
-	}
-
-	@Override
-	public void onCreate(Bundle savedInstanceState) {
-		super.onCreate(savedInstanceState);
-
-		setHasOptionsMenu(true);
-		groupId = new GroupId(getArguments().getByteArray(GROUP_ID));
-		if (groupId == null) throw new IllegalStateException("No GroupId");
-	}
-
-	@Override
-	public View onCreateView(LayoutInflater inflater, ViewGroup container,
-			Bundle savedInstanceState) {
-
-		View contentView = inflater.inflate(
-				R.layout.introduction_contact_chooser, container, false);
-
-		if (Build.VERSION.SDK_INT >= 21) {
-			setExitTransition(new Fade());
-		}
-
-		adapter = new ContactSelectorAdapter(getActivity(), this);
-
-		list = (BriarRecyclerView) contentView.findViewById(R.id.contactList);
-		list.setLayoutManager(new LinearLayoutManager(getActivity()));
-		list.setAdapter(adapter);
-		list.setEmptyText(getString(R.string.no_contacts));
-
-		// restore selected contacts if available
-		if (savedInstanceState != null) {
-			ArrayList<Integer> intContacts =
-					savedInstanceState.getIntegerArrayList(CONTACTS);
-			selectedContacts = ShareForumActivity.getContactsFromIntegers(
-					intContacts);
-		}
-
-		return contentView;
-	}
-
-	@Override
-	public void onResume() {
-		super.onResume();
-
-		if (selectedContacts != null)
-			loadContacts(Collections.unmodifiableCollection(selectedContacts));
-		else loadContacts(null);
-	}
-
-	@Override
-	public void onSaveInstanceState(Bundle outState) {
-		if (adapter != null) {
-			selectedContacts = adapter.getSelectedContactIds();
-			outState.putIntegerArrayList(CONTACTS,
-					getContactsFromIds(selectedContacts));
-		}
-	}
-
-	@Override
-	public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
-		inflater.inflate(R.menu.forum_share_actions, menu);
-		super.onCreateOptionsMenu(menu, inflater);
-		this.menu = menu;
-		// hide sharing action initially, if no contact is selected
-		updateMenuItem();
-	}
-
-	@Override
-	public boolean onOptionsItemSelected(final MenuItem item) {
-		// Handle presses on the action bar items
-		switch (item.getItemId()) {
-			case android.R.id.home:
-				shareForumActivity.onBackPressed();
-				return true;
-			case R.id.action_share_forum:
-				selectedContacts = adapter.getSelectedContactIds();
-				shareForumActivity.showMessageScreen(groupId, selectedContacts);
-				return true;
-			default:
-				return super.onOptionsItemSelected(item);
-		}
-	}
-
-	@Override
-	public String getUniqueTag() {
-		return TAG;
-	}
-
-	@Override
-	public void onItemClick(View view, ContactListItem item) {
-		((SelectableContactListItem) item).toggleSelected();
-		adapter.notifyItemChanged(adapter.findItemPosition(item), item);
-
-		updateMenuItem();
-	}
-
-	private void loadContacts(final Collection<ContactId> selection) {
-		shareForumActivity.runOnDbThread(new Runnable() {
-			@Override
-			public void run() {
-				try {
-					long now = System.currentTimeMillis();
-					List<ContactListItem> contacts = new ArrayList<>();
-
-					for (Contact c : contactManager.getActiveContacts()) {
-						LocalAuthor localAuthor = identityManager
-								.getLocalAuthor(c.getLocalAuthorId());
-						// was this contact already selected?
-						boolean selected = selection != null &&
-								selection.contains(c.getId());
-						// do we have already some sharing with that contact?
-						boolean disabled =
-								!forumSharingManager.canBeShared(groupId, c);
-						contacts.add(new SelectableContactListItem(c,
-								localAuthor, groupId, selected, disabled));
-					}
-					long duration = System.currentTimeMillis() - now;
-					if (LOG.isLoggable(INFO))
-						LOG.info("Load took " + duration + " ms");
-					displayContacts(Collections.unmodifiableList(contacts));
-				} catch (DbException e) {
-					displayContacts(Collections.<ContactListItem>emptyList());
-					if (LOG.isLoggable(WARNING))
-						LOG.log(WARNING, e.toString(), e);
-				}
-			}
-		});
-	}
-
-	private void displayContacts(final List<ContactListItem> contacts) {
-		shareForumActivity.runOnUiThread(new Runnable() {
-			@Override
-			public void run() {
-				if (!contacts.isEmpty()) adapter.addAll(contacts);
-				else list.showData();
-				updateMenuItem();
-			}
-		});
-	}
-
-	private void updateMenuItem() {
-		if (menu == null) return;
-		MenuItem item = menu.findItem(R.id.action_share_forum);
-		if (item == null) return;
-
-		selectedContacts = adapter.getSelectedContactIds();
-		if (selectedContacts.size() > 0) {
-			item.setVisible(true);
-		} else {
-			item.setVisible(false);
-		}
-	}
-}
diff --git a/briar-android/src/org/briarproject/android/forum/CreateForumActivity.java b/briar-android/src/org/briarproject/android/forum/CreateForumActivity.java
deleted file mode 100644
index f3053067a7190c8ada8535a00e83bdcb2c11751c..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/forum/CreateForumActivity.java
+++ /dev/null
@@ -1,162 +0,0 @@
-package org.briarproject.android.forum;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.text.Editable;
-import android.text.TextWatcher;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-import android.widget.TextView.OnEditorActionListener;
-import android.widget.Toast;
-
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.BriarActivity;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.forum.Forum;
-import org.briarproject.api.forum.ForumManager;
-import org.briarproject.util.StringUtils;
-
-import java.util.logging.Logger;
-
-import javax.inject.Inject;
-
-import static android.view.View.GONE;
-import static android.view.View.VISIBLE;
-import static android.widget.Toast.LENGTH_LONG;
-import static java.util.logging.Level.INFO;
-import static java.util.logging.Level.WARNING;
-import static org.briarproject.android.forum.ForumActivity.FORUM_NAME;
-import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH;
-
-public class CreateForumActivity extends BriarActivity
-		implements OnEditorActionListener, OnClickListener {
-
-	private static final Logger LOG =
-			Logger.getLogger(CreateForumActivity.class.getName());
-
-	private EditText nameEntry;
-	private Button createForumButton;
-	private ProgressBar progress;
-	private TextView feedback;
-
-	// Fields that are accessed from background threads must be volatile
-	@Inject
-	protected volatile ForumManager forumManager;
-
-	@Override
-	public void onCreate(Bundle state) {
-		super.onCreate(state);
-
-		setContentView(R.layout.activity_create_forum);
-
-		nameEntry = (EditText) findViewById(R.id.createForumNameEntry);
-		TextWatcher nameEntryWatcher = new TextWatcher() {
-
-			@Override
-			public void afterTextChanged(Editable s) {
-			}
-
-			@Override
-			public void beforeTextChanged(CharSequence s, int start, int count,
-					int after) {
-			}
-
-			@Override
-			public void onTextChanged(CharSequence text, int start,
-					int lengthBefore, int lengthAfter) {
-				enableOrDisableCreateButton();
-			}
-		};
-		nameEntry.setOnEditorActionListener(this);
-		nameEntry.addTextChangedListener(nameEntryWatcher);
-
-		feedback = (TextView) findViewById(R.id.createForumFeedback);
-
-		createForumButton = (Button) findViewById(R.id.createForumButton);
-		createForumButton.setOnClickListener(this);
-
-		progress = (ProgressBar) findViewById(R.id.createForumProgressBar);
-
-	}
-
-	@Override
-	public void injectActivity(ActivityComponent component) {
-		component.inject(this);
-	}
-
-	private void enableOrDisableCreateButton() {
-		if (progress == null) return; // Not created yet
-		createForumButton.setEnabled(validateName());
-	}
-
-	@Override
-	public boolean onEditorAction(TextView textView, int actionId, KeyEvent e) {
-		hideSoftKeyboard(textView);
-		return true;
-	}
-
-	private boolean validateName() {
-		String name = nameEntry.getText().toString();
-		int length = StringUtils.toUtf8(name).length;
-		if (length > MAX_FORUM_NAME_LENGTH) {
-			feedback.setText(R.string.name_too_long);
-			return false;
-		}
-		feedback.setText("");
-		return length > 0;
-	}
-
-	@Override
-	public void onClick(View view) {
-		if (view == createForumButton) {
-			hideSoftKeyboard(view);
-			if (!validateName()) return;
-			createForumButton.setVisibility(GONE);
-			progress.setVisibility(VISIBLE);
-			storeForum(nameEntry.getText().toString());
-		}
-	}
-
-	private void storeForum(final String name) {
-		runOnDbThread(new Runnable() {
-			@Override
-			public void run() {
-				try {
-					long now = System.currentTimeMillis();
-					Forum f = forumManager.createForum(name);
-					forumManager.addForum(f);
-					long duration = System.currentTimeMillis() - now;
-					if (LOG.isLoggable(INFO))
-						LOG.info("Storing forum took " + duration + " ms");
-					displayForum(f);
-				} catch (DbException e) {
-					if (LOG.isLoggable(WARNING))
-						LOG.log(WARNING, e.toString(), e);
-					finishOnUiThread();
-				}
-			}
-		});
-	}
-
-	private void displayForum(final Forum f) {
-		runOnUiThread(new Runnable() {
-			@Override
-			public void run() {
-				Intent i = new Intent(CreateForumActivity.this,
-						ForumActivity.class);
-				i.putExtra(GROUP_ID, f.getId().getBytes());
-				i.putExtra(FORUM_NAME, f.getName());
-				startActivity(i);
-				Toast.makeText(CreateForumActivity.this,
-						R.string.forum_created_toast, LENGTH_LONG).show();
-				finish();
-			}
-		});
-	}
-}
diff --git a/briar-android/src/org/briarproject/android/forum/ForumActivity.java b/briar-android/src/org/briarproject/android/forum/ForumActivity.java
deleted file mode 100644
index 1ea92c3c08b6c73d5c66def586d8796908042c0e..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/forum/ForumActivity.java
+++ /dev/null
@@ -1,442 +0,0 @@
-package org.briarproject.android.forum;
-
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.design.widget.Snackbar;
-import android.support.v4.app.ActivityCompat;
-import android.support.v4.app.ActivityOptionsCompat;
-import android.support.v7.app.AlertDialog;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.LinearLayout;
-import android.widget.ListView;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.AndroidComponent;
-import org.briarproject.android.BriarActivity;
-import org.briarproject.android.api.AndroidNotificationManager;
-import org.briarproject.android.util.ListLoadingProgressBar;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.NoSuchGroupException;
-import org.briarproject.api.db.NoSuchMessageException;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.GroupRemovedEvent;
-import org.briarproject.api.event.MessageValidatedEvent;
-import org.briarproject.api.forum.Forum;
-import org.briarproject.api.forum.ForumManager;
-import org.briarproject.api.forum.ForumPostHeader;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.logging.Logger;
-
-import javax.inject.Inject;
-
-import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
-import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
-import static android.support.design.widget.Snackbar.LENGTH_LONG;
-import static android.view.Gravity.CENTER;
-import static android.view.Gravity.CENTER_HORIZONTAL;
-import static android.view.View.GONE;
-import static android.view.View.VISIBLE;
-import static android.widget.LinearLayout.VERTICAL;
-import static android.widget.Toast.LENGTH_SHORT;
-import static java.util.logging.Level.INFO;
-import static java.util.logging.Level.WARNING;
-import static org.briarproject.android.forum.ReadForumPostActivity.RESULT_PREV_NEXT;
-import static org.briarproject.android.util.CommonLayoutParams.MATCH_MATCH;
-import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP_1;
-
-public class ForumActivity extends BriarActivity implements EventListener,
-		OnItemClickListener {
-
-	public static final String FORUM_NAME = "briar.FORUM_NAME";
-	public static final String MIN_TIMESTAMP = "briar.MIN_TIMESTAMP";
-
-	private static final int REQUEST_READ = 2;
-	private static final int REQUEST_FORUM_SHARED = 3;
-	private static final Logger LOG =
-			Logger.getLogger(ForumActivity.class.getName());
-
-	@Inject protected AndroidNotificationManager notificationManager;
-	private Map<MessageId, byte[]> bodyCache = new HashMap<>();
-	private TextView empty = null;
-	private ForumAdapter adapter = null;
-	private ListView list = null;
-	private ListLoadingProgressBar loading = null;
-
-	// Fields that are accessed from background threads must be volatile
-	@Inject protected volatile ForumManager forumManager;
-	@Inject protected volatile EventBus eventBus;
-	private volatile GroupId groupId = null;
-	private volatile Forum forum = null;
-
-	@Override
-	public void onCreate(Bundle state) {
-		super.onCreate(state);
-
-		Intent i = getIntent();
-		byte[] b = i.getByteArrayExtra(GROUP_ID);
-		if (b == null) throw new IllegalStateException();
-		groupId = new GroupId(b);
-		String forumName = i.getStringExtra(FORUM_NAME);
-		if (forumName != null) setTitle(forumName);
-
-		LinearLayout layout = new LinearLayout(this);
-		layout.setLayoutParams(MATCH_MATCH);
-		layout.setOrientation(VERTICAL);
-		layout.setGravity(CENTER_HORIZONTAL);
-
-		empty = new TextView(this);
-		empty.setLayoutParams(MATCH_WRAP_1);
-		empty.setGravity(CENTER);
-		empty.setTextSize(18);
-		empty.setText(R.string.no_forum_posts);
-		empty.setVisibility(GONE);
-		layout.addView(empty);
-
-		adapter = new ForumAdapter(this);
-		list = new ListView(this);
-		list.setLayoutParams(MATCH_WRAP_1);
-		list.setAdapter(adapter);
-		list.setOnItemClickListener(this);
-		list.setVisibility(GONE);
-		layout.addView(list);
-
-		// Show a progress bar while the list is loading
-		loading = new ListLoadingProgressBar(this);
-		layout.addView(loading);
-
-		setContentView(layout);
-	}
-
-	@Override
-	public void injectActivity(ActivityComponent component) {
-		component.inject(this);
-	}
-
-	@Override
-	public void onResume() {
-		super.onResume();
-		eventBus.addListener(this);
-		notificationManager.blockNotification(groupId);
-		notificationManager.clearForumPostNotification(groupId);
-		loadForum();
-		loadHeaders();
-	}
-
-	@Override
-	public boolean onCreateOptionsMenu(Menu menu) {
-		// Inflate the menu items for use in the action bar
-		MenuInflater inflater = getMenuInflater();
-		inflater.inflate(R.menu.forum_actions, menu);
-
-		return super.onCreateOptionsMenu(menu);
-	}
-
-	@Override
-	public boolean onOptionsItemSelected(final MenuItem item) {
-		// Handle presses on the action bar items
-		switch (item.getItemId()) {
-			case R.id.action_forum_compose_post:
-				Intent i = new Intent(this, WriteForumPostActivity.class);
-				i.putExtra(GROUP_ID, groupId.getBytes());
-				i.putExtra(FORUM_NAME, forum.getName());
-				i.putExtra(MIN_TIMESTAMP, getMinTimestampForNewPost());
-				startActivity(i);
-				return true;
-			case R.id.action_forum_share:
-				Intent i2 = new Intent(this, ShareForumActivity.class);
-				i2.setFlags(FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP);
-				i2.putExtra(GROUP_ID, groupId.getBytes());
-				ActivityOptionsCompat options = ActivityOptionsCompat
-						.makeCustomAnimation(this, android.R.anim.slide_in_left,
-								android.R.anim.slide_out_right);
-				ActivityCompat
-						.startActivityForResult(this, i2, REQUEST_FORUM_SHARED,
-								options.toBundle());
-				return true;
-			case R.id.action_forum_delete:
-				showUnsubscribeDialog();
-				return true;
-			default:
-				return super.onOptionsItemSelected(item);
-		}
-	}
-
-	private void loadForum() {
-		runOnDbThread(new Runnable() {
-			public void run() {
-				try {
-					long now = System.currentTimeMillis();
-					forum = forumManager.getForum(groupId);
-					long duration = System.currentTimeMillis() - now;
-					if (LOG.isLoggable(INFO))
-						LOG.info("Loading forum " + duration + " ms");
-					displayForumName();
-				} catch (NoSuchGroupException e) {
-					finishOnUiThread();
-				} catch (DbException e) {
-					if (LOG.isLoggable(WARNING))
-						LOG.log(WARNING, e.toString(), e);
-				}
-			}
-		});
-	}
-
-	private void displayForumName() {
-		runOnUiThread(new Runnable() {
-			public void run() {
-				setTitle(forum.getName());
-			}
-		});
-	}
-
-	private void loadHeaders() {
-		runOnDbThread(new Runnable() {
-			public void run() {
-				try {
-					long now = System.currentTimeMillis();
-					Collection<ForumPostHeader> headers =
-							forumManager.getPostHeaders(groupId);
-					long duration = System.currentTimeMillis() - now;
-					if (LOG.isLoggable(INFO))
-						LOG.info("Load took " + duration + " ms");
-					displayHeaders(headers);
-				} catch (NoSuchGroupException e) {
-					finishOnUiThread();
-				} catch (DbException e) {
-					if (LOG.isLoggable(WARNING))
-						LOG.log(WARNING, e.toString(), e);
-				}
-			}
-		});
-	}
-
-	private void displayHeaders(final Collection<ForumPostHeader> headers) {
-		runOnUiThread(new Runnable() {
-			public void run() {
-				loading.setVisibility(GONE);
-				adapter.clear();
-				if (headers.isEmpty()) {
-					empty.setVisibility(VISIBLE);
-					list.setVisibility(GONE);
-				} else {
-					empty.setVisibility(GONE);
-					list.setVisibility(VISIBLE);
-					for (ForumPostHeader h : headers) {
-						ForumItem item = new ForumItem(h);
-						byte[] body = bodyCache.get(h.getId());
-						if (body == null) loadPostBody(h);
-						else item.setBody(body);
-						adapter.add(item);
-					}
-					adapter.sort(ForumItemComparator.INSTANCE);
-					// Scroll to the bottom
-					list.setSelection(adapter.getCount() - 1);
-				}
-			}
-		});
-	}
-
-	private void loadPostBody(final ForumPostHeader h) {
-		runOnDbThread(new Runnable() {
-			public void run() {
-				try {
-					long now = System.currentTimeMillis();
-					byte[] body = forumManager.getPostBody(h.getId());
-					long duration = System.currentTimeMillis() - now;
-					if (LOG.isLoggable(INFO))
-						LOG.info("Loading message took " + duration + " ms");
-					displayPost(h.getId(), body);
-				} catch (NoSuchMessageException e) {
-					// The item will be removed when we get the event
-				} catch (DbException e) {
-					if (LOG.isLoggable(WARNING))
-						LOG.log(WARNING, e.toString(), e);
-				}
-			}
-		});
-	}
-
-	private void displayPost(final MessageId m, final byte[] body) {
-		runOnUiThread(new Runnable() {
-			public void run() {
-				bodyCache.put(m, body);
-				int count = adapter.getCount();
-				for (int i = 0; i < count; i++) {
-					ForumItem item = adapter.getItem(i);
-					if (item.getHeader().getId().equals(m)) {
-						item.setBody(body);
-						adapter.notifyDataSetChanged();
-						// Scroll to the bottom
-						list.setSelection(count - 1);
-						return;
-					}
-				}
-			}
-		});
-	}
-
-	@Override
-	protected void onActivityResult(int request, int result, Intent data) {
-		super.onActivityResult(request, result, data);
-		if (request == REQUEST_READ && result == RESULT_PREV_NEXT) {
-			int position = data.getIntExtra("briar.POSITION", -1);
-			if (position >= 0 && position < adapter.getCount())
-				displayPost(position);
-		}
-		else if (request == REQUEST_FORUM_SHARED && result == RESULT_OK) {
-			Snackbar s = Snackbar.make(list, R.string.forum_shared_snackbar,
-					LENGTH_LONG);
-			s.getView().setBackgroundResource(R.color.briar_primary);
-			s.show();
-		}
-	}
-
-	@Override
-	public void onPause() {
-		super.onPause();
-		eventBus.removeListener(this);
-		notificationManager.unblockNotification(groupId);
-		if (isFinishing()) markPostsRead();
-	}
-
-	private void markPostsRead() {
-		List<MessageId> unread = new ArrayList<>();
-		int count = adapter.getCount();
-		for (int i = 0; i < count; i++) {
-			ForumPostHeader h = adapter.getItem(i).getHeader();
-			if (!h.isRead()) unread.add(h.getId());
-		}
-		if (unread.isEmpty()) return;
-		if (LOG.isLoggable(INFO))
-			LOG.info("Marking " + unread.size() + " posts read");
-		markPostsRead(Collections.unmodifiableList(unread));
-	}
-
-	private void markPostsRead(final Collection<MessageId> unread) {
-		runOnDbThread(new Runnable() {
-			public void run() {
-				try {
-					long now = System.currentTimeMillis();
-					for (MessageId m : unread)
-						forumManager.setReadFlag(m, true);
-					long duration = System.currentTimeMillis() - now;
-					if (LOG.isLoggable(INFO))
-						LOG.info("Marking read took " + duration + " ms");
-				} catch (DbException e) {
-					if (LOG.isLoggable(WARNING))
-						LOG.log(WARNING, e.toString(), e);
-				}
-			}
-		});
-	}
-
-	public void eventOccurred(Event e) {
-		if (e instanceof MessageValidatedEvent) {
-			MessageValidatedEvent m = (MessageValidatedEvent) e;
-			if (m.isValid() && m.getMessage().getGroupId().equals(groupId)) {
-				LOG.info("Message added, reloading");
-				loadHeaders();
-			}
-		} else if (e instanceof GroupRemovedEvent) {
-			GroupRemovedEvent s = (GroupRemovedEvent) e;
-			if (s.getGroup().getId().equals(groupId)) {
-				LOG.info("Forum removed");
-				finishOnUiThread();
-			}
-		}
-	}
-
-	private long getMinTimestampForNewPost() {
-		// Don't use an earlier timestamp than the newest post
-		long timestamp = 0;
-		int count = adapter.getCount();
-		for (int i = 0; i < count; i++) {
-			long t = adapter.getItem(i).getHeader().getTimestamp();
-			if (t > timestamp) timestamp = t;
-		}
-		return timestamp + 1;
-	}
-
-	public void onItemClick(AdapterView<?> parent, View view, int position,
-			long id) {
-		displayPost(position);
-	}
-
-	private void displayPost(int position) {
-		ForumPostHeader header = adapter.getItem(position).getHeader();
-		Intent i = new Intent(this, ReadForumPostActivity.class);
-		i.putExtra(GROUP_ID, groupId.getBytes());
-		i.putExtra(FORUM_NAME, forum.getName());
-		i.putExtra("briar.MESSAGE_ID", header.getId().getBytes());
-		Author author = header.getAuthor();
-		if (author != null) {
-			i.putExtra("briar.AUTHOR_NAME", author.getName());
-			i.putExtra("briar.AUTHOR_ID", author.getId().getBytes());
-		}
-		i.putExtra("briar.AUTHOR_STATUS", header.getAuthorStatus().name());
-		i.putExtra("briar.CONTENT_TYPE", header.getContentType());
-		i.putExtra("briar.TIMESTAMP", header.getTimestamp());
-		i.putExtra(MIN_TIMESTAMP, getMinTimestampForNewPost());
-		i.putExtra("briar.POSITION", position);
-		startActivityForResult(i, REQUEST_READ);
-	}
-
-	private void showUnsubscribeDialog() {
-		DialogInterface.OnClickListener okListener =
-				new DialogInterface.OnClickListener() {
-					@Override
-					public void onClick(DialogInterface dialog, int which) {
-						unsubscribe(forum);
-						Toast.makeText(ForumActivity.this,
-								R.string.forum_left_toast, LENGTH_SHORT)
-								.show();
-					}
-				};
-		AlertDialog.Builder builder =
-				new AlertDialog.Builder(ForumActivity.this,
-						R.style.BriarDialogTheme);
-		builder.setTitle(getString(R.string.dialog_title_leave_forum));
-		builder.setMessage(getString(R.string.dialog_message_leave_forum));
-		builder.setPositiveButton(R.string.dialog_button_leave, okListener);
-		builder.setNegativeButton(android.R.string.cancel, null);
-		builder.show();
-	}
-
-	private void unsubscribe(final Forum f) {
-		runOnDbThread(new Runnable() {
-			public void run() {
-				try {
-					long now = System.currentTimeMillis();
-					forumManager.removeForum(f);
-					long duration = System.currentTimeMillis() - now;
-					if (LOG.isLoggable(INFO))
-						LOG.info("Removing forum took " + duration + " ms");
-				} catch (DbException e) {
-					if (LOG.isLoggable(WARNING))
-						LOG.log(WARNING, e.toString(), e);
-				}
-			}
-		});
-	}
-
-}
diff --git a/briar-android/src/org/briarproject/android/forum/ForumAdapter.java b/briar-android/src/org/briarproject/android/forum/ForumAdapter.java
deleted file mode 100644
index df2e4e425fe795756948ed1dc03f4cfd2a64d2b9..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/forum/ForumAdapter.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package org.briarproject.android.forum;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.text.format.DateUtils;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.ImageButton;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import org.briarproject.R;
-import org.briarproject.android.util.AuthorView;
-import org.briarproject.android.util.LayoutUtils;
-import org.briarproject.api.forum.ForumPostHeader;
-import org.briarproject.api.identity.Author;
-import org.briarproject.util.StringUtils;
-
-import java.util.ArrayList;
-
-import static android.view.Gravity.CENTER_HORIZONTAL;
-import static android.view.Gravity.CENTER_VERTICAL;
-import static android.widget.LinearLayout.HORIZONTAL;
-import static android.widget.LinearLayout.VERTICAL;
-import static org.briarproject.android.util.CommonLayoutParams.WRAP_WRAP_1;
-
-class ForumAdapter extends ArrayAdapter<ForumItem> {
-
-	private final int pad;
-
-	ForumAdapter(Context ctx) {
-		super(ctx, android.R.layout.simple_expandable_list_item_1,
-				new ArrayList<ForumItem>());
-		pad = LayoutUtils.getPadding(ctx);
-	}
-
-	@Override
-	public View getView(int position, View convertView, ViewGroup parent) {
-		ForumItem item = getItem(position);
-		ForumPostHeader header = item.getHeader();
-		Context ctx = getContext();
-		Resources res = ctx.getResources();
-
-		LinearLayout layout = new LinearLayout(ctx);
-		layout.setOrientation(VERTICAL);
-		layout.setGravity(CENTER_HORIZONTAL);
-		if (!header.isRead())
-			layout.setBackgroundColor(res.getColor(R.color.unread_background));
-
-		LinearLayout headerLayout = new LinearLayout(ctx);
-		headerLayout.setOrientation(HORIZONTAL);
-		headerLayout.setGravity(CENTER_VERTICAL);
-
-		AuthorView authorView = new AuthorView(ctx);
-		authorView.setLayoutParams(WRAP_WRAP_1);
-		authorView.setPadding(0, pad, pad, pad);
-		Author author = header.getAuthor();
-		if (author == null) {
-			authorView.init(null, null, header.getAuthorStatus());
-		} else {
-			authorView.init(author.getName(), author.getId(),
-					header.getAuthorStatus());
-		}
-		headerLayout.addView(authorView);
-
-		TextView date = new TextView(ctx);
-		date.setPadding(pad, pad, pad, pad);
-		long timestamp = header.getTimestamp();
-		date.setText(DateUtils.getRelativeTimeSpanString(ctx, timestamp));
-		headerLayout.addView(date);
-		layout.addView(headerLayout);
-
-		if (item.getBody() == null) {
-			TextView ellipsis = new TextView(ctx);
-			ellipsis.setPadding(pad, 0, pad, pad);
-			ellipsis.setText("\u2026");
-			layout.addView(ellipsis);
-		} else if (header.getContentType().equals("text/plain")) {
-			TextView text = new TextView(ctx);
-			text.setPadding(pad, 0, pad, pad);
-			text.setText(StringUtils.fromUtf8(item.getBody()));
-			layout.addView(text);
-		} else {
-			ImageButton attachment = new ImageButton(ctx);
-			attachment.setPadding(pad, 0, pad, pad);
-			attachment.setImageResource(R.drawable.content_attachment);
-			layout.addView(attachment);
-		}
-
-		return layout;
-	}
-}
\ No newline at end of file
diff --git a/briar-android/src/org/briarproject/android/forum/ForumContacts.java b/briar-android/src/org/briarproject/android/forum/ForumContacts.java
deleted file mode 100644
index ce24fc86053d44987cc5fb710f37a90c65b2ad27..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/forum/ForumContacts.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.briarproject.android.forum;
-
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.forum.Forum;
-
-import java.util.Collection;
-
-class ForumContacts {
-
-	private final Forum forum;
-	private final Collection<Contact> contacts;
-
-	ForumContacts(Forum forum, Collection<Contact> contacts) {
-		this.forum = forum;
-		this.contacts = contacts;
-	}
-
-	Forum getForum() {
-		return forum;
-	}
-
-	Collection<Contact> getContacts() {
-		return contacts;
-	}
-}
diff --git a/briar-android/src/org/briarproject/android/forum/ForumItem.java b/briar-android/src/org/briarproject/android/forum/ForumItem.java
deleted file mode 100644
index 92ae9320bf7ec48eeeb6b77c6a00ce51bc17ab76..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/forum/ForumItem.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.briarproject.android.forum;
-
-import org.briarproject.api.forum.ForumPostHeader;
-
-// This class is not thread-safe
-class ForumItem {
-
-	private final ForumPostHeader header;
-	private byte[] body;
-
-	ForumItem(ForumPostHeader header) {
-		this.header = header;
-		body = null;
-	}
-
-	ForumPostHeader getHeader() {
-		return header;
-	}
-
-	byte[] getBody() {
-		return body;
-	}
-
-	void setBody(byte[] body) {
-		this.body = body;
-	}
-}
diff --git a/briar-android/src/org/briarproject/android/forum/ForumItemComparator.java b/briar-android/src/org/briarproject/android/forum/ForumItemComparator.java
deleted file mode 100644
index d482b979b7d8e95caec1c15c61ce9c89d5f77693..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/forum/ForumItemComparator.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.briarproject.android.forum;
-
-import java.util.Comparator;
-
-class ForumItemComparator implements Comparator<ForumItem> {
-
-	static final ForumItemComparator INSTANCE = new ForumItemComparator();
-
-	public int compare(ForumItem a, ForumItem b) {
-		// The oldest message comes first
-		long aTime = a.getHeader().getTimestamp();
-		long bTime = b.getHeader().getTimestamp();
-		if (aTime < bTime) return -1;
-		if (aTime > bTime) return 1;
-		return 0;
-	}
-}
diff --git a/briar-android/src/org/briarproject/android/forum/ForumListAdapter.java b/briar-android/src/org/briarproject/android/forum/ForumListAdapter.java
deleted file mode 100644
index de53aab8dafb0520d9be2fee004cec26745d7ff1..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/forum/ForumListAdapter.java
+++ /dev/null
@@ -1,197 +0,0 @@
-package org.briarproject.android.forum;
-
-import android.content.Context;
-import android.content.Intent;
-import android.support.annotation.Nullable;
-import android.support.v4.content.ContextCompat;
-import android.support.v7.util.SortedList;
-import android.support.v7.widget.RecyclerView;
-import android.text.format.DateUtils;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
-
-import org.briarproject.R;
-import org.briarproject.android.util.TextAvatarView;
-import org.briarproject.api.forum.Forum;
-import org.briarproject.api.sync.GroupId;
-
-import java.util.Collection;
-
-import static org.briarproject.android.BriarActivity.GROUP_ID;
-import static org.briarproject.android.forum.ForumActivity.FORUM_NAME;
-
-public class ForumListAdapter extends
-		RecyclerView.Adapter<ForumListAdapter.ForumViewHolder> {
-
-	private SortedList<ForumListItem> forums = new SortedList<>(
-			ForumListItem.class, new SortedList.Callback<ForumListItem>() {
-
-		@Override
-		public int compare(ForumListItem a, ForumListItem b) {
-			if (a == b) return 0;
-			// The forum with the newest message comes first
-			long aTime = a.getTimestamp(), bTime = b.getTimestamp();
-			if (aTime > bTime) return -1;
-			if (aTime < bTime) return 1;
-			// Break ties by forum name
-			String aName = a.getForum().getName();
-			String bName = b.getForum().getName();
-			return String.CASE_INSENSITIVE_ORDER.compare(aName, bName);
-		}
-
-		@Override
-		public void onInserted(int position, int count) {
-			notifyItemRangeInserted(position, count);
-		}
-
-		@Override
-		public void onRemoved(int position, int count) {
-			notifyItemRangeRemoved(position, count);
-		}
-
-		@Override
-		public void onMoved(int fromPosition, int toPosition) {
-			notifyItemMoved(fromPosition, toPosition);
-		}
-
-		@Override
-		public void onChanged(int position, int count) {
-			notifyItemRangeChanged(position, count);
-		}
-
-		@Override
-		public boolean areContentsTheSame(ForumListItem a, ForumListItem b) {
-			return a.getForum().equals(b.getForum()) &&
-					a.getTimestamp() == b.getTimestamp() &&
-					a.getUnreadCount() == b.getUnreadCount();
-		}
-
-		@Override
-		public boolean areItemsTheSame(ForumListItem a, ForumListItem b) {
-			return a.getForum().equals(b.getForum());
-		}
-	});
-
-	private final Context ctx;
-
-	public ForumListAdapter(Context ctx) {
-		this.ctx = ctx;
-	}
-
-	@Override
-	public ForumViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
-		View v = LayoutInflater.from(ctx).inflate(
-				R.layout.list_item_forum, parent, false);
-		return new ForumViewHolder(v);
-	}
-
-	@Override
-	public void onBindViewHolder(ForumViewHolder ui, int position) {
-		final ForumListItem item = getItem(position);
-
-		// Avatar
-		ui.avatar.setText(item.getForum().getName().substring(0, 1));
-		ui.avatar.setBackgroundBytes(item.getForum().getId().getBytes());
-
-		// Forum Name
-		ui.name.setText(item.getForum().getName());
-
-		// Unread Count
-		int unread = item.getUnreadCount();
-		if (unread > 0) {
-			ui.unread.setText(ctx.getResources()
-					.getQuantityString(R.plurals.unread_posts, unread, unread));
-			ui.unread.setTextColor(
-					ContextCompat.getColor(ctx, R.color.briar_button_positive));
-		} else {
-			ui.unread.setText(ctx.getString(R.string.no_unread_posts));
-			ui.unread.setTextColor(
-					ContextCompat.getColor(ctx, R.color.briar_text_secondary));
-		}
-
-		// Date or "No Posts"
-		if (item.isEmpty()) {
-			ui.date.setVisibility(View.GONE);
-		} else {
-			long timestamp = item.getTimestamp();
-			ui.date.setText(
-					DateUtils.getRelativeTimeSpanString(ctx, timestamp));
-			ui.date.setVisibility(View.VISIBLE);
-		}
-
-		// Open Forum on Click
-		ui.layout.setOnClickListener(new View.OnClickListener() {
-			@Override
-			public void onClick(View v) {
-				Intent i = new Intent(ctx, ForumActivity.class);
-				Forum f = item.getForum();
-				i.putExtra(GROUP_ID, f.getId().getBytes());
-				i.putExtra(FORUM_NAME, f.getName());
-				ctx.startActivity(i);
-			}
-		});
-	}
-
-	@Override
-	public int getItemCount() {
-		return forums.size();
-	}
-
-	public ForumListItem getItem(int position) {
-		return forums.get(position);
-	}
-
-	@Nullable
-	public ForumListItem getItem(GroupId g) {
-		for (int i = 0; i < forums.size(); i++) {
-			ForumListItem item = forums.get(i);
-			if (item.getForum().getGroup().getId().equals(g)) {
-				return item;
-			}
-		}
-		return null;
-	}
-
-	public void addAll(Collection<ForumListItem> items) {
-		forums.addAll(items);
-	}
-
-	public void updateItem(ForumListItem item) {
-		ForumListItem oldItem = getItem(item.getForum().getGroup().getId());
-		int position = forums.indexOf(oldItem);
-		forums.updateItemAt(position, item);
-	}
-
-	public void remove(ForumListItem item) {
-		forums.remove(item);
-	}
-
-	public void clear() {
-		forums.clear();
-	}
-
-	public boolean isEmpty() {
-		return forums.size() == 0;
-	}
-
-	protected static class ForumViewHolder extends RecyclerView.ViewHolder {
-
-		private final ViewGroup layout;
-		private final TextAvatarView avatar;
-		private final TextView name;
-		private final TextView unread;
-		private final TextView date;
-
-		public ForumViewHolder(View v) {
-			super(v);
-
-			layout = (ViewGroup) v;
-			avatar = (TextAvatarView) v.findViewById(R.id.avatarView);
-			name = (TextView) v.findViewById(R.id.forumNameView);
-			unread = (TextView) v.findViewById(R.id.unreadView);
-			date = (TextView) v.findViewById(R.id.dateView);
-		}
-	}
-}
diff --git a/briar-android/src/org/briarproject/android/forum/ForumListFragment.java b/briar-android/src/org/briarproject/android/forum/ForumListFragment.java
deleted file mode 100644
index e6f0f6a26685e7feee22c25e8be0a15a322dbe2a..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/forum/ForumListFragment.java
+++ /dev/null
@@ -1,286 +0,0 @@
-package org.briarproject.android.forum;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.design.widget.Snackbar;
-import android.support.v4.content.ContextCompat;
-import android.support.v7.widget.LinearLayoutManager;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.AndroidComponent;
-import org.briarproject.android.fragment.BaseEventFragment;
-import org.briarproject.android.util.BriarRecyclerView;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.NoSuchGroupException;
-import org.briarproject.api.event.ContactRemovedEvent;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.ForumInvitationReceivedEvent;
-import org.briarproject.api.event.GroupAddedEvent;
-import org.briarproject.api.event.GroupRemovedEvent;
-import org.briarproject.api.event.MessageValidatedEvent;
-import org.briarproject.api.forum.Forum;
-import org.briarproject.api.forum.ForumManager;
-import org.briarproject.api.forum.ForumPostHeader;
-import org.briarproject.api.forum.ForumSharingManager;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.GroupId;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.logging.Logger;
-
-import javax.inject.Inject;
-
-import static android.support.design.widget.Snackbar.LENGTH_INDEFINITE;
-import static java.util.logging.Level.INFO;
-import static java.util.logging.Level.WARNING;
-
-public class ForumListFragment extends BaseEventFragment implements
-		View.OnClickListener {
-
-	public final static String TAG = "ForumListFragment";
-
-	private static final Logger LOG =
-			Logger.getLogger(ForumListFragment.class.getName());
-
-
-	private BriarRecyclerView list;
-	private ForumListAdapter adapter;
-	private Snackbar snackbar;
-
-	// Fields that are accessed from background threads must be volatile
-	@Inject protected volatile ForumManager forumManager;
-	@Inject protected volatile ForumSharingManager forumSharingManager;
-
-	@Inject
-	public ForumListFragment() {
-
-	}
-
-	@Nullable
-	@Override
-	public View onCreateView(LayoutInflater inflater, ViewGroup container,
-			Bundle savedInstanceState) {
-
-		setHasOptionsMenu(true);
-
-		View contentView =
-				inflater.inflate(R.layout.fragment_forum_list, container,
-						false);
-
-		adapter = new ForumListAdapter(getActivity());
-
-		list = (BriarRecyclerView) contentView.findViewById(R.id.forumList);
-		list.setLayoutManager(new LinearLayoutManager(getActivity()));
-		list.setAdapter(adapter);
-		list.setEmptyText(getString(R.string.no_forums));
-
-		snackbar = Snackbar.make(list, "", LENGTH_INDEFINITE);
-		snackbar.getView().setBackgroundResource(R.color.briar_primary);
-		snackbar.setAction(R.string.show_forums, this);
-		snackbar.setActionTextColor(ContextCompat
-				.getColor(getContext(), R.color.briar_button_positive));
-
-		return contentView;
-	}
-
-	@Override
-	public String getUniqueTag() {
-		return TAG;
-	}
-
-	@Override
-	public void onResume() {
-		super.onResume();
-
-		loadForumHeaders();
-		loadAvailableForums();
-	}
-
-	@Override
-	public void onPause() {
-		super.onPause();
-
-		adapter.clear();
-	}
-
-	@Override
-	public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
-		inflater.inflate(R.menu.forum_list_actions, menu);
-		super.onCreateOptionsMenu(menu, inflater);
-	}
-
-	@Override
-	public boolean onOptionsItemSelected(final MenuItem item) {
-		// Handle presses on the action bar items
-		switch (item.getItemId()) {
-			case R.id.action_create_forum:
-				Intent intent =
-						new Intent(getContext(), CreateForumActivity.class);
-				startActivity(intent);
-				return true;
-			default:
-				return super.onOptionsItemSelected(item);
-		}
-	}
-
-	private void loadForumHeaders() {
-		listener.runOnDbThread(new Runnable() {
-			@Override
-			public void run() {
-				try {
-					// load forums
-					long now = System.currentTimeMillis();
-					Collection<ForumListItem> forums = new ArrayList<>();
-					for (Forum f : forumManager.getForums()) {
-						try {
-							Collection<ForumPostHeader> headers =
-									forumManager.getPostHeaders(f.getId());
-							forums.add(new ForumListItem(f, headers));
-						} catch (NoSuchGroupException e) {
-							// Continue
-						}
-					}
-					displayForumHeaders(forums);
-					long duration = System.currentTimeMillis() - now;
-					if (LOG.isLoggable(INFO))
-						LOG.info("Full load took " + duration + " ms");
-				} catch (DbException e) {
-					if (LOG.isLoggable(WARNING))
-						LOG.log(WARNING, e.toString(), e);
-				}
-			}
-		});
-	}
-
-	private void displayForumHeaders(final Collection<ForumListItem> forums) {
-		listener.runOnUiThread(new Runnable() {
-			@Override
-			public void run() {
-				if (forums.size() > 0) adapter.addAll(forums);
-				else list.showData();
-			}
-		});
-	}
-
-	private void loadAvailableForums() {
-		listener.runOnDbThread(new Runnable() {
-			@Override
-			public void run() {
-				try {
-					long now = System.currentTimeMillis();
-					int available =
-							forumSharingManager.getAvailableForums().size();
-					long duration = System.currentTimeMillis() - now;
-					if (LOG.isLoggable(INFO))
-						LOG.info("Loading available took " + duration + " ms");
-					displayAvailableForums(available);
-				} catch (DbException e) {
-					if (LOG.isLoggable(WARNING))
-						LOG.log(WARNING, e.toString(), e);
-				}
-			}
-		});
-	}
-
-	private void displayAvailableForums(final int availableCount) {
-		listener.runOnUiThread(new Runnable() {
-			@Override
-			public void run() {
-				if (availableCount == 0) {
-					snackbar.dismiss();
-				} else {
-					snackbar.show();
-					snackbar.setText(getResources().getQuantityString(
-							R.plurals.forums_shared, availableCount,
-							availableCount));
-				}
-			}
-		});
-	}
-
-	@Override
-	public void eventOccurred(Event e) {
-		if (e instanceof ContactRemovedEvent) {
-			LOG.info("Contact removed, reloading available forums");
-			loadAvailableForums();
-		} else if (e instanceof GroupAddedEvent) {
-			GroupAddedEvent g = (GroupAddedEvent) e;
-			if (g.getGroup().getClientId().equals(forumManager.getClientId())) {
-				LOG.info("Forum added, reloading forums");
-				loadForumHeaders();
-			}
-		} else if (e instanceof GroupRemovedEvent) {
-			GroupRemovedEvent g = (GroupRemovedEvent) e;
-			if (g.getGroup().getClientId().equals(forumManager.getClientId())) {
-				LOG.info("Forum removed, removing from list");
-				removeForum(g.getGroup().getId());
-			}
-		} else if (e instanceof MessageValidatedEvent) {
-			MessageValidatedEvent m = (MessageValidatedEvent) e;
-			if (m.isValid()) {
-				ClientId c = m.getClientId();
-				if (c.equals(forumManager.getClientId())) {
-					LOG.info("Forum post added, reloading");
-					loadForumHeaders(m.getMessage().getGroupId());
-				}
-			}
-		} else if (e instanceof ForumInvitationReceivedEvent) {
-			loadAvailableForums();
-		}
-	}
-
-	private void loadForumHeaders(final GroupId g) {
-		listener.runOnDbThread(new Runnable() {
-			@Override
-			public void run() {
-				try {
-					long now = System.currentTimeMillis();
-					Forum f = forumManager.getForum(g);
-					Collection<ForumPostHeader> headers =
-							forumManager.getPostHeaders(g);
-					long duration = System.currentTimeMillis() - now;
-					if (LOG.isLoggable(INFO))
-						LOG.info("Partial load took " + duration + " ms");
-					updateForum(new ForumListItem(f, headers));
-				} catch (DbException e) {
-					if (LOG.isLoggable(WARNING))
-						LOG.log(WARNING, e.toString(), e);
-				}
-			}
-		});
-	}
-
-	private void updateForum(final ForumListItem item) {
-		listener.runOnUiThread(new Runnable() {
-			@Override
-			public void run() {
-				adapter.updateItem(item);
-			}
-		});
-	}
-
-	private void removeForum(final GroupId g) {
-		listener.runOnUiThread(new Runnable() {
-			@Override
-			public void run() {
-				ForumListItem item = adapter.getItem(g);
-				if (item != null) adapter.remove(item);
-			}
-		});
-	}
-
-	@Override
-	public void onClick(View view) {
-		// snackbar click
-		startActivity(new Intent(getContext(), AvailableForumsActivity.class));
-	}
-}
diff --git a/briar-android/src/org/briarproject/android/forum/ForumListItem.java b/briar-android/src/org/briarproject/android/forum/ForumListItem.java
deleted file mode 100644
index f6e55a8a1129f76dcecf4e2aa7ae84abada76014..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/forum/ForumListItem.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package org.briarproject.android.forum;
-
-import org.briarproject.api.forum.Forum;
-import org.briarproject.api.forum.ForumPostHeader;
-
-import java.util.Collection;
-
-class ForumListItem {
-
-	private final Forum forum;
-	private final boolean empty;
-	private final long timestamp;
-	private final int unread;
-
-	ForumListItem(Forum forum, Collection<ForumPostHeader> headers) {
-		this.forum = forum;
-		empty = headers.isEmpty();
-		if (empty) {
-			timestamp = 0;
-			unread = 0;
-		} else {
-			ForumPostHeader newest = null;
-			long timestamp = -1;
-			int unread = 0;
-			for (ForumPostHeader h : headers) {
-				if (h.getTimestamp() > timestamp) {
-					timestamp = h.getTimestamp();
-					newest = h;
-				}
-				if (!h.isRead()) unread++;
-			}
-			this.timestamp = newest.getTimestamp();
-			this.unread = unread;
-		}
-	}
-
-	Forum getForum() {
-		return forum;
-	}
-
-	boolean isEmpty() {
-		return empty;
-	}
-
-	long getTimestamp() {
-		return timestamp;
-	}
-
-	int getUnreadCount() {
-		return unread;
-	}
-}
diff --git a/briar-android/src/org/briarproject/android/forum/ReadForumPostActivity.java b/briar-android/src/org/briarproject/android/forum/ReadForumPostActivity.java
deleted file mode 100644
index cfc80ace2a4a4363327a4c88b3115bdc6cecbf64..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/forum/ReadForumPostActivity.java
+++ /dev/null
@@ -1,249 +0,0 @@
-package org.briarproject.android.forum;
-
-import android.content.Intent;
-import android.content.res.Resources;
-import android.os.Bundle;
-import android.text.format.DateUtils;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.ImageButton;
-import android.widget.LinearLayout;
-import android.widget.ScrollView;
-import android.widget.TextView;
-
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.AndroidComponent;
-import org.briarproject.android.BriarActivity;
-import org.briarproject.android.util.AuthorView;
-import org.briarproject.android.util.ElasticHorizontalSpace;
-import org.briarproject.android.util.HorizontalBorder;
-import org.briarproject.android.util.LayoutUtils;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.NoSuchMessageException;
-import org.briarproject.api.forum.ForumManager;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.util.StringUtils;
-
-import java.util.logging.Logger;
-
-import javax.inject.Inject;
-
-import static android.view.Gravity.CENTER;
-import static android.view.Gravity.CENTER_VERTICAL;
-import static android.widget.LinearLayout.HORIZONTAL;
-import static android.widget.LinearLayout.VERTICAL;
-import static java.util.logging.Level.INFO;
-import static java.util.logging.Level.WARNING;
-import static org.briarproject.android.forum.ForumActivity.FORUM_NAME;
-import static org.briarproject.android.forum.ForumActivity.MIN_TIMESTAMP;
-import static org.briarproject.android.util.CommonLayoutParams.MATCH_MATCH;
-import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP;
-import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP_1;
-import static org.briarproject.android.util.CommonLayoutParams.WRAP_WRAP_1;
-
-public class ReadForumPostActivity extends BriarActivity
-implements OnClickListener {
-
-	static final int RESULT_REPLY = RESULT_FIRST_USER;
-	static final int RESULT_PREV_NEXT = RESULT_FIRST_USER + 1;
-
-	private static final Logger LOG =
-			Logger.getLogger(ReadForumPostActivity.class.getName());
-
-	private GroupId groupId = null;
-	private String forumName = null;
-	private long minTimestamp = -1;
-	private ImageButton prevButton = null, nextButton = null;
-	private ImageButton replyButton = null;
-	private TextView content = null;
-	private int position = -1;
-
-	// Fields that are accessed from background threads must be volatile
-	@Inject protected volatile ForumManager forumManager;
-	private volatile MessageId messageId = null;
-
-	@Override
-	public void onCreate(Bundle state) {
-		super.onCreate(state);
-
-		Intent i = getIntent();
-		byte[] b = i.getByteArrayExtra(GROUP_ID);
-		if (b == null) throw new IllegalStateException();
-		groupId = new GroupId(b);
-		forumName = i.getStringExtra(FORUM_NAME);
-		if (forumName == null) throw new IllegalStateException();
-		setTitle(forumName);
-		b = i.getByteArrayExtra("briar.MESSAGE_ID");
-		if (b == null) throw new IllegalStateException();
-		messageId = new MessageId(b);
-		String contentType = i.getStringExtra("briar.CONTENT_TYPE");
-		if (contentType == null) throw new IllegalStateException();
-		long timestamp = i.getLongExtra("briar.TIMESTAMP", -1);
-		if (timestamp == -1) throw new IllegalStateException();
-		minTimestamp = i.getLongExtra(MIN_TIMESTAMP, -1);
-		if (minTimestamp == -1) throw new IllegalStateException();
-		position = i.getIntExtra("briar.POSITION", -1);
-		if (position == -1) throw new IllegalStateException();
-		String authorName = i.getStringExtra("briar.AUTHOR_NAME");
-		AuthorId authorId = null;
-		b = i.getByteArrayExtra("briar.AUTHOR_ID");
-		if (b != null) authorId = new AuthorId(b);
-		String s = i.getStringExtra("briar.AUTHOR_STATUS");
-		if (s == null) throw new IllegalStateException();
-		Author.Status authorStatus = Author.Status.valueOf(s);
-
-		LinearLayout layout = new LinearLayout(this);
-		layout.setLayoutParams(MATCH_MATCH);
-		layout.setOrientation(VERTICAL);
-
-		ScrollView scrollView = new ScrollView(this);
-		scrollView.setLayoutParams(MATCH_WRAP_1);
-
-		LinearLayout message = new LinearLayout(this);
-		message.setOrientation(VERTICAL);
-
-		LinearLayout header = new LinearLayout(this);
-		header.setLayoutParams(MATCH_WRAP);
-		header.setOrientation(HORIZONTAL);
-		header.setGravity(CENTER_VERTICAL);
-
-		int pad = LayoutUtils.getPadding(this);
-
-		AuthorView authorView = new AuthorView(this);
-		authorView.setPadding(0, pad, pad, pad);
-		authorView.setLayoutParams(WRAP_WRAP_1);
-		authorView.init(authorName, authorId, authorStatus);
-		header.addView(authorView);
-
-		TextView date = new TextView(this);
-		date.setPadding(pad, pad, pad, pad);
-		date.setText(DateUtils.getRelativeTimeSpanString(this, timestamp));
-		header.addView(date);
-		message.addView(header);
-
-		if (contentType.equals("text/plain")) {
-			// Load and display the message body
-			content = new TextView(this);
-			content.setPadding(pad, 0, pad, pad);
-			message.addView(content);
-			loadPostBody();
-		}
-		scrollView.addView(message);
-		layout.addView(scrollView);
-
-		layout.addView(new HorizontalBorder(this));
-
-		LinearLayout footer = new LinearLayout(this);
-		footer.setLayoutParams(MATCH_WRAP);
-		footer.setOrientation(HORIZONTAL);
-		footer.setGravity(CENTER);
-		Resources res = getResources();
-		footer.setBackgroundColor(res.getColor(R.color.button_bar_background));
-
-		prevButton = new ImageButton(this);
-		prevButton.setBackgroundResource(0);
-		prevButton.setImageResource(R.drawable.navigation_previous_item);
-		prevButton.setOnClickListener(this);
-		footer.addView(prevButton);
-		footer.addView(new ElasticHorizontalSpace(this));
-
-		nextButton = new ImageButton(this);
-		nextButton.setBackgroundResource(0);
-		nextButton.setImageResource(R.drawable.navigation_next_item);
-		nextButton.setOnClickListener(this);
-		footer.addView(nextButton);
-		footer.addView(new ElasticHorizontalSpace(this));
-
-		replyButton = new ImageButton(this);
-		replyButton.setBackgroundResource(0);
-		replyButton.setImageResource(R.drawable.social_reply_all);
-		replyButton.setOnClickListener(this);
-		footer.addView(replyButton);
-		layout.addView(footer);
-
-		setContentView(layout);
-	}
-
-	@Override
-	public void injectActivity(ActivityComponent component) {
-		component.inject(this);
-	}
-
-	@Override
-	public void onPause() {
-		super.onPause();
-		if (isFinishing()) markPostRead();
-	}
-
-	private void markPostRead() {
-		runOnDbThread(new Runnable() {
-			public void run() {
-				try {
-					long now = System.currentTimeMillis();
-					forumManager.setReadFlag(messageId, true);
-					long duration = System.currentTimeMillis() - now;
-					if (LOG.isLoggable(INFO))
-						LOG.info("Marking read took " + duration + " ms");
-				} catch (DbException e) {
-					if (LOG.isLoggable(WARNING))
-						LOG.log(WARNING, e.toString(), e);
-				}
-			}
-		});
-	}
-
-	private void loadPostBody() {
-		runOnDbThread(new Runnable() {
-			public void run() {
-				try {
-					long now = System.currentTimeMillis();
-					byte[] body = forumManager.getPostBody(messageId);
-					long duration = System.currentTimeMillis() - now;
-					if (LOG.isLoggable(INFO))
-						LOG.info("Loading post took " + duration + " ms");
-					displayPostBody(StringUtils.fromUtf8(body));
-				} catch (NoSuchMessageException e) {
-					finishOnUiThread();
-				} catch (DbException e) {
-					if (LOG.isLoggable(WARNING))
-						LOG.log(WARNING, e.toString(), e);
-				}
-			}
-		});
-	}
-
-	private void displayPostBody(final String body) {
-		runOnUiThread(new Runnable() {
-			public void run() {
-				content.setText(body);
-			}
-		});
-	}
-
-	public void onClick(View view) {
-		if (view == prevButton) {
-			Intent i = new Intent();
-			i.putExtra("briar.POSITION", position - 1);
-			setResult(RESULT_PREV_NEXT, i);
-			finish();
-		} else if (view == nextButton) {
-			Intent i = new Intent();
-			i.putExtra("briar.POSITION", position + 1);
-			setResult(RESULT_PREV_NEXT, i);
-			finish();
-		} else if (view == replyButton) {
-			Intent i = new Intent(this, WriteForumPostActivity.class);
-			i.putExtra(GROUP_ID, groupId.getBytes());
-			i.putExtra(FORUM_NAME, forumName);
-			i.putExtra("briar.PARENT_ID", messageId.getBytes());
-			i.putExtra(MIN_TIMESTAMP, minTimestamp);
-			startActivity(i);
-			setResult(RESULT_REPLY);
-			finish();
-		}
-	}
-}
diff --git a/briar-android/src/org/briarproject/android/forum/SelectableContactListItem.java b/briar-android/src/org/briarproject/android/forum/SelectableContactListItem.java
deleted file mode 100644
index fa5ad2284f0852d98ec3460f87c5018f72d8e06b..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/forum/SelectableContactListItem.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.briarproject.android.forum;
-
-import org.briarproject.android.contact.ContactListItem;
-import org.briarproject.android.contact.ConversationItem;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.sync.GroupId;
-
-import java.util.Collections;
-
-// This class is not thread-safe
-public class SelectableContactListItem extends ContactListItem {
-
-	private boolean selected, disabled;
-
-	public SelectableContactListItem(Contact contact, LocalAuthor localAuthor,
-			GroupId groupId, boolean selected, boolean disabled) {
-
-		super(contact, localAuthor, false, groupId,
-				Collections.<ConversationItem>emptyList());
-
-		this.selected = selected;
-		this.disabled = disabled;
-	}
-
-	public void setSelected(boolean selected) {
-		this.selected = selected;
-	}
-
-	public boolean isSelected() {
-		return selected;
-	}
-
-	public void toggleSelected() {
-		selected = !selected;
-	}
-
-	public boolean isDisabled() {
-		return disabled;
-	}
-}
diff --git a/briar-android/src/org/briarproject/android/forum/ShareForumActivity.java b/briar-android/src/org/briarproject/android/forum/ShareForumActivity.java
deleted file mode 100644
index 81bcdf8cd7025b179a4a4ba66ab36768926db478..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/forum/ShareForumActivity.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package org.briarproject.android.forum;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.View;
-
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.BriarActivity;
-import org.briarproject.android.fragment.BaseFragment;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.sync.GroupId;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-public class ShareForumActivity extends BriarActivity implements
-		BaseFragment.BaseFragmentListener {
-
-	public final static String CONTACTS = "contacts";
-
-	@Override
-	public void onCreate(Bundle savedInstanceState) {
-		super.onCreate(savedInstanceState);
-
-		setContentView(R.layout.activity_share_forum);
-
-		Intent i = getIntent();
-		byte[] b = i.getByteArrayExtra(GROUP_ID);
-		if (b == null) throw new IllegalStateException("No GroupId");
-		GroupId groupId = new GroupId(b);
-
-		if (savedInstanceState == null) {
-			ContactSelectorFragment contactSelectorFragment =
-					activityComponent.newContactSelectorFragment();
-			contactSelectorFragment.initBundle(groupId);
-			getSupportFragmentManager().beginTransaction()
-					.add(R.id.shareForumContainer, contactSelectorFragment)
-					.commit();
-		}
-	}
-
-	@Override
-	public void injectActivity(ActivityComponent component) {
-		component.inject(this);
-	}
-
-	public void showMessageScreen(GroupId groupId,
-			Collection<ContactId> contacts) {
-
-		ShareForumMessageFragment messageFragment =
-				activityComponent.newShareForumMessageFragment();
-		messageFragment.initBundle(groupId, contacts);
-
-		getSupportFragmentManager().beginTransaction()
-				.setCustomAnimations(android.R.anim.fade_in,
-						android.R.anim.fade_out,
-						android.R.anim.slide_in_left,
-						android.R.anim.slide_out_right)
-				.replace(R.id.shareForumContainer, messageFragment,
-						ContactSelectorFragment.TAG)
-				.addToBackStack(null)
-				.commit();
-	}
-
-	public static ArrayList<Integer> getContactsFromIds(
-			Collection<ContactId> contacts) {
-
-		// transform ContactIds to Integers so they can be added to a bundle
-		ArrayList<Integer> intContacts = new ArrayList<>(contacts.size());
-		for (ContactId contactId : contacts) {
-			intContacts.add(contactId.getInt());
-		}
-		return intContacts;
-	}
-
-	public void sharingSuccessful(View v) {
-		setResult(RESULT_OK);
-		hideSoftKeyboard(v);
-		supportFinishAfterTransition();
-	}
-
-	protected static Collection<ContactId> getContactsFromIntegers(
-			ArrayList<Integer> intContacts) {
-
-		// turn contact integers from a bundle back to ContactIds
-		List<ContactId> contacts = new ArrayList<>(intContacts.size());
-		for(Integer c : intContacts) {
-			contacts.add(new ContactId(c));
-		}
-		return contacts;
-	}
-
-	@Override
-	public void showLoadingScreen(boolean isBlocking, int stringId) {
-		// this is handled by the recycler view in ContactSelectorFragment
-	}
-
-	@Override
-	public void hideLoadingScreen() {
-		// this is handled by the recycler view in ContactSelectorFragment
-	}
-
-}
diff --git a/briar-android/src/org/briarproject/android/forum/ShareForumMessageFragment.java b/briar-android/src/org/briarproject/android/forum/ShareForumMessageFragment.java
deleted file mode 100644
index d88c33d548a6a2bf67bc874e8266fc1840a0596d..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/forum/ShareForumMessageFragment.java
+++ /dev/null
@@ -1,171 +0,0 @@
-package org.briarproject.android.forum;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.support.v7.app.ActionBar;
-import android.view.LayoutInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.Toast;
-
-import org.briarproject.R;
-import org.briarproject.android.fragment.BaseFragment;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.forum.ForumSharingManager;
-import org.briarproject.api.sync.GroupId;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.logging.Logger;
-
-import javax.inject.Inject;
-
-import static android.widget.Toast.LENGTH_SHORT;
-import static java.util.logging.Level.WARNING;
-import static org.briarproject.android.forum.ShareForumActivity.CONTACTS;
-import static org.briarproject.android.forum.ShareForumActivity.getContactsFromIds;
-import static org.briarproject.api.forum.ForumConstants.GROUP_ID;
-
-public class ShareForumMessageFragment extends BaseFragment {
-
-	public final static String TAG = "IntroductionMessageFragment";
-
-	private static final Logger LOG =
-			Logger.getLogger(ShareForumMessageFragment.class.getName());
-
-	private ShareForumActivity shareForumActivity;
-	private ViewHolder ui;
-
-	// Fields that are accessed from background threads must be volatile
-	@Inject
-	protected volatile ForumSharingManager forumSharingManager;
-	private volatile GroupId groupId;
-	private volatile Collection<ContactId> contacts;
-
-	public void initBundle(GroupId groupId, Collection<ContactId> contacts) {
-		Bundle bundle = new Bundle();
-		bundle.putByteArray(GROUP_ID, groupId.getBytes());
-		bundle.putIntegerArrayList(CONTACTS, getContactsFromIds(contacts));
-		setArguments(bundle);
-	}
-
-	@Inject
-	public ShareForumMessageFragment() {
-
-	}
-
-	@Override
-	public void onAttach(Context context) {
-		super.onAttach(context);
-		try {
-			shareForumActivity = (ShareForumActivity) context;
-		} catch (ClassCastException e) {
-			throw new InstantiationError(
-					"This fragment is only meant to be attached to the ShareForumActivity");
-		}
-	}
-
-	@Override
-	public View onCreateView(LayoutInflater inflater, ViewGroup container,
-			Bundle savedInstanceState) {
-
-		// change toolbar text
-		ActionBar actionBar = shareForumActivity.getSupportActionBar();
-		if (actionBar != null) {
-			actionBar.setTitle(R.string.forum_share_button);
-		}
-
-		// allow for home button to act as back button
-		setHasOptionsMenu(true);
-
-		// inflate view
-		View v = inflater.inflate(R.layout.share_forum_message, container,
-				false);
-		ui = new ViewHolder(v);
-		ui.button.setOnClickListener(new View.OnClickListener() {
-			@Override
-			public void onClick(View v) {
-				onButtonClick();
-			}
-		});
-
-		// get groupID and contactIDs from fragment arguments
-		groupId = new GroupId(getArguments().getByteArray(GROUP_ID));
-		ArrayList<Integer> intContacts =
-				getArguments().getIntegerArrayList(CONTACTS);
-		if (intContacts == null) throw new IllegalArgumentException();
-		contacts = ShareForumActivity.getContactsFromIntegers(intContacts);
-
-		return v;
-	}
-
-	@Override
-	public boolean onOptionsItemSelected(final MenuItem item) {
-		switch (item.getItemId()) {
-			case android.R.id.home:
-				shareForumActivity.onBackPressed();
-				return true;
-			default:
-				return super.onOptionsItemSelected(item);
-		}
-	}
-
-	@Override
-	public String getUniqueTag() {
-		return TAG;
-	}
-
-	public void onButtonClick() {
-		// disable button to prevent accidental double invitations
-		ui.button.setEnabled(false);
-
-		String msg = ui.message.getText().toString();
-		shareForum(msg);
-
-		// don't wait for the introduction to be made before finishing activity
-		shareForumActivity.sharingSuccessful(ui.message);
-	}
-
-	private void shareForum(final String msg) {
-		shareForumActivity.runOnDbThread(new Runnable() {
-			@Override
-			public void run() {
-				try {
-					for (ContactId c : contacts) {
-						forumSharingManager.sendForumInvitation(groupId, c,
-								msg);
-					}
-				} catch (DbException e) {
-					sharingError();
-					if (LOG.isLoggable(WARNING))
-						LOG.log(WARNING, e.toString(), e);
-				}
-			}
-		});
-	}
-
-	private void sharingError() {
-		shareForumActivity.runOnUiThread(new Runnable() {
-			@Override
-			public void run() {
-				Toast.makeText(shareForumActivity,
-						R.string.introduction_error, LENGTH_SHORT).show();
-			}
-		});
-	}
-
-	private static class ViewHolder {
-
-		private final EditText message;
-		private final Button button;
-
-		ViewHolder(View v) {
-			message = (EditText) v.findViewById(R.id.invitationMessageView);
-			button = (Button) v.findViewById(R.id.shareForumButton);
-		}
-	}
-}
diff --git a/briar-android/src/org/briarproject/android/forum/WriteForumPostActivity.java b/briar-android/src/org/briarproject/android/forum/WriteForumPostActivity.java
deleted file mode 100644
index d2185aa4630df3d1dcd024fd322a6c4bcdd154dd..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/forum/WriteForumPostActivity.java
+++ /dev/null
@@ -1,317 +0,0 @@
-package org.briarproject.android.forum;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.text.InputType;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemSelectedListener;
-import android.widget.EditText;
-import android.widget.ImageButton;
-import android.widget.LinearLayout;
-import android.widget.RelativeLayout;
-import android.widget.Spinner;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import org.briarproject.R;
-import org.briarproject.android.ActivityComponent;
-import org.briarproject.android.AndroidComponent;
-import org.briarproject.android.BriarActivity;
-import org.briarproject.android.identity.CreateIdentityActivity;
-import org.briarproject.android.identity.LocalAuthorItem;
-import org.briarproject.android.identity.LocalAuthorItemComparator;
-import org.briarproject.android.identity.LocalAuthorSpinnerAdapter;
-import org.briarproject.android.util.CommonLayoutParams;
-import org.briarproject.android.util.LayoutUtils;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.CryptoExecutor;
-import org.briarproject.api.crypto.KeyParser;
-import org.briarproject.api.crypto.PrivateKey;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.forum.Forum;
-import org.briarproject.api.forum.ForumManager;
-import org.briarproject.api.forum.ForumPost;
-import org.briarproject.api.forum.ForumPostFactory;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.util.StringUtils;
-
-import java.security.GeneralSecurityException;
-import java.util.Collection;
-import java.util.concurrent.Executor;
-import java.util.logging.Logger;
-
-import javax.inject.Inject;
-
-import static android.text.InputType.TYPE_CLASS_TEXT;
-import static android.text.InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
-import static android.widget.LinearLayout.VERTICAL;
-import static android.widget.RelativeLayout.ALIGN_PARENT_LEFT;
-import static android.widget.RelativeLayout.ALIGN_PARENT_RIGHT;
-import static android.widget.RelativeLayout.CENTER_VERTICAL;
-import static android.widget.RelativeLayout.LEFT_OF;
-import static android.widget.RelativeLayout.RIGHT_OF;
-import static android.widget.Toast.LENGTH_LONG;
-import static java.util.logging.Level.INFO;
-import static java.util.logging.Level.WARNING;
-import static org.briarproject.android.forum.ForumActivity.FORUM_NAME;
-import static org.briarproject.android.forum.ForumActivity.MIN_TIMESTAMP;
-import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP;
-
-public class WriteForumPostActivity extends BriarActivity
-implements OnItemSelectedListener, OnClickListener {
-
-	private static final int REQUEST_CREATE_IDENTITY = 2;
-	private static final Logger LOG =
-			Logger.getLogger(WriteForumPostActivity.class.getName());
-
-	@Inject @CryptoExecutor protected Executor cryptoExecutor;
-	private LocalAuthorSpinnerAdapter adapter = null;
-	private Spinner spinner = null;
-	private ImageButton sendButton = null;
-	private EditText content = null;
-	private AuthorId localAuthorId = null;
-	private GroupId groupId = null;
-
-	// Fields that are accessed from background threads must be volatile
-	@Inject protected volatile IdentityManager identityManager;
-	@Inject protected volatile ForumManager forumManager;
-	@Inject protected volatile ForumPostFactory forumPostFactory;
-	@Inject protected volatile CryptoComponent crypto;
-	private volatile MessageId parentId = null;
-	private volatile long minTimestamp = -1;
-	private volatile LocalAuthor localAuthor = null;
-	private volatile Forum forum = null;
-
-	@Override
-	public void onCreate(Bundle state) {
-		super.onCreate(state);
-
-		Intent i = getIntent();
-		byte[] b = i.getByteArrayExtra(GROUP_ID);
-		if (b == null) throw new IllegalStateException();
-		groupId = new GroupId(b);
-		String forumName = i.getStringExtra(FORUM_NAME);
-		if (forumName == null) throw new IllegalStateException();
-		setTitle(forumName);
-		minTimestamp = i.getLongExtra(MIN_TIMESTAMP, -1);
-		if (minTimestamp == -1) throw new IllegalStateException();
-		b = i.getByteArrayExtra("briar.PARENT_ID");
-		if (b != null) parentId = new MessageId(b);
-
-		if (state != null) {
-			b = state.getByteArray("briar.LOCAL_AUTHOR_ID");
-			if (b != null) localAuthorId = new AuthorId(b);
-		}
-
-		LinearLayout layout = new LinearLayout(this);
-		layout.setLayoutParams(MATCH_WRAP);
-		layout.setOrientation(VERTICAL);
-		int pad = LayoutUtils.getPadding(this);
-		layout.setPadding(pad, 0, pad, pad);
-
-		RelativeLayout header = new RelativeLayout(this);
-
-		TextView from = new TextView(this);
-		from.setId(1);
-		from.setTextSize(18);
-		from.setText(R.string.from);
-		RelativeLayout.LayoutParams left = CommonLayoutParams.relative();
-		left.addRule(ALIGN_PARENT_LEFT);
-		left.addRule(CENTER_VERTICAL);
-		header.addView(from, left);
-
-		adapter = new LocalAuthorSpinnerAdapter(this, true);
-		spinner = new Spinner(this);
-		spinner.setId(2);
-		spinner.setAdapter(adapter);
-		spinner.setOnItemSelectedListener(this);
-		RelativeLayout.LayoutParams between = CommonLayoutParams.relative();
-		between.addRule(CENTER_VERTICAL);
-		between.addRule(RIGHT_OF, 1);
-		between.addRule(LEFT_OF, 3);
-		header.addView(spinner, between);
-
-		sendButton = new ImageButton(this);
-		sendButton.setId(3);
-		sendButton.setBackgroundResource(0);
-		sendButton.setImageResource(R.drawable.social_send_now);
-		sendButton.setEnabled(false); // Enabled after loading the forum
-		sendButton.setOnClickListener(this);
-		RelativeLayout.LayoutParams right = CommonLayoutParams.relative();
-		right.addRule(ALIGN_PARENT_RIGHT);
-		right.addRule(CENTER_VERTICAL);
-		header.addView(sendButton, right);
-		layout.addView(header);
-
-		content = new EditText(this);
-		content.setId(4);
-		int inputType = TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE
-				| TYPE_TEXT_FLAG_CAP_SENTENCES;
-		content.setInputType(inputType);
-		content.setHint(R.string.forum_post_hint);
-		layout.addView(content);
-
-		setContentView(layout);
-	}
-
-	@Override
-	public void injectActivity(ActivityComponent component) {
-		component.inject(this);
-	}
-
-	@Override
-	public void onResume() {
-		super.onResume();
-		loadAuthorsAndForum();
-	}
-
-	private void loadAuthorsAndForum() {
-		runOnDbThread(new Runnable() {
-			public void run() {
-				try {
-					long now = System.currentTimeMillis();
-					Collection<LocalAuthor> localAuthors =
-							identityManager.getLocalAuthors();
-					forum = forumManager.getForum(groupId);
-					long duration = System.currentTimeMillis() - now;
-					if (LOG.isLoggable(INFO))
-						LOG.info("Load took " + duration + " ms");
-					displayAuthorsAndForum(localAuthors);
-				} catch (DbException e) {
-					if (LOG.isLoggable(WARNING))
-						LOG.log(WARNING, e.toString(), e);
-				}
-			}
-		});
-	}
-
-	private void displayAuthorsAndForum(
-			final Collection<LocalAuthor> localAuthors) {
-		runOnUiThread(new Runnable() {
-			public void run() {
-				if (localAuthors.isEmpty()) throw new IllegalStateException();
-				adapter.clear();
-				for (LocalAuthor a : localAuthors)
-					adapter.add(new LocalAuthorItem(a));
-				adapter.sort(LocalAuthorItemComparator.INSTANCE);
-				int count = adapter.getCount();
-				for (int i = 0; i < count; i++) {
-					LocalAuthorItem item = adapter.getItem(i);
-					if (item == LocalAuthorItem.ANONYMOUS) continue;
-					if (item == LocalAuthorItem.NEW) continue;
-					if (item.getLocalAuthor().getId().equals(localAuthorId)) {
-						localAuthor = item.getLocalAuthor();
-						spinner.setSelection(i);
-						break;
-					}
-				}
-				setTitle(forum.getName());
-				sendButton.setEnabled(true);
-			}
-		});
-	}
-
-	@Override
-	public void onSaveInstanceState(Bundle state) {
-		super.onSaveInstanceState(state);
-		if (localAuthorId != null) {
-			byte[] b =  localAuthorId.getBytes();
-			state.putByteArray("briar.LOCAL_AUTHOR_ID", b);
-		}
-	}
-
-	@Override
-	protected void onActivityResult(int request, int result, Intent data) {
-		super.onActivityResult(request, result, data);
-		if (request == REQUEST_CREATE_IDENTITY && result == RESULT_OK) {
-			byte[] b = data.getByteArrayExtra("briar.LOCAL_AUTHOR_ID");
-			if (b == null) throw new IllegalStateException();
-			localAuthorId = new AuthorId(b);
-			loadAuthorsAndForum();
-		}
-	}
-
-	public void onItemSelected(AdapterView<?> parent, View view, int position,
-			long id) {
-		LocalAuthorItem item = adapter.getItem(position);
-		if (item == LocalAuthorItem.ANONYMOUS) {
-			localAuthor = null;
-			localAuthorId = null;
-		} else if (item == LocalAuthorItem.NEW) {
-			localAuthor = null;
-			localAuthorId = null;
-			Intent i = new Intent(this, CreateIdentityActivity.class);
-			startActivityForResult(i, REQUEST_CREATE_IDENTITY);
-		} else {
-			localAuthor = item.getLocalAuthor();
-			localAuthorId = localAuthor.getId();
-		}
-	}
-
-	public void onNothingSelected(AdapterView<?> parent) {
-		localAuthor = null;
-		localAuthorId = null;
-	}
-
-	public void onClick(View view) {
-		if (forum == null) throw new IllegalStateException();
-		String body = content.getText().toString();
-		if (body.equals("")) return;
-		createPost(StringUtils.toUtf8(body));
-		Toast.makeText(this, R.string.post_sent_toast, LENGTH_LONG).show();
-		finish();
-	}
-
-	private void createPost(final byte[] body) {
-		cryptoExecutor.execute(new Runnable() {
-			public void run() {
-				// Don't use an earlier timestamp than the newest post
-				long timestamp = System.currentTimeMillis();
-				timestamp = Math.max(timestamp, minTimestamp);
-				ForumPost p;
-				try {
-					if (localAuthor == null) {
-						p = forumPostFactory.createAnonymousPost(groupId,
-								timestamp, parentId, "text/plain", body);
-					} else {
-						KeyParser keyParser = crypto.getSignatureKeyParser();
-						byte[] b = localAuthor.getPrivateKey();
-						PrivateKey authorKey = keyParser.parsePrivateKey(b);
-						p = forumPostFactory.createPseudonymousPost(groupId,
-								timestamp, parentId, localAuthor, "text/plain",
-								body, authorKey);
-					}
-				} catch (GeneralSecurityException e) {
-					throw new RuntimeException(e);
-				} catch (FormatException e) {
-					throw new RuntimeException(e);
-				}
-				storePost(p);
-			}
-		});
-	}
-
-	private void storePost(final ForumPost p) {
-		runOnDbThread(new Runnable() {
-			public void run() {
-				try {
-					long now = System.currentTimeMillis();
-					forumManager.addLocalPost(p);
-					long duration = System.currentTimeMillis() - now;
-					if (LOG.isLoggable(INFO))
-						LOG.info("Storing message took " + duration + " ms");
-				} catch (DbException e) {
-					if (LOG.isLoggable(WARNING))
-						LOG.log(WARNING, e.toString(), e);
-				}
-			}
-		});
-	}
-}
diff --git a/briar-android/src/org/briarproject/android/fragment/SettingsFragment.java b/briar-android/src/org/briarproject/android/fragment/SettingsFragment.java
index b7750dc17a91f3f96f480126eb31397c602376f8..75bbd1cf8f38c90ccf2637b9c30f7c356b2c0d83 100644
--- a/briar-android/src/org/briarproject/android/fragment/SettingsFragment.java
+++ b/briar-android/src/org/briarproject/android/fragment/SettingsFragment.java
@@ -59,7 +59,6 @@ public class SettingsFragment extends PreferenceFragmentCompat
 	private ListPreference enableBluetooth;
 	private ListPreference torOverMobile;
 	private CheckBoxPreference notifyPrivateMessages;
-	private CheckBoxPreference notifyForumPosts;
 	private CheckBoxPreference notifyVibration;
 	private Preference notifySound;
 
@@ -94,8 +93,6 @@ public class SettingsFragment extends PreferenceFragmentCompat
 				(ListPreference) findPreference("pref_key_tor_mobile");
 		notifyPrivateMessages = (CheckBoxPreference) findPreference(
 				"pref_key_notify_private_messages");
-		notifyForumPosts = (CheckBoxPreference) findPreference(
-				"pref_key_notify_forum_posts");
 		notifyVibration = (CheckBoxPreference) findPreference(
 				"pref_key_notify_vibration");
 		notifySound = findPreference("pref_key_notify_sound");
@@ -103,7 +100,6 @@ public class SettingsFragment extends PreferenceFragmentCompat
 		enableBluetooth.setOnPreferenceChangeListener(this);
 		torOverMobile.setOnPreferenceChangeListener(this);
 		notifyPrivateMessages.setOnPreferenceChangeListener(this);
-		notifyForumPosts.setOnPreferenceChangeListener(this);
 		notifyVibration.setOnPreferenceChangeListener(this);
 
 		notifySound.setOnPreferenceClickListener(
@@ -197,9 +193,6 @@ public class SettingsFragment extends PreferenceFragmentCompat
 				notifyPrivateMessages.setChecked(settings.getBoolean(
 						"notifyPrivateMessages", true));
 
-				notifyForumPosts.setChecked(settings.getBoolean(
-						"notifyForumPosts", true));
-
 				notifyVibration.setChecked(settings.getBoolean(
 						"notifyVibration", true));
 
@@ -241,10 +234,6 @@ public class SettingsFragment extends PreferenceFragmentCompat
 			Settings s = new Settings();
 			s.putBoolean("notifyPrivateMessages", (Boolean) o);
 			storeSettings(s);
-		} else if (preference == notifyForumPosts) {
-			Settings s = new Settings();
-			s.putBoolean("notifyForumPosts", (Boolean) o);
-			storeSettings(s);
 		} else if (preference == notifyVibration) {
 			Settings s = new Settings();
 			s.putBoolean("notifyVibration", (Boolean) o);
diff --git a/briar-android/src/org/briarproject/android/util/TextAvatarView.java b/briar-android/src/org/briarproject/android/util/TextAvatarView.java
deleted file mode 100644
index 721fc5e91c28d83ea348cc4914b4d96600659c2f..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/util/TextAvatarView.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package org.briarproject.android.util;
-
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.graphics.Color;
-import android.graphics.PorterDuff;
-import android.support.v7.widget.AppCompatTextView;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.widget.FrameLayout;
-
-import org.briarproject.R;
-
-import de.hdodenhof.circleimageview.CircleImageView;
-
-public class TextAvatarView extends FrameLayout {
-
-	final private AppCompatTextView textView;
-	final private CircleImageView backgroundView;
-
-	public TextAvatarView(Context context, AttributeSet attrs) {
-		super(context, attrs);
-
-		LayoutInflater inflater = (LayoutInflater) context
-				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-		inflater
-				.inflate(R.layout.text_avatar_view, this, true);
-		textView = (AppCompatTextView) findViewById(R.id.textAvatarView);
-		backgroundView = (CircleImageView) findViewById(R.id.avatarBackground);
-	}
-
-	public TextAvatarView(Context context) {
-		this(context, null);
-	}
-
-	public void setText(String text) {
-		textView.setText(text);
-	}
-
-	public void setBackgroundBytes(byte[] bytes) {
-		int r = getByte(bytes, 0) * 3 / 4 + 96;
-		int g = getByte(bytes, 1) * 3 / 4 + 96;
-		int b = getByte(bytes, 2) * 3 / 4 + 96;
-		int color = Color.rgb(r, g, b);
-
-		backgroundView.setFillColor(color);
-	}
-
-	private byte getByte(byte[] bytes, int index) {
-		if (bytes == null) {
-			return -128;
-		} else {
-			return bytes[index % bytes.length];
-		}
-	}
-
-}
diff --git a/briar-api/src/org/briarproject/api/event/ForumInvitationReceivedEvent.java b/briar-api/src/org/briarproject/api/event/ForumInvitationReceivedEvent.java
deleted file mode 100644
index 1d8e7b5f7b61a1a88076277e48fb3b52cc34de13..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/ForumInvitationReceivedEvent.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.forum.Forum;
-import org.briarproject.api.introduction.IntroductionRequest;
-
-public class ForumInvitationReceivedEvent extends Event {
-
-	private final Forum forum;
-	private final ContactId contactId;
-
-	public ForumInvitationReceivedEvent(Forum forum, ContactId contactId) {
-		this.forum = forum;
-		this.contactId = contactId;
-	}
-
-	public Forum getForum() {
-		return forum;
-	}
-
-	public ContactId getContactId() {
-		return contactId;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/event/ForumInvitationResponseReceivedEvent.java b/briar-api/src/org/briarproject/api/event/ForumInvitationResponseReceivedEvent.java
deleted file mode 100644
index 1e799240386966ff59c73037c97e6cfaaaeb2e63..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/event/ForumInvitationResponseReceivedEvent.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.briarproject.api.event;
-
-import org.briarproject.api.contact.ContactId;
-
-public class ForumInvitationResponseReceivedEvent extends Event {
-
-	private final String forumName;
-	private final ContactId contactId;
-
-	public ForumInvitationResponseReceivedEvent(String forumName,
-			ContactId contactId) {
-
-		this.forumName = forumName;
-		this.contactId = contactId;
-	}
-
-	public String getForumName() {
-		return forumName;
-	}
-
-	public ContactId getContactId() {
-		return contactId;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/forum/Forum.java b/briar-api/src/org/briarproject/api/forum/Forum.java
deleted file mode 100644
index 2eeadc21664f069e32db944305a5d0756ec05561..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/forum/Forum.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package org.briarproject.api.forum;
-
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-
-public class Forum {
-
-	private final Group group;
-	private final String name;
-	private final byte[] salt;
-
-	public Forum(Group group, String name, byte[] salt) {
-		this.group = group;
-		this.name = name;
-		this.salt = salt;
-	}
-
-	public GroupId getId() {
-		return group.getId();
-	}
-
-	public Group getGroup() {
-		return group;
-	}
-
-	public String getName() {
-		return name;
-	}
-
-	public byte[] getSalt() {
-		return salt;
-	}
-
-	@Override
-	public int hashCode() {
-		return group.hashCode();
-	}
-
-	@Override
-	public boolean equals(Object o) {
-		return o instanceof Forum && group.equals(((Forum) o).group);
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/forum/ForumConstants.java b/briar-api/src/org/briarproject/api/forum/ForumConstants.java
deleted file mode 100644
index dcdee0132b9d1d807ca402c12e5972e3cf85ce09..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/forum/ForumConstants.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package org.briarproject.api.forum;
-
-import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
-
-public interface ForumConstants {
-
-	/** The maximum length of a forum's name in UTF-8 bytes. */
-	int MAX_FORUM_NAME_LENGTH = 100;
-
-	/** The length of a forum's random salt in bytes. */
-	int FORUM_SALT_LENGTH = 32;
-
-	/** The maximum length of a forum post's content type in UTF-8 bytes. */
-	int MAX_CONTENT_TYPE_LENGTH = 50;
-
-	/** The maximum length of a forum post's body in bytes. */
-	int MAX_FORUM_POST_BODY_LENGTH = MAX_MESSAGE_BODY_LENGTH - 1024;
-
-	/* Forum Sharing Constants */
-	String CONTACT_ID = "contactId";
-	String GROUP_ID = "groupId";
-	String TO_BE_SHARED_BY_US = "toBeSharedByUs";
-	String SHARED_BY_US = "sharedByUs";
-	String SHARED_WITH_US = "sharedWithUs";
-	String TYPE = "type";
-	String SESSION_ID = "sessionId";
-	String STORAGE_ID = "storageId";
-	String STATE = "state";
-	String LOCAL = "local";
-	String TIME = "time";
-	String READ = "read";
-	String IS_SHARER = "isSharer";
-	String FORUM_ID = "forumId";
-	String FORUM_NAME = "forumName";
-	String FORUM_SALT = "forumSalt";
-	String INVITATION_MSG = "invitationMsg";
-	int SHARE_MSG_TYPE_INVITATION = 1;
-	int SHARE_MSG_TYPE_ACCEPT = 2;
-	int SHARE_MSG_TYPE_DECLINE = 3;
-	int SHARE_MSG_TYPE_LEAVE = 4;
-	int SHARE_MSG_TYPE_ABORT = 5;
-	String TASK = "task";
-	int TASK_ADD_FORUM_TO_LIST_SHARED_WITH_US = 0;
-	int TASK_REMOVE_FORUM_FROM_LIST_SHARED_WITH_US = 1;
-	int TASK_ADD_SHARED_FORUM = 2;
-	int TASK_ADD_FORUM_TO_LIST_TO_BE_SHARED_BY_US = 3;
-	int TASK_REMOVE_FORUM_FROM_LIST_TO_BE_SHARED_BY_US = 4;
-	int TASK_SHARE_FORUM = 5;
-	int TASK_UNSHARE_FORUM_SHARED_BY_US = 6;
-	int TASK_UNSHARE_FORUM_SHARED_WITH_US = 7;
-
-}
diff --git a/briar-api/src/org/briarproject/api/forum/ForumInvitationMessage.java b/briar-api/src/org/briarproject/api/forum/ForumInvitationMessage.java
deleted file mode 100644
index b153c27f11cb996d5b48f3ad3ebb4aa47e17475d..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/forum/ForumInvitationMessage.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.briarproject.api.forum;
-
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.messaging.BaseMessage;
-import org.briarproject.api.sync.MessageId;
-
-public class ForumInvitationMessage extends BaseMessage {
-
-	private final SessionId sessionId;
-	private final ContactId contactId;
-	private final String forumName, message;
-	private final boolean available;
-
-	public ForumInvitationMessage(MessageId id, SessionId sessionId,
-			ContactId contactId, String forumName, String message,
-			boolean available, long time, boolean local, boolean sent,
-			boolean seen, boolean read) {
-
-		super(id, time, local, read, sent, seen);
-		this.sessionId = sessionId;
-		this.contactId = contactId;
-		this.forumName = forumName;
-		this.message = message;
-		this.available = available;
-	}
-
-	public SessionId getSessionId() {
-		return sessionId;
-	}
-
-	public ContactId getContactId() {
-		return contactId;
-	}
-
-	public String getForumName() {
-		return forumName;
-	}
-
-	public String getMessage() {
-		return message;
-	}
-
-	public boolean isAvailable() {
-		return available;
-	}
-
-}
diff --git a/briar-api/src/org/briarproject/api/forum/ForumManager.java b/briar-api/src/org/briarproject/api/forum/ForumManager.java
deleted file mode 100644
index 7c619294bea1b0777b355ab1f93af06433154190..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/forum/ForumManager.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package org.briarproject.api.forum;
-
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-
-import java.util.Collection;
-
-public interface ForumManager {
-
-	/** Returns the unique ID of the forum client. */
-	ClientId getClientId();
-
-	/** Creates a forum with the given name. */
-	Forum createForum(String name);
-
-	/** Creates a forum with the given name and salt. */
-	Forum createForum(String name, byte[] salt);
-
-	/** Subscribes to a forum. */
-	void addForum(Forum f) throws DbException;
-
-	/** Unsubscribes from a forum. */
-	void removeForum(Forum f) throws DbException;
-
-	/** Stores a local forum post. */
-	void addLocalPost(ForumPost p) throws DbException;
-
-	/** Returns the forum with the given ID. */
-	Forum getForum(GroupId g) throws DbException;
-
-	/** Returns the forum with the given ID. */
-	Forum getForum(Transaction txn, GroupId g) throws DbException;
-
-	/** Returns all forums to which the user subscribes. */
-	Collection<Forum> getForums() throws DbException;
-
-	/** Returns the body of the forum post with the given ID. */
-	byte[] getPostBody(MessageId m) throws DbException;
-
-	/** Returns the headers of all posts in the given forum. */
-	Collection<ForumPostHeader> getPostHeaders(GroupId g) throws DbException;
-
-	/** Marks a forum post as read or unread. */
-	void setReadFlag(MessageId m, boolean read) throws DbException;
-
-	/** Registers a hook to be called whenever a forum is removed. */
-	void registerRemoveForumHook(RemoveForumHook hook);
-
-	interface RemoveForumHook {
-		void removingForum(Transaction txn, Forum f) throws DbException;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/forum/ForumPost.java b/briar-api/src/org/briarproject/api/forum/ForumPost.java
deleted file mode 100644
index 404d6c520e8cb33661298fa48a7acc123c278e31..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/forum/ForumPost.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package org.briarproject.api.forum;
-
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-
-public class ForumPost {
-
-	private final Message message;
-	private final MessageId parent;
-	private final Author author;
-	private final String contentType;
-
-	public ForumPost(Message message, MessageId parent, Author author,
-			String contentType) {
-		this.message = message;
-		this.parent = parent;
-		this.author = author;
-		this.contentType = contentType;
-	}
-
-	public Message getMessage() {
-		return message;
-	}
-
-	public MessageId getParent() {
-		return parent;
-	}
-
-	public Author getAuthor() {
-		return author;
-	}
-
-	public String getContentType() {
-		return contentType;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/forum/ForumPostFactory.java b/briar-api/src/org/briarproject/api/forum/ForumPostFactory.java
deleted file mode 100644
index e05edc8831b3538458c44175e8a005d59d56d878..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/forum/ForumPostFactory.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.briarproject.api.forum;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.crypto.PrivateKey;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-
-import java.security.GeneralSecurityException;
-
-public interface ForumPostFactory {
-
-	ForumPost createAnonymousPost(GroupId groupId, long timestamp,
-			MessageId parent, String contentType, byte[] body)
-			throws FormatException;
-
-	ForumPost createPseudonymousPost(GroupId groupId, long timestamp,
-			MessageId parent, Author author, String contentType, byte[] body,
-			PrivateKey privateKey) throws FormatException,
-			GeneralSecurityException;
-}
diff --git a/briar-api/src/org/briarproject/api/forum/ForumPostHeader.java b/briar-api/src/org/briarproject/api/forum/ForumPostHeader.java
deleted file mode 100644
index 15030223eeac2888443e2daee453be1bf8bc1150..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/forum/ForumPostHeader.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.briarproject.api.forum;
-
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.sync.MessageId;
-
-public class ForumPostHeader {
-
-	private final MessageId id;
-	private final long timestamp;
-	private final Author author;
-	private final Author.Status authorStatus;
-	private final String contentType;
-	private final boolean read;
-
-	public ForumPostHeader(MessageId id, long timestamp, Author author,
-			Author.Status authorStatus, String contentType, boolean read) {
-		this.id = id;
-		this.timestamp = timestamp;
-		this.author = author;
-		this.authorStatus = authorStatus;
-		this.contentType = contentType;
-		this.read = read;
-	}
-
-	public MessageId getId() {
-		return id;
-	}
-
-	public Author getAuthor() {
-		return author;
-	}
-
-	public Author.Status getAuthorStatus() {
-		return authorStatus;
-	}
-
-	public String getContentType() {
-		return contentType;
-	}
-
-	public long getTimestamp() {
-		return timestamp;
-	}
-
-	public boolean isRead() {
-		return read;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/forum/ForumSharingManager.java b/briar-api/src/org/briarproject/api/forum/ForumSharingManager.java
deleted file mode 100644
index 9f4cc87b6620aebb593a32f3f2e9e3655207aa9a..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/forum/ForumSharingManager.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.briarproject.api.forum;
-
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.GroupId;
-
-import java.util.Collection;
-
-public interface ForumSharingManager {
-
-	/** Returns the unique ID of the forum sharing client. */
-	ClientId getClientId();
-
-	/**
-	 * Sends an invitation to share the given forum with the given contact
-	 * and sends an optional message along with it.
-	 */
-	void sendForumInvitation(GroupId groupId, ContactId contactId,
-			String message)	throws DbException;
-
-	/**
-	 * Responds to a pending forum invitation
-	 */
-	void respondToInvitation(Forum f, boolean accept) throws DbException;
-
-	/**
-	 * Returns all forum sharing messages sent by the Contact
-	 * identified by contactId.
-	 */
-	Collection<ForumInvitationMessage> getForumInvitationMessages(
-			ContactId contactId) throws DbException;
-
-	/** Returns all forums to which the user could subscribe. */
-	Collection<Forum> getAvailableForums() throws DbException;
-
-	/** Returns all contacts who are sharing the given forum with us. */
-	Collection<Contact> getSharedBy(GroupId g) throws DbException;
-
-	/** Returns the IDs of all contacts with whom the given forum is shared. */
-	Collection<ContactId> getSharedWith(GroupId g) throws DbException;
-
-	/** Returns true if the forum not already shared and no invitation is open */
-	boolean canBeShared(GroupId g, Contact c) throws DbException;
-
-}
diff --git a/briar-api/src/org/briarproject/api/forum/InviteeAction.java b/briar-api/src/org/briarproject/api/forum/InviteeAction.java
deleted file mode 100644
index 212f0861ce661de2e69b18adeb8a52ba9aa14af5..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/forum/InviteeAction.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.briarproject.api.forum;
-
-import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_ABORT;
-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;
-
-public enum InviteeAction {
-
-	LOCAL_ACCEPT,
-	LOCAL_DECLINE,
-	LOCAL_LEAVE,
-	LOCAL_ABORT,
-	REMOTE_INVITATION,
-	REMOTE_LEAVE,
-	REMOTE_ABORT;
-
-	public static InviteeAction getLocal(long type) {
-		if (type == SHARE_MSG_TYPE_ACCEPT) return LOCAL_ACCEPT;
-		if (type == SHARE_MSG_TYPE_DECLINE) return LOCAL_DECLINE;
-		if (type == SHARE_MSG_TYPE_LEAVE) return LOCAL_LEAVE;
-		if (type == SHARE_MSG_TYPE_ABORT) return LOCAL_ABORT;
-		return null;
-	}
-
-	public static InviteeAction getRemote(long type) {
-		if (type == SHARE_MSG_TYPE_INVITATION) return REMOTE_INVITATION;
-		if (type == SHARE_MSG_TYPE_LEAVE) return REMOTE_LEAVE;
-		if (type == SHARE_MSG_TYPE_ABORT) return REMOTE_ABORT;
-		return null;
-	}
-
-}
diff --git a/briar-api/src/org/briarproject/api/forum/InviteeProtocolState.java b/briar-api/src/org/briarproject/api/forum/InviteeProtocolState.java
deleted file mode 100644
index 35d6a880af0b9bbb41c3ffd2ede3122d9b7fb297..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/forum/InviteeProtocolState.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package org.briarproject.api.forum;
-
-import static org.briarproject.api.forum.InviteeAction.LOCAL_ACCEPT;
-import static org.briarproject.api.forum.InviteeAction.LOCAL_DECLINE;
-import static org.briarproject.api.forum.InviteeAction.LOCAL_LEAVE;
-import static org.briarproject.api.forum.InviteeAction.REMOTE_INVITATION;
-import static org.briarproject.api.forum.InviteeAction.REMOTE_LEAVE;
-
-public enum InviteeProtocolState {
-
-	ERROR(0),
-	AWAIT_INVITATION(1) {
-		@Override
-		public InviteeProtocolState next(InviteeAction a) {
-			if (a == REMOTE_INVITATION) return AWAIT_LOCAL_RESPONSE;
-			return ERROR;
-		}
-	},
-	AWAIT_LOCAL_RESPONSE(2) {
-		@Override
-		public InviteeProtocolState next(InviteeAction a) {
-			if (a == LOCAL_ACCEPT || a == LOCAL_DECLINE) return FINISHED;
-			if (a == REMOTE_LEAVE) return LEFT;
-			return ERROR;
-		}
-	},
-	FINISHED(3) {
-		@Override
-		public InviteeProtocolState next(InviteeAction a) {
-			if (a == LOCAL_LEAVE || a == REMOTE_LEAVE) return LEFT;
-			return FINISHED;
-		}
-	},
-	LEFT(4) {
-		@Override
-		public InviteeProtocolState next(InviteeAction a) {
-			if (a == LOCAL_LEAVE) return ERROR;
-			return LEFT;
-		}
-	};
-
-	private final int value;
-
-	InviteeProtocolState(int value) {
-		this.value = value;
-	}
-
-	public int getValue() {
-		return value;
-	}
-
-	public static InviteeProtocolState fromValue(int value) {
-		for (InviteeProtocolState s : values()) {
-			if (s.value == value) return s;
-		}
-		throw new IllegalArgumentException();
-	}
-
-	public InviteeProtocolState next(InviteeAction a) {
-		return this;
-	}
-}
diff --git a/briar-api/src/org/briarproject/api/forum/SharerAction.java b/briar-api/src/org/briarproject/api/forum/SharerAction.java
deleted file mode 100644
index 39796f2c828c10f01bcd6ae3a05f7d258792e11e..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/forum/SharerAction.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.briarproject.api.forum;
-
-import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_ABORT;
-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;
-
-public enum SharerAction {
-
-	LOCAL_INVITATION,
-	LOCAL_LEAVE,
-	LOCAL_ABORT,
-	REMOTE_ACCEPT,
-	REMOTE_DECLINE,
-	REMOTE_LEAVE,
-	REMOTE_ABORT;
-
-	public static SharerAction getLocal(long type) {
-		if (type == SHARE_MSG_TYPE_INVITATION) return LOCAL_INVITATION;
-		if (type == SHARE_MSG_TYPE_LEAVE) return LOCAL_LEAVE;
-		if (type == SHARE_MSG_TYPE_ABORT) return LOCAL_ABORT;
-		return null;
-	}
-
-	public static SharerAction getRemote(long type) {
-		if (type == SHARE_MSG_TYPE_ACCEPT) return REMOTE_ACCEPT;
-		if (type == SHARE_MSG_TYPE_DECLINE) return REMOTE_DECLINE;
-		if (type == SHARE_MSG_TYPE_LEAVE) return REMOTE_LEAVE;
-		if (type == SHARE_MSG_TYPE_ABORT) return REMOTE_ABORT;
-		return null;
-	}
-
-}
diff --git a/briar-api/src/org/briarproject/api/forum/SharerProtocolState.java b/briar-api/src/org/briarproject/api/forum/SharerProtocolState.java
deleted file mode 100644
index b948a9483d980d1cd9a0eeed91d81a6edcdf5511..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/forum/SharerProtocolState.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package org.briarproject.api.forum;
-
-import static org.briarproject.api.forum.SharerAction.LOCAL_INVITATION;
-import static org.briarproject.api.forum.SharerAction.LOCAL_LEAVE;
-import static org.briarproject.api.forum.SharerAction.REMOTE_ACCEPT;
-import static org.briarproject.api.forum.SharerAction.REMOTE_DECLINE;
-import static org.briarproject.api.forum.SharerAction.REMOTE_LEAVE;
-
-public enum SharerProtocolState {
-
-	ERROR(0),
-	PREPARE_INVITATION(1) {
-		@Override
-		public SharerProtocolState next(SharerAction a) {
-			if (a == LOCAL_INVITATION) return AWAIT_RESPONSE;
-			return ERROR;
-		}
-	},
-	AWAIT_RESPONSE(2) {
-		@Override
-		public SharerProtocolState next(SharerAction a) {
-			if (a == REMOTE_ACCEPT || a == REMOTE_DECLINE) return FINISHED;
-			if (a == LOCAL_LEAVE) return LEFT;
-			return ERROR;
-		}
-	},
-	FINISHED(3) {
-		@Override
-		public SharerProtocolState next(SharerAction a) {
-			if (a == LOCAL_LEAVE || a == REMOTE_LEAVE) return LEFT;
-			return FINISHED;
-		}
-	},
-	LEFT(4) {
-		@Override
-		public SharerProtocolState next(SharerAction a) {
-			if (a == LOCAL_LEAVE) return ERROR;
-			return LEFT;
-		}
-	};
-
-	private final int value;
-
-	SharerProtocolState(int value) {
-		this.value = value;
-	}
-
-	public int getValue() {
-		return value;
-	}
-
-	public static SharerProtocolState fromValue(int value) {
-		for (SharerProtocolState s : values()) {
-			if (s.value == value) return s;
-		}
-		throw new IllegalArgumentException();
-	}
-
-	public SharerProtocolState next(SharerAction a) {
-		return this;
-	}
-}
diff --git a/briar-core/src/org/briarproject/CoreEagerSingletons.java b/briar-core/src/org/briarproject/CoreEagerSingletons.java
index 174ee9c570b572e77861cff17229a19f0f9d8a71..0a6eae86e27ae6d1adc9b27d25559bcd69626dd2 100644
--- a/briar-core/src/org/briarproject/CoreEagerSingletons.java
+++ b/briar-core/src/org/briarproject/CoreEagerSingletons.java
@@ -3,7 +3,6 @@ package org.briarproject;
 import org.briarproject.contact.ContactModule;
 import org.briarproject.crypto.CryptoModule;
 import org.briarproject.db.DatabaseExecutorModule;
-import org.briarproject.forum.ForumModule;
 import org.briarproject.introduction.IntroductionModule;
 import org.briarproject.lifecycle.LifecycleModule;
 import org.briarproject.messaging.MessagingModule;
@@ -21,8 +20,6 @@ public interface CoreEagerSingletons {
 
 	void inject(DatabaseExecutorModule.EagerSingletons init);
 
-	void inject(ForumModule.EagerSingletons init);
-
 	void inject(IntroductionModule.EagerSingletons init);
 
 	void inject(LifecycleModule.EagerSingletons init);
diff --git a/briar-core/src/org/briarproject/CoreModule.java b/briar-core/src/org/briarproject/CoreModule.java
index 238c859e7fa8f1d79b00613c14e92938d7ace480..d9ed30c5c748719b9e1afb31783f1e4ec90b73ab 100644
--- a/briar-core/src/org/briarproject/CoreModule.java
+++ b/briar-core/src/org/briarproject/CoreModule.java
@@ -7,7 +7,6 @@ import org.briarproject.data.DataModule;
 import org.briarproject.db.DatabaseExecutorModule;
 import org.briarproject.db.DatabaseModule;
 import org.briarproject.event.EventModule;
-import org.briarproject.forum.ForumModule;
 import org.briarproject.identity.IdentityModule;
 import org.briarproject.introduction.IntroductionModule;
 import org.briarproject.invitation.InvitationModule;
@@ -33,7 +32,6 @@ import dagger.Module;
 		DatabaseModule.class,
 		DatabaseExecutorModule.class,
 		EventModule.class,
-		ForumModule.class,
 		IdentityModule.class,
 		IntroductionModule.class,
 		InvitationModule.class,
@@ -55,7 +53,6 @@ public class CoreModule {
 		c.inject(new ContactModule.EagerSingletons());
 		c.inject(new CryptoModule.EagerSingletons());
 		c.inject(new DatabaseExecutorModule.EagerSingletons());
-		c.inject(new ForumModule.EagerSingletons());
 		c.inject(new LifecycleModule.EagerSingletons());
 		c.inject(new MessagingModule.EagerSingletons());
 		c.inject(new PluginsModule.EagerSingletons());
diff --git a/briar-core/src/org/briarproject/forum/ForumManagerImpl.java b/briar-core/src/org/briarproject/forum/ForumManagerImpl.java
deleted file mode 100644
index d2a2b14d8a98f20f97fee4c14680b7c82e1adb56..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/forum/ForumManagerImpl.java
+++ /dev/null
@@ -1,271 +0,0 @@
-package org.briarproject.forum;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.forum.Forum;
-import org.briarproject.api.forum.ForumManager;
-import org.briarproject.api.forum.ForumPost;
-import org.briarproject.api.forum.ForumPostHeader;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupFactory;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.util.StringUtils;
-
-import java.security.SecureRandom;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-import javax.inject.Inject;
-
-import static org.briarproject.api.forum.ForumConstants.FORUM_SALT_LENGTH;
-import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH;
-import static org.briarproject.api.identity.Author.Status.ANONYMOUS;
-import static org.briarproject.api.identity.Author.Status.UNKNOWN;
-import static org.briarproject.api.identity.Author.Status.VERIFIED;
-
-class ForumManagerImpl implements ForumManager {
-
-	static final ClientId CLIENT_ID = new ClientId(StringUtils.fromHexString(
-			"859a7be50dca035b64bd6902fb797097"
-					+ "795af837abbf8c16d750b3c2ccc186ea"));
-
-	private final DatabaseComponent db;
-	private final ClientHelper clientHelper;
-	private final GroupFactory groupFactory;
-	private final SecureRandom random;
-	private final List<RemoveForumHook> removeHooks;
-
-	@Inject
-	ForumManagerImpl(DatabaseComponent db, ClientHelper clientHelper,
-			GroupFactory groupFactory, SecureRandom random) {
-
-		this.db = db;
-		this.clientHelper = clientHelper;
-		this.groupFactory = groupFactory;
-		this.random = random;
-		removeHooks = new CopyOnWriteArrayList<RemoveForumHook>();
-	}
-
-	@Override
-	public ClientId getClientId() {
-		return CLIENT_ID;
-	}
-
-	@Override
-	public Forum createForum(String name) {
-		int length = StringUtils.toUtf8(name).length;
-		if (length == 0) throw new IllegalArgumentException();
-		if (length > MAX_FORUM_NAME_LENGTH)
-			throw new IllegalArgumentException();
-		byte[] salt = new byte[FORUM_SALT_LENGTH];
-		random.nextBytes(salt);
-		return createForum(name, salt);
-	}
-
-	@Override
-	public Forum createForum(String name, byte[] salt) {
-		try {
-			BdfList forum = BdfList.of(name, salt);
-			byte[] descriptor = clientHelper.toByteArray(forum);
-			Group g = groupFactory.createGroup(getClientId(), descriptor);
-			return new Forum(g, name, salt);
-		} catch (FormatException e) {
-			throw new RuntimeException(e);
-		}
-	}
-
-	@Override
-	public void addForum(Forum f) throws DbException {
-		Transaction txn = db.startTransaction(false);
-		try {
-			db.addGroup(txn, f.getGroup());
-			txn.setComplete();
-		} finally {
-			db.endTransaction(txn);
-		}
-	}
-
-	@Override
-	public void removeForum(Forum f) throws DbException {
-		Transaction txn = db.startTransaction(false);
-		try {
-			for (RemoveForumHook hook : removeHooks)
-				hook.removingForum(txn, f);
-			db.removeGroup(txn, f.getGroup());
-			txn.setComplete();
-		} finally {
-			db.endTransaction(txn);
-		}
-	}
-
-	@Override
-	public void addLocalPost(ForumPost p) throws DbException {
-		try {
-			BdfDictionary meta = new BdfDictionary();
-			meta.put("timestamp", p.getMessage().getTimestamp());
-			if (p.getParent() != null) meta.put("parent", p.getParent());
-			if (p.getAuthor() != null) {
-				Author a = p.getAuthor();
-				BdfDictionary authorMeta = new BdfDictionary();
-				authorMeta.put("id", a.getId());
-				authorMeta.put("name", a.getName());
-				authorMeta.put("publicKey", a.getPublicKey());
-				meta.put("author", authorMeta);
-			}
-			meta.put("contentType", p.getContentType());
-			meta.put("local", true);
-			meta.put("read", true);
-			clientHelper.addLocalMessage(p.getMessage(), CLIENT_ID, meta, true);
-		} catch (FormatException e) {
-			throw new RuntimeException(e);
-		}
-	}
-
-	@Override
-	public Forum getForum(GroupId g) throws DbException {
-		Forum forum;
-		Transaction txn = db.startTransaction(true);
-		try {
-			forum = getForum(txn, g);
-			txn.setComplete();
-		} finally {
-			db.endTransaction(txn);
-		}
-		return forum;
-	}
-
-	@Override
-	public Forum getForum(Transaction txn, GroupId g) throws DbException {
-		try {
-			Group group = db.getGroup(txn, g);
-			return parseForum(group);
-		} catch (FormatException e) {
-			throw new DbException(e);
-		}
-	}
-
-	@Override
-	public Collection<Forum> getForums() throws DbException {
-		try {
-			Collection<Group> groups;
-			Transaction txn = db.startTransaction(true);
-			try {
-				groups = db.getGroups(txn, CLIENT_ID);
-				txn.setComplete();
-			} finally {
-				db.endTransaction(txn);
-			}
-			List<Forum> forums = new ArrayList<Forum>();
-			for (Group g : groups) forums.add(parseForum(g));
-			return Collections.unmodifiableList(forums);
-		} catch (FormatException e) {
-			throw new DbException(e);
-		}
-	}
-
-	@Override
-	public byte[] getPostBody(MessageId m) throws DbException {
-		try {
-			// Parent ID, author, content type, forum post body, signature
-			BdfList message = clientHelper.getMessageAsList(m);
-			return message.getRaw(3);
-		} catch (FormatException e) {
-			throw new DbException(e);
-		}
-	}
-
-	@Override
-	public Collection<ForumPostHeader> getPostHeaders(GroupId g)
-			throws DbException {
-		Set<AuthorId> localAuthorIds = new HashSet<AuthorId>();
-		Set<AuthorId> contactAuthorIds = new HashSet<AuthorId>();
-		Map<MessageId, BdfDictionary> metadata;
-		Transaction txn = db.startTransaction(true);
-		try {
-			// Load the IDs of the user's identities
-			for (LocalAuthor a : db.getLocalAuthors(txn))
-				localAuthorIds.add(a.getId());
-			// Load the IDs of contacts' identities
-			for (Contact c : db.getContacts(txn))
-				contactAuthorIds.add(c.getAuthor().getId());
-			// Load the metadata
-			metadata = clientHelper.getMessageMetadataAsDictionary(txn, g);
-			txn.setComplete();
-		} catch (FormatException e) {
-			throw new DbException(e);
-		} finally {
-			db.endTransaction(txn);
-		}
-		// Parse the metadata
-		Collection<ForumPostHeader> headers = new ArrayList<ForumPostHeader>();
-		for (Entry<MessageId, BdfDictionary> entry : metadata.entrySet()) {
-			try {
-				BdfDictionary meta = entry.getValue();
-				long timestamp = meta.getLong("timestamp");
-				Author author = null;
-				Author.Status authorStatus = ANONYMOUS;
-				BdfDictionary d1 = meta.getDictionary("author", null);
-				if (d1 != null) {
-					AuthorId authorId = new AuthorId(d1.getRaw("id"));
-					String name = d1.getString("name");
-					byte[] publicKey = d1.getRaw("publicKey");
-					author = new Author(authorId, name, publicKey);
-					if (localAuthorIds.contains(authorId))
-						authorStatus = VERIFIED;
-					else if (contactAuthorIds.contains(authorId))
-						authorStatus = VERIFIED;
-					else authorStatus = UNKNOWN;
-				}
-				String contentType = meta.getString("contentType");
-				boolean read = meta.getBoolean("read");
-				headers.add(new ForumPostHeader(entry.getKey(), timestamp,
-						author, authorStatus, contentType, read));
-			} catch (FormatException e) {
-				throw new DbException(e);
-			}
-		}
-		return headers;
-	}
-
-	@Override
-	public void setReadFlag(MessageId m, boolean read) throws DbException {
-		try {
-			BdfDictionary meta = new BdfDictionary();
-			meta.put("read", read);
-			clientHelper.mergeMessageMetadata(m, meta);
-		} catch (FormatException e) {
-			throw new RuntimeException(e);
-		}
-	}
-
-	@Override
-	public void registerRemoveForumHook(RemoveForumHook hook) {
-		removeHooks.add(hook);
-	}
-
-	private Forum parseForum(Group g) throws FormatException {
-		byte[] descriptor = g.getDescriptor();
-		// Name, salt
-		BdfList forum = clientHelper.toList(descriptor, 0, descriptor.length);
-		return new Forum(g, forum.getString(0), forum.getRaw(1));
-	}
-
-}
diff --git a/briar-core/src/org/briarproject/forum/ForumModule.java b/briar-core/src/org/briarproject/forum/ForumModule.java
deleted file mode 100644
index e6d7b55ac4197043c14d50185053926ea1463253..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/forum/ForumModule.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package org.briarproject.forum;
-
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.MessageQueueManager;
-import org.briarproject.api.contact.ContactManager;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.forum.ForumManager;
-import org.briarproject.api.forum.ForumPostFactory;
-import org.briarproject.api.forum.ForumSharingManager;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.sync.GroupFactory;
-import org.briarproject.api.sync.ValidationManager;
-import org.briarproject.api.system.Clock;
-
-import java.security.SecureRandom;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-import dagger.Module;
-import dagger.Provides;
-
-@Module
-public class ForumModule {
-
-	public static class EagerSingletons {
-		@Inject
-		ForumPostValidator forumPostValidator;
-		@Inject
-		ForumSharingValidator forumSharingValidator;
-		@Inject
-		ForumSharingManager forumSharingManager;
-	}
-
-	@Provides
-	@Singleton
-	ForumManager provideForumManager(DatabaseComponent db,
-			ClientHelper clientHelper,
-			GroupFactory groupFactory, SecureRandom random) {
-		return new ForumManagerImpl(db, clientHelper, groupFactory, random);
-	}
-
-	@Provides
-	ForumPostFactory provideForumPostFactory(CryptoComponent crypto,
-			ClientHelper clientHelper) {
-		return new ForumPostFactoryImpl(crypto, clientHelper);
-	}
-
-	@Provides
-	@Singleton
-	ForumPostValidator provideForumPostValidator(
-			ValidationManager validationManager, CryptoComponent crypto,
-			AuthorFactory authorFactory, ClientHelper clientHelper,
-			MetadataEncoder metadataEncoder, Clock clock) {
-		ForumPostValidator validator = new ForumPostValidator(crypto,
-				authorFactory, clientHelper, metadataEncoder, clock);
-		validationManager.registerMessageValidator(
-				ForumManagerImpl.CLIENT_ID, validator);
-		return validator;
-	}
-
-	@Provides
-	@Singleton
-	ForumSharingValidator provideSharingValidator(
-			MessageQueueManager messageQueueManager, ClientHelper clientHelper,
-			MetadataEncoder metadataEncoder, Clock clock) {
-
-		ForumSharingValidator validator = new ForumSharingValidator(clientHelper,
-				metadataEncoder, clock);
-		messageQueueManager.registerMessageValidator(
-				ForumSharingManagerImpl.CLIENT_ID, validator);
-
-		return validator;
-	}
-
-	@Provides
-	@Singleton
-	ForumSharingManager provideForumSharingManager(
-			LifecycleManager lifecycleManager,
-			ContactManager contactManager,
-			MessageQueueManager messageQueueManager,
-			ForumManager forumManager,
-			ForumSharingManagerImpl forumSharingManager) {
-
-		lifecycleManager.registerClient(forumSharingManager);
-		contactManager.registerAddContactHook(forumSharingManager);
-		contactManager.registerRemoveContactHook(forumSharingManager);
-		messageQueueManager.registerIncomingMessageHook(
-				ForumSharingManagerImpl.CLIENT_ID, forumSharingManager);
-		forumManager.registerRemoveForumHook(forumSharingManager);
-
-		return forumSharingManager;
-	}
-}
diff --git a/briar-core/src/org/briarproject/forum/ForumPostFactoryImpl.java b/briar-core/src/org/briarproject/forum/ForumPostFactoryImpl.java
deleted file mode 100644
index c3c2067f19170e3a5b41cd515deab31ad5d82b54..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/forum/ForumPostFactoryImpl.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package org.briarproject.forum;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.PrivateKey;
-import org.briarproject.api.crypto.Signature;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.forum.ForumPost;
-import org.briarproject.api.forum.ForumPostFactory;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.util.StringUtils;
-
-import java.security.GeneralSecurityException;
-
-import javax.inject.Inject;
-
-import static org.briarproject.api.forum.ForumConstants.MAX_CONTENT_TYPE_LENGTH;
-import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
-
-class ForumPostFactoryImpl implements ForumPostFactory {
-
-	private final CryptoComponent crypto;
-	private final ClientHelper clientHelper;
-
-	@Inject
-	ForumPostFactoryImpl(CryptoComponent crypto, ClientHelper clientHelper) {
-		this.crypto = crypto;
-		this.clientHelper = clientHelper;
-	}
-
-	@Override
-	public ForumPost createAnonymousPost(GroupId groupId, long timestamp,
-			MessageId parent, String contentType, byte[] body)
-			throws FormatException {
-		// Validate the arguments
-		if (StringUtils.toUtf8(contentType).length > MAX_CONTENT_TYPE_LENGTH)
-			throw new IllegalArgumentException();
-		if (body.length > MAX_FORUM_POST_BODY_LENGTH)
-			throw new IllegalArgumentException();
-		// Serialise the message
-		BdfList message = BdfList.of(parent, null, contentType, body, null);
-		Message m = clientHelper.createMessage(groupId, timestamp, message);
-		return new ForumPost(m, parent, null, contentType);
-	}
-
-	@Override
-	public ForumPost createPseudonymousPost(GroupId groupId, long timestamp,
-			MessageId parent, Author author, String contentType, byte[] body,
-			PrivateKey privateKey) throws FormatException,
-			GeneralSecurityException {
-		// Validate the arguments
-		if (StringUtils.toUtf8(contentType).length > MAX_CONTENT_TYPE_LENGTH)
-			throw new IllegalArgumentException();
-		if (body.length > MAX_FORUM_POST_BODY_LENGTH)
-			throw new IllegalArgumentException();
-		// Serialise the data to be signed
-		BdfList authorList = BdfList.of(author.getName(),
-				author.getPublicKey());
-		BdfList signed = BdfList.of(groupId, timestamp, parent, authorList,
-				contentType, body);
-		// Generate the signature
-		Signature signature = crypto.getSignature();
-		signature.initSign(privateKey);
-		signature.update(clientHelper.toByteArray(signed));
-		byte[] sig = signature.sign();
-		// Serialise the signed message
-		BdfList message = BdfList.of(parent, authorList, contentType, body,
-				sig);
-		Message m = clientHelper.createMessage(groupId, timestamp, message);
-		return new ForumPost(m, parent, author, contentType);
-	}
-}
diff --git a/briar-core/src/org/briarproject/forum/ForumPostValidator.java b/briar-core/src/org/briarproject/forum/ForumPostValidator.java
deleted file mode 100644
index 8796bb7e6d430034d3b08fefbabfe75b93fa382e..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/forum/ForumPostValidator.java
+++ /dev/null
@@ -1,116 +0,0 @@
-package org.briarproject.forum;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.UniqueId;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.KeyParser;
-import org.briarproject.api.crypto.PublicKey;
-import org.briarproject.api.crypto.Signature;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorFactory;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.system.Clock;
-import org.briarproject.clients.BdfMessageValidator;
-
-import java.security.GeneralSecurityException;
-
-import static org.briarproject.api.forum.ForumConstants.MAX_CONTENT_TYPE_LENGTH;
-import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
-import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
-import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
-import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
-
-class ForumPostValidator extends BdfMessageValidator {
-
-	private final CryptoComponent crypto;
-	private final AuthorFactory authorFactory;
-
-	ForumPostValidator(CryptoComponent crypto, AuthorFactory authorFactory,
-			ClientHelper clientHelper, MetadataEncoder metadataEncoder,
-			Clock clock) {
-		super(clientHelper, metadataEncoder, clock);
-		this.crypto = crypto;
-		this.authorFactory = authorFactory;
-	}
-
-	@Override
-	protected BdfDictionary validateMessage(Message m, Group g,
-			BdfList body) throws FormatException {
-		// Parent ID, author, content type, forum post body, signature
-		checkSize(body, 5);
-		// Parent ID is optional
-		byte[] parent = body.getOptionalRaw(0);
-		checkLength(parent, UniqueId.LENGTH);
-		// Author is optional
-		Author author = null;
-		BdfList authorList = body.getOptionalList(1);
-		if (authorList != null) {
-			// Name, public key
-			checkSize(authorList, 2);
-			String name = authorList.getString(0);
-			checkLength(name, 1, MAX_AUTHOR_NAME_LENGTH);
-			byte[] publicKey = authorList.getRaw(1);
-			checkLength(publicKey, 0, MAX_PUBLIC_KEY_LENGTH);
-			author = authorFactory.createAuthor(name, publicKey);
-		}
-		// Content type
-		String contentType = body.getString(2);
-		checkLength(contentType, 0, MAX_CONTENT_TYPE_LENGTH);
-		// Forum post body
-		byte[] forumPostBody = body.getRaw(3);
-		checkLength(forumPostBody, 0, MAX_FORUM_POST_BODY_LENGTH);
-		// Signature is optional
-		byte[] sig = body.getOptionalRaw(4);
-		checkLength(sig, 0, MAX_SIGNATURE_LENGTH);
-		// If there's an author there must be a signature and vice versa
-		if (author != null && sig == null) {
-			LOG.info("Author without signature");
-			return null;
-		}
-		if (author == null && sig != null) {
-			LOG.info("Signature without author");
-			return null;
-		}
-		// Verify the signature, if any
-		if (author != null) {
-			try {
-				// Parse the public key
-				KeyParser keyParser = crypto.getSignatureKeyParser();
-				PublicKey key = keyParser.parsePublicKey(author.getPublicKey());
-				// Serialise the data to be signed
-				BdfList signed = BdfList.of(g.getId(), m.getTimestamp(), parent,
-						authorList, contentType, forumPostBody);
-				// Verify the signature
-				Signature signature = crypto.getSignature();
-				signature.initVerify(key);
-				signature.update(clientHelper.toByteArray(signed));
-				if (!signature.verify(sig)) {
-					LOG.info("Invalid signature");
-					return null;
-				}
-			} catch (GeneralSecurityException e) {
-				LOG.info("Invalid public key");
-				return null;
-			}
-		}
-		// Return the metadata
-		BdfDictionary meta = new BdfDictionary();
-		meta.put("timestamp", m.getTimestamp());
-		if (parent != null) meta.put("parent", parent);
-		if (author != null) {
-			BdfDictionary authorMeta = new BdfDictionary();
-			authorMeta.put("id", author.getId());
-			authorMeta.put("name", author.getName());
-			authorMeta.put("publicKey", author.getPublicKey());
-			meta.put("author", authorMeta);
-		}
-		meta.put("contentType", contentType);
-		meta.put("read", false);
-		return meta;
-	}
-}
diff --git a/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java b/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java
deleted file mode 100644
index c970571a9c02523cea3db2b5844f346de72502c6..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java
+++ /dev/null
@@ -1,878 +0,0 @@
-package org.briarproject.forum;
-
-import org.briarproject.api.Bytes;
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.Client;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.MessageQueueManager;
-import org.briarproject.api.clients.PrivateGroupFactory;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.contact.ContactManager.AddContactHook;
-import org.briarproject.api.contact.ContactManager.RemoveContactHook;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfEntry;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.data.MetadataParser;
-import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Metadata;
-import org.briarproject.api.db.NoSuchMessageException;
-import org.briarproject.api.db.Transaction;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.forum.Forum;
-import org.briarproject.api.forum.ForumInvitationMessage;
-import org.briarproject.api.forum.ForumManager;
-import org.briarproject.api.forum.ForumSharingManager;
-import org.briarproject.api.forum.InviteeAction;
-import org.briarproject.api.forum.InviteeProtocolState;
-import org.briarproject.api.forum.SharerAction;
-import org.briarproject.api.forum.SharerProtocolState;
-import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.api.sync.MessageStatus;
-import org.briarproject.api.system.Clock;
-import org.briarproject.clients.BdfIncomingMessageHook;
-import org.briarproject.util.StringUtils;
-
-import java.io.IOException;
-import java.security.SecureRandom;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.logging.Logger;
-
-import javax.inject.Inject;
-
-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_NAME;
-import static org.briarproject.api.forum.ForumConstants.FORUM_SALT;
-import static org.briarproject.api.forum.ForumConstants.FORUM_SALT_LENGTH;
-import static org.briarproject.api.forum.ForumConstants.GROUP_ID;
-import static org.briarproject.api.forum.ForumConstants.INVITATION_MSG;
-import static org.briarproject.api.forum.ForumConstants.IS_SHARER;
-import static org.briarproject.api.forum.ForumConstants.LOCAL;
-import static org.briarproject.api.forum.ForumConstants.READ;
-import static org.briarproject.api.forum.ForumConstants.SESSION_ID;
-import static org.briarproject.api.forum.ForumConstants.SHARED_BY_US;
-import static org.briarproject.api.forum.ForumConstants.SHARED_WITH_US;
-import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_ABORT;
-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.STORAGE_ID;
-import static org.briarproject.api.forum.ForumConstants.TASK;
-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_FORUM_TO_LIST_SHARED_WITH_US;
-import static org.briarproject.api.forum.ForumConstants.TASK_ADD_SHARED_FORUM;
-import static org.briarproject.api.forum.ForumConstants.TASK_REMOVE_FORUM_FROM_LIST_SHARED_WITH_US;
-import static org.briarproject.api.forum.ForumConstants.TASK_REMOVE_FORUM_FROM_LIST_TO_BE_SHARED_BY_US;
-import static org.briarproject.api.forum.ForumConstants.TASK_SHARE_FORUM;
-import static org.briarproject.api.forum.ForumConstants.TASK_UNSHARE_FORUM_SHARED_BY_US;
-import static org.briarproject.api.forum.ForumConstants.TASK_UNSHARE_FORUM_SHARED_WITH_US;
-import static org.briarproject.api.forum.ForumConstants.TIME;
-import static org.briarproject.api.forum.ForumConstants.TO_BE_SHARED_BY_US;
-import static org.briarproject.api.forum.ForumConstants.TYPE;
-import static org.briarproject.api.forum.ForumManager.RemoveForumHook;
-import static org.briarproject.api.forum.InviteeProtocolState.AWAIT_INVITATION;
-import static org.briarproject.api.forum.InviteeProtocolState.AWAIT_LOCAL_RESPONSE;
-import static org.briarproject.api.forum.SharerProtocolState.PREPARE_INVITATION;
-
-class ForumSharingManagerImpl extends BdfIncomingMessageHook
-		implements ForumSharingManager, Client, RemoveForumHook,
-		AddContactHook, RemoveContactHook {
-
-	static final ClientId CLIENT_ID = new ClientId(StringUtils.fromHexString(
-			"cd11a5d04dccd9e2931d6fc3df456313"
-					+ "63bb3e9d9d0e9405fccdb051f41f5449"));
-
-	private static final Logger LOG =
-			Logger.getLogger(ForumSharingManagerImpl.class.getName());
-
-	private final DatabaseComponent db;
-	private final ForumManager forumManager;
-	private final MessageQueueManager messageQueueManager;
-	private final MetadataEncoder metadataEncoder;
-	private final SecureRandom random;
-	private final PrivateGroupFactory privateGroupFactory;
-	private final Clock clock;
-	private final Group localGroup;
-
-	@Inject
-	ForumSharingManagerImpl(DatabaseComponent db, ForumManager forumManager,
-			MessageQueueManager messageQueueManager, ClientHelper clientHelper,
-			MetadataParser metadataParser, MetadataEncoder metadataEncoder,
-			SecureRandom random, PrivateGroupFactory privateGroupFactory,
-			Clock clock) {
-
-		super(clientHelper, metadataParser);
-		this.db = db;
-		this.forumManager = forumManager;
-		this.messageQueueManager = messageQueueManager;
-		this.metadataEncoder = metadataEncoder;
-		this.random = random;
-		this.privateGroupFactory = privateGroupFactory;
-		this.clock = clock;
-		localGroup = privateGroupFactory.createLocalGroup(getClientId());
-	}
-
-	@Override
-	public void createLocalState(Transaction txn) throws DbException {
-		db.addGroup(txn, localGroup);
-		// Ensure we've set things up for any pre-existing contacts
-		for (Contact c : db.getContacts(txn)) addingContact(txn, c);
-	}
-
-	@Override
-	public void addingContact(Transaction txn, Contact c) throws DbException {
-		try {
-			// Create a group to share with the contact
-			Group g = getContactGroup(c);
-			// Return if we've already set things up for this contact
-			if (db.containsGroup(txn, g.getId())) return;
-			// Store the group and share it with the contact
-			db.addGroup(txn, g);
-			db.setVisibleToContact(txn, c.getId(), g.getId(), true);
-			// Attach the contact ID to the group
-			BdfDictionary meta = new BdfDictionary();
-			meta.put(CONTACT_ID, c.getId().getInt());
-			meta.put(TO_BE_SHARED_BY_US, new BdfList());
-			meta.put(SHARED_BY_US, new BdfList());
-			meta.put(SHARED_WITH_US, new BdfList());
-			clientHelper.mergeGroupMetadata(txn, g.getId(), meta);
-		} catch (FormatException e) {
-			throw new DbException(e);
-		}
-	}
-
-	@Override
-	public void removingContact(Transaction txn, Contact c) throws DbException {
-		// 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());
-			for (Map.Entry<MessageId, BdfDictionary> entry : map.entrySet()) {
-				BdfDictionary d = entry.getValue();
-				if (id.equals(d.getLong(CONTACT_ID))) {
-					deleteMessage(txn, entry.getKey());
-				}
-			}
-		} catch (FormatException e) {
-			if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
-		}
-
-		// remove the contact group (all messages will be removed with it)
-		db.removeGroup(txn, getContactGroup(c));
-	}
-
-	@Override
-	protected void incomingMessage(Transaction txn, Message m, BdfList body,
-			BdfDictionary msg) throws DbException, FormatException {
-
-		SessionId sessionId = new SessionId(msg.getRaw(SESSION_ID));
-		long type = msg.getLong(TYPE);
-		if (type == SHARE_MSG_TYPE_INVITATION) {
-			// we are an invitee who just received a new invitation
-			boolean stateExists = true;
-			try {
-				// check if we have a session with that ID already
-				getSessionState(txn, sessionId, false);
-			} catch (FormatException e) {
-				// this is what we would expect under normal circumstances
-				stateExists = false;
-			}
-			try {
-				// check if we already have a state with that sessionId
-				if (stateExists) throw new FormatException();
-
-				// check if forum can be shared
-				Forum f = forumManager.createForum(msg.getString(FORUM_NAME),
-						msg.getRaw(FORUM_SALT));
-				ContactId contactId = getContactId(txn, m.getGroupId());
-				Contact contact = db.getContact(txn, contactId);
-				if (!canBeShared(txn, f.getId(), contact))
-					throw new FormatException();
-
-				// initialize state and process invitation
-				BdfDictionary state =
-						initializeInviteeState(txn, contactId, msg);
-				InviteeEngine engine = new InviteeEngine();
-				processStateUpdate(txn, m.getId(),
-						engine.onMessageReceived(state, msg));
-			} catch (FormatException e) {
-				if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
-				deleteMessage(txn, m.getId());
-			}
-		} else if (type == SHARE_MSG_TYPE_ACCEPT ||
-				type == SHARE_MSG_TYPE_DECLINE) {
-			// we are a sharer who just received a response
-			BdfDictionary state = getSessionState(txn, sessionId, true);
-			SharerEngine engine = new SharerEngine();
-			processStateUpdate(txn, m.getId(),
-					engine.onMessageReceived(state, msg));
-		} else if (type == SHARE_MSG_TYPE_LEAVE ||
-				type == SHARE_MSG_TYPE_ABORT) {
-			// we don't know who we are, so figure it out
-			BdfDictionary state = getSessionState(txn, sessionId, true);
-			if (state.getBoolean(IS_SHARER)) {
-				// we are a sharer and the invitee wants to leave or abort
-				SharerEngine engine = new SharerEngine();
-				processStateUpdate(txn, m.getId(),
-						engine.onMessageReceived(state, msg));
-			} else {
-				// we are an invitee and the sharer wants to leave or abort
-				InviteeEngine engine = new InviteeEngine();
-				processStateUpdate(txn, m.getId(),
-						engine.onMessageReceived(state, msg));
-			}
-		} else {
-			// message has passed validator, so that should never happen
-			throw new RuntimeException("Illegal Forum Sharing Message");
-		}
-	}
-
-	@Override
-	public ClientId getClientId() {
-		return CLIENT_ID;
-	}
-
-	@Override
-	public void sendForumInvitation(GroupId groupId, ContactId contactId,
-			String msg) throws DbException {
-
-		Transaction txn = db.startTransaction(false);
-		try {
-			// initialize local state for sharer
-			Forum f = forumManager.getForum(txn, groupId);
-			BdfDictionary localState = initializeSharerState(txn, f, contactId);
-
-			// define action
-			BdfDictionary localAction = new BdfDictionary();
-			localAction.put(TYPE, SHARE_MSG_TYPE_INVITATION);
-			if (!StringUtils.isNullOrEmpty(msg)) {
-				localAction.put(INVITATION_MSG, msg);
-			}
-
-			// start engine and process its state update
-			SharerEngine engine = new SharerEngine();
-			processStateUpdate(txn, null,
-					engine.onLocalAction(localState, localAction));
-
-			txn.setComplete();
-		} catch (FormatException e) {
-			throw new DbException();
-		} finally {
-			db.endTransaction(txn);
-		}
-	}
-
-	@Override
-	public void respondToInvitation(Forum f, boolean accept)
-			throws DbException {
-
-		Transaction txn = db.startTransaction(false);
-		try {
-			// find session state based on forum
-			BdfDictionary localState = getSessionStateForResponse(txn, f);
-
-			// define action
-			BdfDictionary localAction = new BdfDictionary();
-			if (accept) {
-				localAction.put(TYPE, SHARE_MSG_TYPE_ACCEPT);
-			} else {
-				localAction.put(TYPE, SHARE_MSG_TYPE_DECLINE);
-			}
-
-			// start engine and process its state update
-			InviteeEngine engine = new InviteeEngine();
-			processStateUpdate(txn, null,
-					engine.onLocalAction(localState, localAction));
-
-			txn.setComplete();
-		} catch (FormatException e) {
-			throw new DbException(e);
-		} finally {
-			db.endTransaction(txn);
-		}
-	}
-
-	@Override
-	public Collection<ForumInvitationMessage> getForumInvitationMessages(
-			ContactId contactId) throws DbException {
-
-		Transaction txn = db.startTransaction(false);
-		try {
-			Contact contact = db.getContact(txn, contactId);
-			Group group = getContactGroup(contact);
-
-			Collection<ForumInvitationMessage> list =
-					new ArrayList<ForumInvitationMessage>();
-			Map<MessageId, BdfDictionary> map = clientHelper
-					.getMessageMetadataAsDictionary(txn, group.getId());
-			for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) {
-				BdfDictionary msg = m.getValue();
-				try {
-					if (msg.getLong(TYPE) != SHARE_MSG_TYPE_INVITATION)
-						continue;
-
-					MessageStatus status =
-							db.getMessageStatus(txn, contactId, m.getKey());
-					SessionId sessionId = new SessionId(msg.getRaw(SESSION_ID));
-					String name = msg.getString(FORUM_NAME);
-					String message = msg.getOptionalString(INVITATION_MSG);
-					long time = msg.getLong(TIME);
-					boolean local = msg.getBoolean(LOCAL);
-					boolean read = msg.getBoolean(READ, false);
-					boolean available = false;
-					if (!local) {
-						// figure out whether the forum is still available
-						BdfDictionary sessionState =
-								getSessionState(txn, sessionId, true);
-						InviteeProtocolState state = InviteeProtocolState
-								.fromValue(
-										sessionState.getLong(STATE).intValue());
-						available = state == AWAIT_LOCAL_RESPONSE;
-					}
-					ForumInvitationMessage im =
-							new ForumInvitationMessage(m.getKey(), sessionId,
-									contactId, name, message, available, time,
-									local, status.isSent(), status.isSeen(),
-									read);
-					list.add(im);
-				} catch (FormatException e) {
-					if (LOG.isLoggable(WARNING))
-						LOG.log(WARNING, e.toString(), e);
-				}
-			}
-			txn.setComplete();
-			return list;
-		} catch (FormatException e) {
-			throw new DbException(e);
-		} finally {
-			db.endTransaction(txn);
-		}
-	}
-
-	@Override
-	public void removingForum(Transaction txn, Forum f) throws DbException {
-		try {
-			for (Contact c : db.getContacts(txn)) {
-				GroupId g = getContactGroup(c).getId();
-				if (removeFromList(txn, g, TO_BE_SHARED_BY_US, f)) {
-					leaveForum(txn, c.getId(), f);
-				}
-				if (removeFromList(txn, g, SHARED_BY_US, f)) {
-					leaveForum(txn, c.getId(), f);
-				}
-				if (removeFromList(txn, g, SHARED_WITH_US, f)) {
-					leaveForum(txn, c.getId(), f);
-				}
-			}
-		} catch (IOException e) {
-			throw new DbException(e);
-		}
-	}
-
-	@Override
-	public Collection<Forum> getAvailableForums() throws DbException {
-		try {
-			Set<Forum> available = new HashSet<Forum>();
-			Transaction txn = db.startTransaction(true);
-			try {
-				// Get any forums we subscribe to
-				Set<Group> subscribed = new HashSet<Group>(db.getGroups(txn,
-						forumManager.getClientId()));
-				// Get all forums shared by contacts
-				for (Contact c : db.getContacts(txn)) {
-					Group g = getContactGroup(c);
-					List<Forum> forums =
-							getForumList(txn, g.getId(), SHARED_WITH_US);
-					for (Forum f : forums) {
-						if (!subscribed.contains(f.getGroup()))
-							available.add(f);
-					}
-				}
-				txn.setComplete();
-			} finally {
-				db.endTransaction(txn);
-			}
-			return Collections.unmodifiableSet(available);
-		} catch (IOException e) {
-			throw new DbException(e);
-		}
-	}
-
-	@Override
-	public Collection<Contact> getSharedBy(GroupId g) throws DbException {
-		try {
-			List<Contact> subscribers = new ArrayList<Contact>();
-			Transaction txn = db.startTransaction(true);
-			try {
-				for (Contact c : db.getContacts(txn)) {
-					GroupId contactGroup = getContactGroup(c).getId();
-					if (listContains(txn, contactGroup, g, SHARED_WITH_US))
-						subscribers.add(c);
-				}
-				txn.setComplete();
-			} finally {
-				db.endTransaction(txn);
-			}
-			return Collections.unmodifiableList(subscribers);
-		} catch (IOException e) {
-			throw new DbException(e);
-		}
-	}
-
-	@Override
-	public Collection<ContactId> getSharedWith(GroupId g) throws DbException {
-		try {
-			List<ContactId> shared = new ArrayList<ContactId>();
-			Transaction txn = db.startTransaction(true);
-			try {
-				for (Contact c : db.getContacts(txn)) {
-					GroupId contactGroup = getContactGroup(c).getId();
-					if (listContains(txn, contactGroup, g, SHARED_BY_US))
-						shared.add(c.getId());
-				}
-				txn.setComplete();
-			} finally {
-				db.endTransaction(txn);
-			}
-			return Collections.unmodifiableList(shared);
-		} catch (FormatException e) {
-			throw new DbException(e);
-		}
-	}
-
-	@Override
-	public boolean canBeShared(GroupId g, Contact c) throws DbException {
-		boolean canBeShared;
-		Transaction txn = db.startTransaction(true);
-		try {
-			canBeShared = canBeShared(txn, g, c);
-			txn.setComplete();
-		} finally {
-			db.endTransaction(txn);
-		}
-		return canBeShared;
-	}
-
-	private boolean canBeShared(Transaction txn, GroupId g, Contact c)
-			throws DbException {
-
-		try {
-			GroupId contactGroup = getContactGroup(c).getId();
-			return !listContains(txn, contactGroup, g, SHARED_BY_US) &&
-					!listContains(txn, contactGroup, g, SHARED_WITH_US) &&
-					!listContains(txn, contactGroup, g, TO_BE_SHARED_BY_US);
-		} catch (FormatException e) {
-			throw new DbException(e);
-		}
-	}
-
-	private BdfDictionary initializeSharerState(Transaction txn, Forum f,
-			ContactId contactId) throws FormatException, DbException {
-
-		Contact c = db.getContact(txn, contactId);
-		Group group = getContactGroup(c);
-
-		// create local message to keep engine state
-		long now = clock.currentTimeMillis();
-		Bytes salt = new Bytes(new byte[FORUM_SALT_LENGTH]);
-		random.nextBytes(salt.getBytes());
-		Message m = clientHelper.createMessage(localGroup.getId(), now,
-				BdfList.of(salt));
-		MessageId sessionId = m.getId();
-
-		BdfDictionary d = new BdfDictionary();
-		d.put(SESSION_ID, sessionId);
-		d.put(STORAGE_ID, sessionId);
-		d.put(GROUP_ID, group.getId());
-		d.put(IS_SHARER, true);
-		d.put(STATE, PREPARE_INVITATION.getValue());
-		d.put(CONTACT_ID, contactId.getInt());
-		d.put(FORUM_ID, f.getId());
-		d.put(FORUM_NAME, f.getName());
-		d.put(FORUM_SALT, f.getSalt());
-
-		// save local state to database
-		clientHelper.addLocalMessage(txn, m, getClientId(), d, false);
-
-		return d;
-	}
-
-	private BdfDictionary initializeInviteeState(Transaction txn,
-			ContactId contactId, BdfDictionary msg)
-			throws FormatException, DbException {
-
-		Contact c = db.getContact(txn, contactId);
-		Group group = getContactGroup(c);
-		String name = msg.getString(FORUM_NAME);
-		byte[] salt = msg.getRaw(FORUM_SALT);
-		Forum f = forumManager.createForum(name, salt);
-
-		// create local message to keep engine state
-		long now = clock.currentTimeMillis();
-		Bytes mSalt = new Bytes(new byte[FORUM_SALT_LENGTH]);
-		random.nextBytes(mSalt.getBytes());
-		Message m = clientHelper.createMessage(localGroup.getId(), now,
-				BdfList.of(mSalt));
-
-		BdfDictionary d = new BdfDictionary();
-		d.put(SESSION_ID, msg.getRaw(SESSION_ID));
-		d.put(STORAGE_ID, m.getId());
-		d.put(GROUP_ID, group.getId());
-		d.put(IS_SHARER, false);
-		d.put(STATE, AWAIT_INVITATION.getValue());
-		d.put(CONTACT_ID, contactId.getInt());
-		d.put(FORUM_ID, f.getId());
-		d.put(FORUM_NAME, name);
-		d.put(FORUM_SALT, salt);
-
-		// save local state to database
-		clientHelper.addLocalMessage(txn, m, getClientId(), d, false);
-
-		return d;
-	}
-
-	private BdfDictionary getSessionState(Transaction txn, SessionId sessionId,
-			boolean warn) throws DbException, FormatException {
-
-		try {
-			// we should be able to get the sharer state directly from sessionId
-			return clientHelper.getMessageMetadataAsDictionary(txn, sessionId);
-		} catch (NoSuchMessageException e) {
-			// State not found directly, so iterate over all states
-			// to find state for invitee
-			Map<MessageId, BdfDictionary> map = clientHelper
-					.getMessageMetadataAsDictionary(txn, localGroup.getId());
-			for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) {
-				BdfDictionary state = m.getValue();
-				if (Arrays.equals(state.getRaw(SESSION_ID),
-						sessionId.getBytes())) {
-					return state;
-				}
-			}
-			if (warn && LOG.isLoggable(WARNING)) {
-				LOG.warning(
-						"No session state found for message with session ID " +
-								Arrays.hashCode(sessionId.getBytes()));
-			}
-			throw new FormatException();
-		}
-	}
-
-	private BdfDictionary getSessionStateForResponse(Transaction txn, Forum f)
-			throws DbException, FormatException {
-
-		Map<MessageId, BdfDictionary> map = clientHelper
-				.getMessageMetadataAsDictionary(txn, localGroup.getId());
-		for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) {
-			BdfDictionary d = m.getValue();
-			try {
-				InviteeProtocolState state = InviteeProtocolState
-						.fromValue(d.getLong(STATE).intValue());
-				if (state == AWAIT_LOCAL_RESPONSE) {
-					byte[] id = d.getRaw(FORUM_ID);
-					if (Arrays.equals(f.getId().getBytes(), id)) {
-						// Note that there should always be only one session
-						// in this state for the same forum
-						return d;
-					}
-				}
-			} catch (FormatException e) {
-				if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
-			}
-		}
-		throw new DbException();
-	}
-
-	private BdfDictionary getSessionStateForLeaving(Transaction txn, Forum f,
-			ContactId c) throws DbException, FormatException {
-
-		Map<MessageId, BdfDictionary> map = clientHelper
-				.getMessageMetadataAsDictionary(txn, localGroup.getId());
-		for (Map.Entry<MessageId, BdfDictionary> m : map.entrySet()) {
-			BdfDictionary d = m.getValue();
-			try {
-				// check that this session is with the right contact
-				if (c.getInt() != d.getLong(CONTACT_ID)) continue;
-				// check that a forum get be left in current session
-				int intState = d.getLong(STATE).intValue();
-				if (d.getBoolean(IS_SHARER)) {
-					SharerProtocolState state =
-							SharerProtocolState.fromValue(intState);
-					if (state.next(SharerAction.LOCAL_LEAVE) ==
-							SharerProtocolState.ERROR) continue;
-				} else {
-					InviteeProtocolState state = InviteeProtocolState
-							.fromValue(intState);
-					if (state.next(InviteeAction.LOCAL_LEAVE) ==
-							InviteeProtocolState.ERROR) continue;
-				}
-				// check that this state actually concerns this forum
-				String name = d.getString(FORUM_NAME);
-				byte[] salt = d.getRaw(FORUM_SALT);
-				if (name.equals(f.getName()) &&
-						Arrays.equals(salt, f.getSalt())) {
-					// TODO what happens when there is more than one invitation?
-					return d;
-				}
-			} catch (FormatException e) {
-				if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
-			}
-		}
-		throw new FormatException();
-	}
-
-	private void processStateUpdate(Transaction txn, MessageId messageId,
-			StateUpdate<BdfDictionary, BdfDictionary> result)
-			throws DbException, FormatException {
-
-		// perform actions based on new local state
-		performTasks(txn, result.localState);
-
-		// save new local state
-		MessageId storageId =
-				new MessageId(result.localState.getRaw(STORAGE_ID));
-		clientHelper.mergeMessageMetadata(txn, storageId, result.localState);
-
-		// send messages
-		for (BdfDictionary d : result.toSend) {
-			sendMessage(txn, d);
-		}
-
-		// broadcast events
-		for (Event event : result.toBroadcast) {
-			txn.attach(event);
-		}
-
-		// delete message
-		if (result.deleteMessage && messageId != null) {
-			if (LOG.isLoggable(INFO)) {
-				LOG.info("Deleting message with id " + messageId.hashCode());
-			}
-			db.deleteMessage(txn, messageId);
-			db.deleteMessageMetadata(txn, messageId);
-		}
-	}
-
-	private void performTasks(Transaction txn, BdfDictionary localState)
-			throws FormatException, DbException {
-
-		if (!localState.containsKey(TASK)) return;
-
-		// remember task and remove it from localState
-		long task = localState.getLong(TASK);
-		localState.put(TASK, BdfDictionary.NULL_VALUE);
-
-		// get group ID for later
-		GroupId groupId = new GroupId(localState.getRaw(GROUP_ID));
-		// get contact ID for later
-		ContactId contactId =
-				new ContactId(localState.getLong(CONTACT_ID).intValue());
-
-		// get forum for later
-		String name = localState.getString(FORUM_NAME);
-		byte[] salt = localState.getRaw(FORUM_SALT);
-		Forum f = forumManager.createForum(name, salt);
-
-		// perform tasks
-		if (task == TASK_ADD_FORUM_TO_LIST_SHARED_WITH_US) {
-			addToList(txn, groupId, SHARED_WITH_US, f);
-		}
-		else if (task == TASK_REMOVE_FORUM_FROM_LIST_SHARED_WITH_US) {
-			removeFromList(txn, groupId, SHARED_WITH_US, f);
-		}
-		else if (task == TASK_ADD_SHARED_FORUM) {
-			db.addGroup(txn, f.getGroup());
-			db.setVisibleToContact(txn, contactId, f.getId(), true);
-		}
-		else if (task == TASK_ADD_FORUM_TO_LIST_TO_BE_SHARED_BY_US) {
-			addToList(txn, groupId, TO_BE_SHARED_BY_US, f);
-		}
-		else if (task == TASK_REMOVE_FORUM_FROM_LIST_TO_BE_SHARED_BY_US) {
-			removeFromList(txn, groupId, TO_BE_SHARED_BY_US, f);
-		}
-		else if (task == TASK_SHARE_FORUM) {
-			db.setVisibleToContact(txn, contactId, f.getId(), true);
-			removeFromList(txn, groupId, TO_BE_SHARED_BY_US, f);
-			addToList(txn, groupId, SHARED_BY_US, f);
-		}
-		else if (task == TASK_UNSHARE_FORUM_SHARED_BY_US) {
-			db.setVisibleToContact(txn, contactId, f.getId(), false);
-			removeFromList(txn, groupId, SHARED_BY_US, f);
-		} else if (task == TASK_UNSHARE_FORUM_SHARED_WITH_US) {
-			db.setVisibleToContact(txn, contactId, f.getId(), false);
-			removeFromList(txn, groupId, SHARED_WITH_US, f);
-		}
-	}
-
-	private void sendMessage(Transaction txn, BdfDictionary m)
-			throws FormatException, DbException {
-
-		BdfList list = encodeMessage(m);
-		byte[] body = clientHelper.toByteArray(list);
-		GroupId groupId = new GroupId(m.getRaw(GROUP_ID));
-		Group group = db.getGroup(txn, groupId);
-		long timestamp = clock.currentTimeMillis();
-
-		// add message itself as metadata
-		m.put(LOCAL, true);
-		m.put(TIME, timestamp);
-		Metadata meta = metadataEncoder.encode(m);
-
-		messageQueueManager
-				.sendMessage(txn, group, timestamp, body, meta);
-	}
-
-	private BdfList encodeMessage(BdfDictionary m) throws FormatException {
-		long type = m.getLong(TYPE);
-
-		BdfList list;
-		if (type == SHARE_MSG_TYPE_INVITATION) {
-			list = BdfList.of(type,
-					m.getRaw(SESSION_ID),
-					m.getString(FORUM_NAME),
-					m.getRaw(FORUM_SALT)
-			);
-			String msg = m.getOptionalString(INVITATION_MSG);
-			if (msg != null) list.add(msg);
-		} else if (type == SHARE_MSG_TYPE_ACCEPT) {
-			list = BdfList.of(type, m.getRaw(SESSION_ID));
-		} else if (type == SHARE_MSG_TYPE_DECLINE) {
-			list = BdfList.of(type, m.getRaw(SESSION_ID));
-		} else if (type == SHARE_MSG_TYPE_LEAVE) {
-			list = BdfList.of(type, m.getRaw(SESSION_ID));
-		} else if (type == SHARE_MSG_TYPE_ABORT) {
-			list = BdfList.of(type, m.getRaw(SESSION_ID));
-		} else {
-			throw new FormatException();
-		}
-		return list;
-	}
-
-	private Group getContactGroup(Contact c) {
-		return privateGroupFactory.createPrivateGroup(CLIENT_ID, c);
-	}
-
-	private ContactId getContactId(Transaction txn, GroupId contactGroupId)
-			throws DbException, FormatException {
-		BdfDictionary meta = clientHelper.getGroupMetadataAsDictionary(txn,
-				contactGroupId);
-		return new ContactId(meta.getLong(CONTACT_ID).intValue());
-	}
-
-	private void leaveForum(Transaction txn, ContactId c, Forum f)
-			throws DbException, FormatException {
-
-		BdfDictionary state = getSessionStateForLeaving(txn, f, c);
-		BdfDictionary action = new BdfDictionary();
-		action.put(TYPE, SHARE_MSG_TYPE_LEAVE);
-		if (state.getBoolean(IS_SHARER)) {
-			SharerEngine engine = new SharerEngine();
-			processStateUpdate(txn, null,
-					engine.onLocalAction(state, action));
-		} else {
-			InviteeEngine engine = new InviteeEngine();
-			processStateUpdate(txn, null,
-					engine.onLocalAction(state, action));
-		}
-	}
-
-	private boolean listContains(Transaction txn, GroupId contactGroup,
-			GroupId forum, String key) throws DbException, FormatException {
-
-		List<Forum> list = getForumList(txn, contactGroup, key);
-		for (Forum f : list) {
-			if (f.getId().equals(forum)) return true;
-		}
-		return false;
-	}
-
-	private boolean addToList(Transaction txn, GroupId groupId, String key,
-			Forum f) throws DbException, FormatException {
-
-		List<Forum> forums = getForumList(txn, groupId, key);
-		if (forums.contains(f)) return false;
-		forums.add(f);
-		storeForumList(txn, groupId, key, forums);
-		return true;
-	}
-
-	private boolean removeFromList(Transaction txn, GroupId groupId, String key,
-			Forum f) throws DbException, FormatException {
-
-		List<Forum> forums = getForumList(txn, groupId, key);
-		if (forums.remove(f)) {
-			storeForumList(txn, groupId, key, forums);
-			return true;
-		}
-		return false;
-	}
-
-	private List<Forum> getForumList(Transaction txn, GroupId groupId,
-			String key) throws DbException, FormatException {
-
-		BdfDictionary metadata =
-				clientHelper.getGroupMetadataAsDictionary(txn, groupId);
-		BdfList list = metadata.getList(key);
-
-		return parseForumList(list);
-	}
-
-	private void storeForumList(Transaction txn, GroupId groupId, String key,
-			List<Forum> forums)	throws DbException, FormatException {
-
-		BdfList list = encodeForumList(forums);
-		BdfDictionary metadata = BdfDictionary.of(
-				new BdfEntry(key, list)
-		);
-		clientHelper.mergeGroupMetadata(txn, groupId, metadata);
-	}
-
-	private BdfList encodeForumList(List<Forum> forums) {
-		BdfList forumList = new BdfList();
-		for (Forum f : forums)
-			forumList.add(BdfList.of(f.getName(), f.getSalt()));
-		return forumList;
-	}
-
-	private List<Forum> parseForumList(BdfList list) throws FormatException {
-		List<Forum> forums = new ArrayList<Forum>(list.size());
-		for (int i = 0; i < list.size(); i++) {
-			BdfList forum = list.getList(i);
-			forums.add(forumManager
-					.createForum(forum.getString(0), forum.getRaw(1)));
-		}
-		return forums;
-	}
-
-	private void deleteMessage(Transaction txn, MessageId messageId)
-			throws DbException {
-
-		if (LOG.isLoggable(INFO))
-			LOG.info("Deleting message with ID: " + messageId.hashCode());
-
-		db.deleteMessage(txn, messageId);
-		db.deleteMessageMetadata(txn, messageId);
-	}
-
-}
diff --git a/briar-core/src/org/briarproject/forum/ForumSharingValidator.java b/briar-core/src/org/briarproject/forum/ForumSharingValidator.java
deleted file mode 100644
index c204623a27dee2dc193befcaaad12ec915a12cba..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/forum/ForumSharingValidator.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package org.briarproject.forum;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
-import org.briarproject.api.clients.SessionId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
-import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.Message;
-import org.briarproject.api.system.Clock;
-import org.briarproject.clients.BdfMessageValidator;
-
-import static org.briarproject.api.forum.ForumConstants.FORUM_NAME;
-import static org.briarproject.api.forum.ForumConstants.FORUM_SALT;
-import static org.briarproject.api.forum.ForumConstants.FORUM_SALT_LENGTH;
-import static org.briarproject.api.forum.ForumConstants.GROUP_ID;
-import static org.briarproject.api.forum.ForumConstants.INVITATION_MSG;
-import static org.briarproject.api.forum.ForumConstants.LOCAL;
-import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH;
-import static org.briarproject.api.forum.ForumConstants.SESSION_ID;
-import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_ABORT;
-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.TIME;
-import static org.briarproject.api.forum.ForumConstants.TYPE;
-import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
-
-class ForumSharingValidator extends BdfMessageValidator {
-
-	ForumSharingValidator(ClientHelper clientHelper,
-			MetadataEncoder metadataEncoder, Clock clock) {
-		super(clientHelper, metadataEncoder, clock);
-	}
-
-	@Override
-	protected BdfDictionary validateMessage(Message m, Group g,
-			BdfList body) throws FormatException {
-
-		BdfDictionary d = new BdfDictionary();
-		long type = body.getLong(0);
-		byte[] id = body.getRaw(1);
-		checkLength(id, SessionId.LENGTH);
-
-		if (type == SHARE_MSG_TYPE_INVITATION) {
-			checkSize(body, 4, 5);
-
-			String name = body.getString(2);
-			checkLength(name, 1, MAX_FORUM_NAME_LENGTH);
-
-			byte[] salt = body.getRaw(3);
-			checkLength(salt, FORUM_SALT_LENGTH);
-
-			d.put(FORUM_NAME, name);
-			d.put(FORUM_SALT, salt);
-
-			if (body.size() > 4) {
-				String msg = body.getString(4);
-				checkLength(msg, 0, MAX_MESSAGE_BODY_LENGTH);
-				d.put(INVITATION_MSG, msg);
-			}
-		} else {
-			checkSize(body, 2);
-			if (type != SHARE_MSG_TYPE_ACCEPT &&
-					type != SHARE_MSG_TYPE_DECLINE &&
-					type != SHARE_MSG_TYPE_LEAVE &&
-					type != SHARE_MSG_TYPE_ABORT) {
-				throw new FormatException();
-			}
-		}
-		// Return the metadata
-		d.put(TYPE, type);
-		d.put(SESSION_ID, id);
-		d.put(GROUP_ID, m.getGroupId());
-		d.put(LOCAL, false);
-		d.put(TIME, m.getTimestamp());
-		return d;
-	}
-}
diff --git a/briar-core/src/org/briarproject/forum/InviteeEngine.java b/briar-core/src/org/briarproject/forum/InviteeEngine.java
deleted file mode 100644
index f208204db66386c080a5511a2ed75445879583e3..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/forum/InviteeEngine.java
+++ /dev/null
@@ -1,265 +0,0 @@
-package org.briarproject.forum;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ProtocolEngine;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfEntry;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.ForumInvitationReceivedEvent;
-import org.briarproject.api.forum.Forum;
-import org.briarproject.api.forum.InviteeAction;
-import org.briarproject.api.forum.InviteeProtocolState;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.logging.Logger;
-
-import static java.util.logging.Level.INFO;
-import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.forum.ForumConstants.CONTACT_ID;
-import static org.briarproject.api.forum.ForumConstants.FORUM_NAME;
-import static org.briarproject.api.forum.ForumConstants.FORUM_SALT;
-import static org.briarproject.api.forum.ForumConstants.GROUP_ID;
-import static org.briarproject.api.forum.ForumConstants.SESSION_ID;
-import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_ABORT;
-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;
-import static org.briarproject.api.forum.ForumConstants.TASK_ADD_FORUM_TO_LIST_SHARED_WITH_US;
-import static org.briarproject.api.forum.ForumConstants.TASK_ADD_SHARED_FORUM;
-import static org.briarproject.api.forum.ForumConstants.TASK_REMOVE_FORUM_FROM_LIST_SHARED_WITH_US;
-import static org.briarproject.api.forum.ForumConstants.TASK_UNSHARE_FORUM_SHARED_WITH_US;
-import static org.briarproject.api.forum.ForumConstants.TYPE;
-import static org.briarproject.api.forum.InviteeAction.LOCAL_ABORT;
-import static org.briarproject.api.forum.InviteeAction.LOCAL_ACCEPT;
-import static org.briarproject.api.forum.InviteeAction.LOCAL_DECLINE;
-import static org.briarproject.api.forum.InviteeAction.LOCAL_LEAVE;
-import static org.briarproject.api.forum.InviteeAction.REMOTE_INVITATION;
-import static org.briarproject.api.forum.InviteeAction.REMOTE_LEAVE;
-import static org.briarproject.api.forum.InviteeProtocolState.ERROR;
-import static org.briarproject.api.forum.InviteeProtocolState.FINISHED;
-import static org.briarproject.api.forum.InviteeProtocolState.LEFT;
-
-public class InviteeEngine
-		implements ProtocolEngine<BdfDictionary, BdfDictionary, BdfDictionary> {
-
-	private static final Logger LOG =
-			Logger.getLogger(SharerEngine.class.getName());
-
-	@Override
-	public StateUpdate<BdfDictionary, BdfDictionary> onLocalAction(
-			BdfDictionary localState, BdfDictionary localAction) {
-
-		try {
-			InviteeProtocolState currentState =
-					getState(localState.getLong(STATE));
-			long type = localAction.getLong(TYPE);
-			InviteeAction action = InviteeAction.getLocal(type);
-			InviteeProtocolState nextState = currentState.next(action);
-			localState.put(STATE, nextState.getValue());
-
-			if (action == LOCAL_ABORT && currentState != ERROR) {
-				return abortSession(currentState, localState);
-			}
-
-			if (nextState == ERROR) {
-				if (LOG.isLoggable(WARNING)) {
-					LOG.warning("Error: Invalid action in state " +
-							currentState.name());
-				}
-				return noUpdate(localState, true);
-			}
-			List<BdfDictionary> messages;
-			List<Event> events = Collections.emptyList();
-
-			if (action == LOCAL_ACCEPT || action == LOCAL_DECLINE) {
-				BdfDictionary msg = BdfDictionary.of(
-						new BdfEntry(SESSION_ID, localState.getRaw(SESSION_ID)),
-						new BdfEntry(GROUP_ID, localState.getRaw(GROUP_ID))
-				);
-				if (action == LOCAL_ACCEPT) {
-					localState.put(TASK, TASK_ADD_SHARED_FORUM);
-					msg.put(TYPE, SHARE_MSG_TYPE_ACCEPT);
-				} else {
-					localState.put(TASK,
-							TASK_REMOVE_FORUM_FROM_LIST_SHARED_WITH_US);
-					msg.put(TYPE, SHARE_MSG_TYPE_DECLINE);
-				}
-				messages = Collections.singletonList(msg);
-				logLocalAction(currentState, localState, msg);
-			}
-			else if (action == LOCAL_LEAVE) {
-				BdfDictionary msg = new BdfDictionary();
-				msg.put(TYPE, SHARE_MSG_TYPE_LEAVE);
-				msg.put(SESSION_ID, localState.getRaw(SESSION_ID));
-				msg.put(GROUP_ID, localState.getRaw(GROUP_ID));
-				messages = Collections.singletonList(msg);
-				logLocalAction(currentState, localState, msg);
-			}
-			else {
-				throw new IllegalArgumentException("Unknown Local Action");
-			}
-			return new StateUpdate<BdfDictionary, BdfDictionary>(false,
-					false, localState, messages, events);
-		} catch (FormatException e) {
-			throw new IllegalArgumentException(e);
-		}
-	}
-
-	@Override
-	public StateUpdate<BdfDictionary, BdfDictionary> onMessageReceived(
-			BdfDictionary localState, BdfDictionary msg) {
-
-		try {
-			InviteeProtocolState currentState =
-					getState(localState.getLong(STATE));
-			long type = msg.getLong(TYPE);
-			InviteeAction action = InviteeAction.getRemote(type);
-			InviteeProtocolState nextState = currentState.next(action);
-			localState.put(STATE, nextState.getValue());
-
-			logMessageReceived(currentState, nextState, type, msg);
-
-			if (nextState == ERROR) {
-				if (currentState != ERROR) {
-					return abortSession(currentState, localState);
-				} else {
-					return noUpdate(localState, true);
-				}
-			}
-
-			List<BdfDictionary> messages = Collections.emptyList();
-			List<Event> events = Collections.emptyList();
-			boolean deleteMsg = false;
-
-			if (currentState == LEFT) {
-				// ignore and delete messages coming in while in that state
-				deleteMsg = true;
-			}
-			// the sharer left the forum she had shared with us
-			else if (action == REMOTE_LEAVE && currentState == FINISHED) {
-				localState.put(TASK, TASK_UNSHARE_FORUM_SHARED_WITH_US);
-			}
-			else if (currentState == FINISHED) {
-				// ignore and delete messages coming in while in that state
-				// note that LEAVE is possible, but was handled above
-				deleteMsg = true;
-			}
-			// the sharer left the forum before we couldn't even respond
-			else if (action == REMOTE_LEAVE) {
-				localState.put(TASK, TASK_REMOVE_FORUM_FROM_LIST_SHARED_WITH_US);
-			}
-			// we have just received our invitation
-			else if (action == REMOTE_INVITATION) {
-				localState.put(TASK, TASK_ADD_FORUM_TO_LIST_SHARED_WITH_US);
-				// TODO how to get the proper group here?
-				Forum forum = new Forum(null, localState.getString(FORUM_NAME),
-						localState.getRaw(FORUM_SALT));
-				ContactId contactId = new ContactId(
-						localState.getLong(CONTACT_ID).intValue());
-				Event event = new ForumInvitationReceivedEvent(forum, contactId);
-				events = Collections.singletonList(event);
-			}
-			else {
-				throw new IllegalArgumentException("Bad state");
-			}
-			return new StateUpdate<BdfDictionary, BdfDictionary>(deleteMsg,
-					false, localState, messages, events);
-		} catch (FormatException e) {
-			throw new IllegalArgumentException(e);
-		}
-	}
-
-	private void logLocalAction(InviteeProtocolState state,
-			BdfDictionary localState, BdfDictionary msg) {
-
-		if (!LOG.isLoggable(INFO)) return;
-
-		String a = "response";
-		if (msg.getLong(TYPE, -1L) == SHARE_MSG_TYPE_LEAVE) a = "leave";
-
-		try {
-			LOG.info("Sending " + a + " in state " + state.name() +
-					" with session ID " +
-					Arrays.hashCode(msg.getRaw(SESSION_ID)) + " in group " +
-					Arrays.hashCode(msg.getRaw(GROUP_ID)) + ". " +
-					"Moving on to state " +
-					getState(localState.getLong(STATE)).name()
-			);
-		} catch (FormatException e) {
-			if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
-		}
-	}
-
-	private void logMessageReceived(InviteeProtocolState currentState,
-			InviteeProtocolState nextState, long type, BdfDictionary msg) {
-		if (!LOG.isLoggable(INFO)) return;
-
-		try {
-			String t = "unknown";
-			if (type == SHARE_MSG_TYPE_INVITATION) t = "INVITE";
-			else if (type == SHARE_MSG_TYPE_LEAVE) t = "LEAVE";
-			else if (type == SHARE_MSG_TYPE_ABORT) t = "ABORT";
-
-			LOG.info("Received " + t + " in state " + currentState.name() +
-					" with session ID " +
-					Arrays.hashCode(msg.getRaw(SESSION_ID)) + " in group " +
-					Arrays.hashCode(msg.getRaw(GROUP_ID)) + ". " +
-					"Moving on to state " + nextState.name()
-			);
-		} catch (FormatException e) {
-			if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
-		}
-	}
-
-	@Override
-	public StateUpdate<BdfDictionary, BdfDictionary> onMessageDelivered(
-			BdfDictionary localState, BdfDictionary delivered) {
-		try {
-			return noUpdate(localState, false);
-		} catch (FormatException e) {
-			if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
-			return null;
-		}
-	}
-
-	private InviteeProtocolState getState(Long state) {
-		return InviteeProtocolState.fromValue(state.intValue());
-	}
-
-	private StateUpdate<BdfDictionary, BdfDictionary> abortSession(
-			InviteeProtocolState currentState, BdfDictionary localState)
-			throws FormatException {
-
-		if (LOG.isLoggable(WARNING)) {
-			LOG.warning("Aborting protocol session " +
-					Arrays.hashCode(localState.getRaw(SESSION_ID)) +
-					" in state " + currentState.name());
-		}
-
-		localState.put(STATE, ERROR.getValue());
-		BdfDictionary msg = new BdfDictionary();
-		msg.put(TYPE, SHARE_MSG_TYPE_ABORT);
-		msg.put(SESSION_ID, localState.getRaw(SESSION_ID));
-		msg.put(GROUP_ID, localState.getRaw(GROUP_ID));
-		List<BdfDictionary> messages = Collections.singletonList(msg);
-
-		List<Event> events = Collections.emptyList();
-
-		return new StateUpdate<BdfDictionary, BdfDictionary>(false, false,
-				localState, messages, events);
-	}
-
-	private StateUpdate<BdfDictionary, BdfDictionary> noUpdate(
-			BdfDictionary localState, boolean delete) throws FormatException {
-
-		return new StateUpdate<BdfDictionary, BdfDictionary>(delete, false,
-				localState, Collections.<BdfDictionary>emptyList(),
-				Collections.<Event>emptyList());
-	}
-}
diff --git a/briar-core/src/org/briarproject/forum/SharerEngine.java b/briar-core/src/org/briarproject/forum/SharerEngine.java
deleted file mode 100644
index 05db965b80fb8f78aaa7b86c3f67cae3a838759f..0000000000000000000000000000000000000000
--- a/briar-core/src/org/briarproject/forum/SharerEngine.java
+++ /dev/null
@@ -1,264 +0,0 @@
-package org.briarproject.forum;
-
-import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ProtocolEngine;
-import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.ForumInvitationResponseReceivedEvent;
-import org.briarproject.api.forum.SharerAction;
-import org.briarproject.api.forum.SharerProtocolState;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.logging.Logger;
-
-import static java.util.logging.Level.INFO;
-import static java.util.logging.Level.WARNING;
-import static org.briarproject.api.forum.ForumConstants.CONTACT_ID;
-import static org.briarproject.api.forum.ForumConstants.FORUM_NAME;
-import static org.briarproject.api.forum.ForumConstants.FORUM_SALT;
-import static org.briarproject.api.forum.ForumConstants.GROUP_ID;
-import static org.briarproject.api.forum.ForumConstants.INVITATION_MSG;
-import static org.briarproject.api.forum.ForumConstants.SESSION_ID;
-import static org.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_ABORT;
-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;
-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_REMOVE_FORUM_FROM_LIST_TO_BE_SHARED_BY_US;
-import static org.briarproject.api.forum.ForumConstants.TASK_SHARE_FORUM;
-import static org.briarproject.api.forum.ForumConstants.TASK_UNSHARE_FORUM_SHARED_BY_US;
-import static org.briarproject.api.forum.ForumConstants.TYPE;
-import static org.briarproject.api.forum.SharerAction.LOCAL_ABORT;
-import static org.briarproject.api.forum.SharerAction.LOCAL_INVITATION;
-import static org.briarproject.api.forum.SharerAction.LOCAL_LEAVE;
-import static org.briarproject.api.forum.SharerAction.REMOTE_ACCEPT;
-import static org.briarproject.api.forum.SharerAction.REMOTE_DECLINE;
-import static org.briarproject.api.forum.SharerAction.REMOTE_LEAVE;
-import static org.briarproject.api.forum.SharerProtocolState.ERROR;
-import static org.briarproject.api.forum.SharerProtocolState.FINISHED;
-import static org.briarproject.api.forum.SharerProtocolState.LEFT;
-
-public class SharerEngine
-		implements ProtocolEngine<BdfDictionary, BdfDictionary, BdfDictionary> {
-
-	private static final Logger LOG =
-			Logger.getLogger(SharerEngine.class.getName());
-
-	@Override
-	public StateUpdate<BdfDictionary, BdfDictionary> onLocalAction(
-			BdfDictionary localState, BdfDictionary localAction) {
-
-		try {
-			SharerProtocolState currentState =
-					getState(localState.getLong(STATE));
-			long type = localAction.getLong(TYPE);
-			SharerAction action = SharerAction.getLocal(type);
-			SharerProtocolState nextState = currentState.next(action);
-			localState.put(STATE, nextState.getValue());
-
-			if (action == LOCAL_ABORT && currentState != ERROR) {
-				return abortSession(currentState, localState);
-			}
-
-			if (nextState == ERROR) {
-				if (LOG.isLoggable(WARNING)) {
-					LOG.warning("Error: Invalid action in state " +
-							currentState.name());
-				}
-				return noUpdate(localState, true);
-			}
-			List<BdfDictionary> messages;
-			List<Event> events = Collections.emptyList();
-
-			if (action == LOCAL_INVITATION) {
-				BdfDictionary msg = new BdfDictionary();
-				msg.put(TYPE, SHARE_MSG_TYPE_INVITATION);
-				msg.put(SESSION_ID, localState.getRaw(SESSION_ID));
-				msg.put(GROUP_ID, localState.getRaw(GROUP_ID));
-				msg.put(FORUM_NAME, localState.getString(FORUM_NAME));
-				msg.put(FORUM_SALT, localState.getRaw(FORUM_SALT));
-				if (localAction.containsKey(INVITATION_MSG)) {
-					msg.put(INVITATION_MSG,
-							localAction.getString(INVITATION_MSG));
-				}
-				messages = Collections.singletonList(msg);
-				logLocalAction(currentState, localState, msg);
-
-				// remember that we offered to share this forum
-				localState.put(TASK, TASK_ADD_FORUM_TO_LIST_TO_BE_SHARED_BY_US);
-			}
-			else if (action == LOCAL_LEAVE) {
-				BdfDictionary msg = new BdfDictionary();
-				msg.put(TYPE, SHARE_MSG_TYPE_LEAVE);
-				msg.put(SESSION_ID, localState.getRaw(SESSION_ID));
-				msg.put(GROUP_ID, localState.getRaw(GROUP_ID));
-				messages = Collections.singletonList(msg);
-				logLocalAction(currentState, localState, msg);
-			}
-			else {
-				throw new IllegalArgumentException("Unknown Local Action");
-			}
-			return new StateUpdate<BdfDictionary, BdfDictionary>(false,
-					false, localState, messages, events);
-		} catch (FormatException e) {
-			throw new IllegalArgumentException(e);
-		}
-	}
-
-	@Override
-	public StateUpdate<BdfDictionary, BdfDictionary> onMessageReceived(
-			BdfDictionary localState, BdfDictionary msg) {
-
-		try {
-			SharerProtocolState currentState =
-					getState(localState.getLong(STATE));
-			long type = msg.getLong(TYPE);
-			SharerAction action = SharerAction.getRemote(type);
-			SharerProtocolState nextState = currentState.next(action);
-			localState.put(STATE, nextState.getValue());
-
-			logMessageReceived(currentState, nextState, type, msg);
-
-			if (nextState == ERROR) {
-				if (currentState != ERROR) {
-					return abortSession(currentState, localState);
-				} else {
-					return noUpdate(localState, true);
-				}
-			}
-			List<BdfDictionary> messages = Collections.emptyList();
-			List<Event> events = Collections.emptyList();
-			boolean deleteMsg = false;
-
-			if (currentState == LEFT) {
-				// ignore and delete messages coming in while in that state
-				deleteMsg = true;
-			}
-			else if (action == REMOTE_LEAVE) {
-				localState.put(TASK, TASK_UNSHARE_FORUM_SHARED_BY_US);
-			}
-			else if (currentState == FINISHED) {
-				// ignore and delete messages coming in while in that state
-				// note that LEAVE is possible, but was handled above
-				deleteMsg = true;
-			}
-			// we have sent our invitation and just got a response
-			else if (action == REMOTE_ACCEPT || action == REMOTE_DECLINE) {
-				if (action == REMOTE_ACCEPT) {
-					localState.put(TASK, TASK_SHARE_FORUM);
-				} else {
-					// this ensures that the forum can be shared again
-					localState.put(TASK,
-							TASK_REMOVE_FORUM_FROM_LIST_TO_BE_SHARED_BY_US);
-				}
-				String name = localState.getString(FORUM_NAME);
-				ContactId c = new ContactId(
-						localState.getLong(CONTACT_ID).intValue());
-				Event event = new ForumInvitationResponseReceivedEvent(name, c);
-				events = Collections.singletonList(event);
-			}
-			else {
-				throw new IllegalArgumentException("Bad state");
-			}
-			return new StateUpdate<BdfDictionary, BdfDictionary>(deleteMsg,
-					false, localState, messages, events);
-		} catch (FormatException e) {
-			throw new IllegalArgumentException(e);
-		}
-	}
-
-	private void logLocalAction(SharerProtocolState state,
-			BdfDictionary localState, BdfDictionary msg) {
-
-		if (!LOG.isLoggable(INFO)) return;
-
-		String a = "invitation";
-		if (msg.getLong(TYPE, -1L) == SHARE_MSG_TYPE_LEAVE) a = "leave";
-
-		try {
-			LOG.info("Sending " + a + " in state " + state.name() +
-					" with session ID " +
-					Arrays.hashCode(msg.getRaw(SESSION_ID)) + " in group " +
-					Arrays.hashCode(msg.getRaw(GROUP_ID)) + ". " +
-					"Moving on to state " +
-					getState(localState.getLong(STATE)).name()
-			);
-		} catch (FormatException e) {
-			if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
-		}
-	}
-
-	private void logMessageReceived(SharerProtocolState currentState,
-			SharerProtocolState nextState, long type, BdfDictionary msg) {
-		if (!LOG.isLoggable(INFO)) return;
-
-		try {
-			String t = "unknown";
-			if (type == SHARE_MSG_TYPE_ACCEPT) t = "ACCEPT";
-			else if (type == SHARE_MSG_TYPE_DECLINE) t = "DECLINE";
-			else if (type == SHARE_MSG_TYPE_LEAVE) t = "LEAVE";
-			else if (type == SHARE_MSG_TYPE_ABORT) t = "ABORT";
-
-			LOG.info("Received " + t + " in state " + currentState.name() +
-					" with session ID " +
-					Arrays.hashCode(msg.getRaw(SESSION_ID)) + " in group " +
-					Arrays.hashCode(msg.getRaw(GROUP_ID)) + ". " +
-					"Moving on to state " + nextState.name()
-			);
-		} catch (FormatException e) {
-			if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
-		}
-	}
-
-	@Override
-	public StateUpdate<BdfDictionary, BdfDictionary> onMessageDelivered(
-			BdfDictionary localState, BdfDictionary delivered) {
-		try {
-			return noUpdate(localState, false);
-		} catch (FormatException e) {
-			if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
-			return null;
-		}
-	}
-
-	private SharerProtocolState getState(Long state) {
-		 return SharerProtocolState.fromValue(state.intValue());
-	}
-
-	private StateUpdate<BdfDictionary, BdfDictionary> abortSession(
-			SharerProtocolState currentState, BdfDictionary localState)
-			throws FormatException {
-
-		if (LOG.isLoggable(WARNING)) {
-			LOG.warning("Aborting protocol session " +
-					Arrays.hashCode(localState.getRaw(SESSION_ID)) +
-					" in state " + currentState.name());
-		}
-
-		localState.put(STATE, ERROR.getValue());
-		BdfDictionary msg = new BdfDictionary();
-		msg.put(TYPE, SHARE_MSG_TYPE_ABORT);
-		msg.put(SESSION_ID, localState.getRaw(SESSION_ID));
-		msg.put(GROUP_ID, localState.getRaw(GROUP_ID));
-		List<BdfDictionary> messages = Collections.singletonList(msg);
-
-		List<Event> events = Collections.emptyList();
-
-		return new StateUpdate<BdfDictionary, BdfDictionary>(false, false,
-				localState, messages, events);
-	}
-
-	private StateUpdate<BdfDictionary, BdfDictionary> noUpdate(
-			BdfDictionary localState, boolean delete) throws FormatException {
-
-		return new StateUpdate<BdfDictionary, BdfDictionary>(delete, false,
-				localState, Collections.<BdfDictionary>emptyList(),
-				Collections.<Event>emptyList());
-	}
-}
diff --git a/briar-tests/src/org/briarproject/forum/ForumManagerImplTest.java b/briar-tests/src/org/briarproject/forum/ForumManagerImplTest.java
deleted file mode 100644
index 0e72451229636910d491aea96840cdf547e56ae4..0000000000000000000000000000000000000000
--- a/briar-tests/src/org/briarproject/forum/ForumManagerImplTest.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.briarproject.forum;
-
-import org.briarproject.BriarTestCase;
-import org.junit.Test;
-
-import static org.junit.Assert.fail;
-
-public class ForumManagerImplTest extends BriarTestCase {
-
-	@Test
-	public void testUnitTestsExist() {
-		fail(); // FIXME: Write tests
-	}
-}
diff --git a/briar-tests/src/org/briarproject/forum/ForumPostValidatorTest.java b/briar-tests/src/org/briarproject/forum/ForumPostValidatorTest.java
deleted file mode 100644
index 089cce54d979cdc067eba10510e9dcdcd4494bbd..0000000000000000000000000000000000000000
--- a/briar-tests/src/org/briarproject/forum/ForumPostValidatorTest.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.briarproject.forum;
-
-import org.briarproject.BriarTestCase;
-import org.junit.Test;
-
-import static org.junit.Assert.fail;
-
-public class ForumPostValidatorTest extends BriarTestCase {
-
-	@Test
-	public void testUnitTestsExist() {
-		fail(); // FIXME: Write tests
-	}
-}
diff --git a/briar-tests/src/org/briarproject/forum/ForumSharingManagerImplTest.java b/briar-tests/src/org/briarproject/forum/ForumSharingManagerImplTest.java
deleted file mode 100644
index 07fc1ad80a77dacffcdf1093c7f09a954c1fffe1..0000000000000000000000000000000000000000
--- a/briar-tests/src/org/briarproject/forum/ForumSharingManagerImplTest.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.briarproject.forum;
-
-import org.briarproject.BriarTestCase;
-import org.junit.Test;
-
-import static org.junit.Assert.fail;
-
-public class ForumSharingManagerImplTest extends BriarTestCase {
-
-	@Test
-	public void testUnitTestsExist() {
-		fail(); // FIXME: Write tests
-	}
-}
diff --git a/briar-tests/src/org/briarproject/forum/ForumSharingValidatorTest.java b/briar-tests/src/org/briarproject/forum/ForumSharingValidatorTest.java
deleted file mode 100644
index 0b87d04c19c36a768b5fcf4222b1445d5cffdaf1..0000000000000000000000000000000000000000
--- a/briar-tests/src/org/briarproject/forum/ForumSharingValidatorTest.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.briarproject.forum;
-
-import org.briarproject.BriarTestCase;
-import org.junit.Test;
-
-import static org.junit.Assert.fail;
-
-public class ForumSharingValidatorTest extends BriarTestCase {
-
-	@Test
-	public void testUnitTestsExist() {
-		fail(); // FIXME: Write tests
-	}
-}