diff --git a/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java index 4c4ba9b965365bce29cad3c7f88e03d5faeb3fe6..ae3e770a4e944e48fc201490cee7e8965c0876e0 100644 --- a/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java +++ b/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java @@ -3,16 +3,14 @@ package org.briarproject; import net.jodah.concurrentunit.Waiter; import org.briarproject.api.Bytes; -import org.briarproject.api.clients.MessageQueueManager; import org.briarproject.api.clients.ContactGroupFactory; +import org.briarproject.api.clients.MessageQueueManager; 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.CryptoComponent; import org.briarproject.api.crypto.KeyPair; -import org.briarproject.api.crypto.KeyParser; -import org.briarproject.api.crypto.PrivateKey; import org.briarproject.api.crypto.SecretKey; import org.briarproject.api.data.BdfList; import org.briarproject.api.db.DatabaseComponent; @@ -820,12 +818,10 @@ public class ForumSharingIntegrationTest extends BriarTestCase { // sharer posts into the forum long time = clock.currentTimeMillis(); - byte[] body = TestUtils.getRandomBytes(42); - KeyParser keyParser = cryptoComponent.getSignatureKeyParser(); - PrivateKey key = keyParser.parsePrivateKey(author0.getPrivateKey()); + String body = TestUtils.getRandomString(42); ForumPost p = forumPostFactory .createPseudonymousPost(forum0.getId(), time, null, author0, - "text/plain", body, key); + body); forumManager0.addLocalPost(p); // sync forum post @@ -841,11 +837,10 @@ public class ForumSharingIntegrationTest extends BriarTestCase { // now invitee creates a post time = clock.currentTimeMillis(); - body = TestUtils.getRandomBytes(42); - key = keyParser.parsePrivateKey(author1.getPrivateKey()); + body = TestUtils.getRandomString(42); p = forumPostFactory .createPseudonymousPost(forum0.getId(), time, null, author1, - "text/plain", body, key); + body); forumManager1.addLocalPost(p); // sync forum post @@ -886,11 +881,10 @@ public class ForumSharingIntegrationTest extends BriarTestCase { // now invitee creates a post time = clock.currentTimeMillis(); - body = TestUtils.getRandomBytes(42); - key = keyParser.parsePrivateKey(author1.getPrivateKey()); + body = TestUtils.getRandomString(42); p = forumPostFactory .createPseudonymousPost(forum0.getId(), time, null, author1, - "text/plain", body, key); + body); forumManager1.addLocalPost(p); // sync forum post 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..45fb9d7237bd38f3dcb8b575d5783c8fb736773c 100644 --- a/briar-android-tests/src/test/java/org/briarproject/MessageSizeIntegrationTest.java +++ b/briar-android-tests/src/test/java/org/briarproject/MessageSizeIntegrationTest.java @@ -6,8 +6,8 @@ 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.identity.LocalAuthor; import org.briarproject.api.messaging.MessagingConstants; import org.briarproject.api.messaging.PrivateMessage; import org.briarproject.api.messaging.PrivateMessageFactory; @@ -68,17 +68,17 @@ public class MessageSizeIntegrationTest extends BriarTestCase { String authorName = TestUtils.getRandomString( MAX_AUTHOR_NAME_LENGTH); byte[] authorPublic = new byte[MAX_PUBLIC_KEY_LENGTH]; - Author author = authorFactory.createAuthor(authorName, authorPublic); + PrivateKey privateKey = crypto.generateSignatureKeyPair().getPrivate(); + LocalAuthor author = authorFactory + .createLocalAuthor(authorName, authorPublic, + privateKey.getEncoded()); // 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(); + String body = TestUtils.getRandomString(MAX_FORUM_POST_BODY_LENGTH); ForumPost post = forumPostFactory.createPseudonymousPost(groupId, - timestamp, parent, author, contentType, body, privateKey); + timestamp, parent, author, body); // Check the size of the serialised message int length = post.getMessage().getRaw().length; assertTrue(length > UniqueId.LENGTH + 8 + UniqueId.LENGTH diff --git a/briar-android/src/org/briarproject/android/AndroidComponent.java b/briar-android/src/org/briarproject/android/AndroidComponent.java index 32f452401409769f9bf7cb6552d1632273b2294a..e8e23988297ab64f8563efcbc09b17c66834eb6c 100644 --- a/briar-android/src/org/briarproject/android/AndroidComponent.java +++ b/briar-android/src/org/briarproject/android/AndroidComponent.java @@ -19,7 +19,6 @@ import org.briarproject.api.db.DatabaseExecutor; import org.briarproject.api.event.EventBus; import org.briarproject.api.feed.FeedManager; 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; @@ -35,7 +34,6 @@ import org.briarproject.api.messaging.MessagingManager; import org.briarproject.api.messaging.PrivateMessageFactory; import org.briarproject.api.plugins.ConnectionRegistry; import org.briarproject.api.plugins.PluginManager; -import org.briarproject.api.privategroup.GroupMessageFactory; import org.briarproject.api.privategroup.PrivateGroupManager; import org.briarproject.api.settings.SettingsManager; import org.briarproject.plugins.AndroidPluginsModule; @@ -97,16 +95,12 @@ public interface AndroidComponent extends CoreEagerSingletons { PrivateGroupManager privateGroupManager(); - GroupMessageFactory groupMessageFactory(); - ForumManager forumManager(); ForumSharingManager forumSharingManager(); BlogSharingManager blogSharingManager(); - ForumPostFactory forumPostFactory(); - BlogManager blogManager(); BlogPostFactory blogPostFactory(); diff --git a/briar-android/src/org/briarproject/android/forum/ForumControllerImpl.java b/briar-android/src/org/briarproject/android/forum/ForumControllerImpl.java index a3b910390d3b409941ccecbf835f8c210d73b58e..9375d0a35d40ab6b81245b784c4e8f555b4bd6ff 100644 --- a/briar-android/src/org/briarproject/android/forum/ForumControllerImpl.java +++ b/briar-android/src/org/briarproject/android/forum/ForumControllerImpl.java @@ -3,13 +3,8 @@ package org.briarproject.android.forum; import android.support.annotation.Nullable; import org.briarproject.android.api.AndroidNotificationManager; -import org.briarproject.android.controller.handler.ResultExceptionHandler; import org.briarproject.android.threaded.ThreadListControllerImpl; -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.DatabaseExecutor; import org.briarproject.api.db.DbException; import org.briarproject.api.event.Event; @@ -18,47 +13,36 @@ import org.briarproject.api.event.ForumPostReceivedEvent; 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.forum.ForumPostHeader; -import org.briarproject.api.identity.IdentityManager; -import org.briarproject.api.identity.LocalAuthor; import org.briarproject.api.lifecycle.LifecycleManager; +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 java.util.logging.Level.INFO; -import static java.util.logging.Level.WARNING; -import static org.briarproject.api.identity.Author.Status.OURSELVES; - public class ForumControllerImpl - extends ThreadListControllerImpl<Forum, ForumEntry, ForumPostHeader> + extends ThreadListControllerImpl<Forum, ForumEntry, ForumPostHeader, ForumPost> implements ForumController { private static final Logger LOG = Logger.getLogger(ForumControllerImpl.class.getName()); - private final ForumPostFactory forumPostFactory; private final ForumManager forumManager; @Inject ForumControllerImpl(@DatabaseExecutor Executor dbExecutor, LifecycleManager lifecycleManager, @CryptoExecutor Executor cryptoExecutor, - ForumPostFactory forumPostFactory, CryptoComponent crypto, ForumManager forumManager, EventBus eventBus, - IdentityManager identityManager, AndroidNotificationManager notificationManager) { - super(dbExecutor, lifecycleManager, cryptoExecutor, crypto, eventBus, - identityManager, notificationManager); + super(dbExecutor, lifecycleManager, cryptoExecutor, eventBus, + notificationManager); this.forumManager = forumManager; - this.forumPostFactory = forumPostFactory; } @Override @@ -76,7 +60,6 @@ public class ForumControllerImpl if (pe.getGroupId().equals(groupId)) { LOG.info("Forum post received, adding..."); final ForumPostHeader fph = pe.getForumPostHeader(); - updateNewestTimestamp(fph.getTimestamp()); listener.runOnUiThreadUnlessDestroyed(new Runnable() { @Override public void run() { @@ -115,65 +98,15 @@ public class ForumControllerImpl } @Override - public void send(final String body, @Nullable final MessageId parentId, - final ResultExceptionHandler<ForumEntry, DbException> handler) { - cryptoExecutor.execute(new Runnable() { - @Override - public void run() { - LOG.info("Create post..."); - long timestamp = System.currentTimeMillis(); - timestamp = Math.max(timestamp, newestTimeStamp.get()); - ForumPost p; - try { - LocalAuthor a = identityManager.getLocalAuthor(); - KeyParser keyParser = crypto.getSignatureKeyParser(); - byte[] k = a.getPrivateKey(); - PrivateKey authorKey = keyParser.parsePrivateKey(k); - byte[] b = StringUtils.toUtf8(body); - p = forumPostFactory - .createPseudonymousPost(groupId, timestamp, - parentId, a, "text/plain", b, authorKey); - } catch (GeneralSecurityException | FormatException e) { - throw new RuntimeException(e); - } catch (DbException e) { - if (LOG.isLoggable(WARNING)) - LOG.log(WARNING, e.toString(), e); - handler.onException(e); - return; - } - bodyCache.put(p.getMessage().getId(), body); - storePost(p, handler); - } - }); + protected ForumPost createLocalMessage(GroupId g, String body, + @Nullable MessageId parentId) throws DbException { + return forumManager.createLocalPost(groupId, body, parentId); } - private void storePost(final ForumPost p, - final ResultExceptionHandler<ForumEntry, DbException> resultHandler) { - runOnDbThread(new Runnable() { - @Override - public void run() { - try { - LOG.info("Store post..."); - long now = System.currentTimeMillis(); - forumManager.addLocalPost(p); - long duration = System.currentTimeMillis() - now; - if (LOG.isLoggable(INFO)) - LOG.info("Storing message took " + duration + " ms"); - - ForumPostHeader h = - new ForumPostHeader(p.getMessage().getId(), - p.getParent(), - p.getMessage().getTimestamp(), - p.getAuthor(), OURSELVES, true); - - resultHandler.onResult(buildItem(h)); - } catch (DbException e) { - if (LOG.isLoggable(WARNING)) - LOG.log(WARNING, e.toString(), e); - resultHandler.onException(e); - } - } - }); + @Override + protected ForumPostHeader addLocalMessage(ForumPost p) + throws DbException { + return forumManager.addLocalPost(p); } @Override diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupControllerImpl.java b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupControllerImpl.java index 40e4d898cddeacf9905a9f284bca83a380be1928..18a9bb57e357bb6945626a2e7a64f14e6299d0fc 100644 --- a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupControllerImpl.java +++ b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupControllerImpl.java @@ -2,45 +2,46 @@ package org.briarproject.android.privategroup.conversation; import android.support.annotation.Nullable; -import org.briarproject.android.controller.handler.ResultExceptionHandler; +import org.briarproject.android.api.AndroidNotificationManager; import org.briarproject.android.threaded.ThreadListControllerImpl; -import org.briarproject.api.FormatException; +import org.briarproject.api.crypto.CryptoExecutor; +import org.briarproject.api.db.DatabaseExecutor; import org.briarproject.api.db.DbException; import org.briarproject.api.event.Event; +import org.briarproject.api.event.EventBus; import org.briarproject.api.event.GroupMessageAddedEvent; -import org.briarproject.api.identity.LocalAuthor; +import org.briarproject.api.lifecycle.LifecycleManager; import org.briarproject.api.privategroup.GroupMessage; -import org.briarproject.api.privategroup.GroupMessageFactory; import org.briarproject.api.privategroup.GroupMessageHeader; import org.briarproject.api.privategroup.PrivateGroup; import org.briarproject.api.privategroup.PrivateGroupManager; +import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.MessageId; -import java.security.GeneralSecurityException; import java.util.Collection; +import java.util.concurrent.Executor; 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.identity.Author.Status.OURSELVES; - public class GroupControllerImpl - extends ThreadListControllerImpl<PrivateGroup, GroupMessageItem, GroupMessageHeader> + extends ThreadListControllerImpl<PrivateGroup, GroupMessageItem, GroupMessageHeader, GroupMessage> implements GroupController { private static final Logger LOG = Logger.getLogger(GroupControllerImpl.class.getName()); - @Inject - volatile GroupMessageFactory groupMessageFactory; - @Inject - volatile PrivateGroupManager privateGroupManager; + private final PrivateGroupManager privateGroupManager; @Inject - GroupControllerImpl() { - super(); + GroupControllerImpl(@DatabaseExecutor Executor dbExecutor, + LifecycleManager lifecycleManager, + @CryptoExecutor Executor cryptoExecutor, + PrivateGroupManager privateGroupManager, EventBus eventBus, + AndroidNotificationManager notificationManager) { + super(dbExecutor, lifecycleManager, cryptoExecutor, eventBus, + notificationManager); + this.privateGroupManager = privateGroupManager; } @Override @@ -58,7 +59,6 @@ public class GroupControllerImpl if (!pe.isLocal() && pe.getGroupId().equals(groupId)) { LOG.info("Group message received, adding..."); final GroupMessageHeader fph = pe.getHeader(); - updateNewestTimestamp(fph.getTimestamp()); listener.runOnUiThreadUnlessDestroyed(new Runnable() { @Override public void run() { @@ -97,59 +97,15 @@ public class GroupControllerImpl } @Override - public void send(final String body, @Nullable final MessageId parentId, - final ResultExceptionHandler<GroupMessageItem, DbException> handler) { - cryptoExecutor.execute(new Runnable() { - @Override - public void run() { - LOG.info("Create message..."); - long timestamp = System.currentTimeMillis(); - timestamp = Math.max(timestamp, newestTimeStamp.get()); - GroupMessage gm; - try { - LocalAuthor a = identityManager.getLocalAuthor(); - gm = groupMessageFactory.createGroupMessage(groupId, - timestamp, parentId, a, body); - } catch (GeneralSecurityException | FormatException e) { - throw new RuntimeException(e); - } catch (DbException e) { - if (LOG.isLoggable(WARNING)) - LOG.log(WARNING, e.toString(), e); - handler.onException(e); - return; - } - bodyCache.put(gm.getMessage().getId(), body); - storeMessage(gm, handler); - } - }); + protected GroupMessage createLocalMessage(GroupId g, String body, + @Nullable MessageId parentId) throws DbException { + return privateGroupManager.createLocalMessage(groupId, body, parentId); } - private void storeMessage(final GroupMessage gm, - final ResultExceptionHandler<GroupMessageItem, DbException> handler) { - runOnDbThread(new Runnable() { - @Override - public void run() { - try { - LOG.info("Store message..."); - long now = System.currentTimeMillis(); - privateGroupManager.addLocalMessage(gm); - long duration = System.currentTimeMillis() - now; - if (LOG.isLoggable(INFO)) - LOG.info("Storing message took " + duration + " ms"); - - GroupMessageHeader h = new GroupMessageHeader(groupId, - gm.getMessage().getId(), gm.getParent(), - gm.getMessage().getTimestamp(), gm.getAuthor(), - OURSELVES, true); - - handler.onResult(buildItem(h)); - } catch (DbException e) { - if (LOG.isLoggable(WARNING)) - LOG.log(WARNING, e.toString(), e); - handler.onException(e); - } - } - }); + @Override + protected GroupMessageHeader addLocalMessage(GroupMessage message) + throws DbException { + return privateGroupManager.addLocalMessage(message); } @Override diff --git a/briar-android/src/org/briarproject/android/threaded/ThreadListControllerImpl.java b/briar-android/src/org/briarproject/android/threaded/ThreadListControllerImpl.java index e60f310c4525e204dce212563b157cb0a7f24ccb..3fbf2bccc6c94217842e60b790dc000cf0b1d236 100644 --- a/briar-android/src/org/briarproject/android/threaded/ThreadListControllerImpl.java +++ b/briar-android/src/org/briarproject/android/threaded/ThreadListControllerImpl.java @@ -2,13 +2,14 @@ package org.briarproject.android.threaded; import android.app.Activity; import android.support.annotation.CallSuper; +import android.support.annotation.Nullable; import org.briarproject.android.api.AndroidNotificationManager; import org.briarproject.android.controller.DbControllerImpl; import org.briarproject.android.controller.handler.ResultExceptionHandler; import org.briarproject.api.clients.BaseGroup; +import org.briarproject.api.clients.BaseMessage; import org.briarproject.api.clients.PostHeader; -import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.CryptoExecutor; import org.briarproject.api.db.DatabaseExecutor; import org.briarproject.api.db.DbException; @@ -16,9 +17,6 @@ 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.forum.ForumManager; -import org.briarproject.api.forum.ForumPostFactory; -import org.briarproject.api.identity.IdentityManager; import org.briarproject.api.lifecycle.LifecycleManager; import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.MessageId; @@ -30,13 +28,12 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; -import java.util.concurrent.atomic.AtomicLong; import java.util.logging.Logger; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; -public abstract class ThreadListControllerImpl<G extends BaseGroup, I extends ThreadItem, H extends PostHeader> +public abstract class ThreadListControllerImpl<G extends BaseGroup, I extends ThreadItem, H extends PostHeader, M extends BaseMessage> extends DbControllerImpl implements ThreadListController<G, I, H>, EventListener { @@ -44,14 +41,11 @@ public abstract class ThreadListControllerImpl<G extends BaseGroup, I extends Th Logger.getLogger(ThreadListControllerImpl.class.getName()); protected final Executor cryptoExecutor; - protected final CryptoComponent crypto; - protected final EventBus eventBus; - protected final IdentityManager identityManager; protected final AndroidNotificationManager notificationManager; + private final EventBus eventBus; protected final Map<MessageId, String> bodyCache = new ConcurrentHashMap<>(); - protected final AtomicLong newestTimeStamp = new AtomicLong(); protected volatile GroupId groupId; @@ -59,14 +53,11 @@ public abstract class ThreadListControllerImpl<G extends BaseGroup, I extends Th protected ThreadListControllerImpl(@DatabaseExecutor Executor dbExecutor, LifecycleManager lifecycleManager, - @CryptoExecutor Executor cryptoExecutor, CryptoComponent crypto, - EventBus eventBus, IdentityManager identityManager, + @CryptoExecutor Executor cryptoExecutor, EventBus eventBus, AndroidNotificationManager notificationManager) { super(dbExecutor, lifecycleManager); this.cryptoExecutor = cryptoExecutor; - this.crypto = crypto; this.eventBus = eventBus; - this.identityManager = identityManager; this.notificationManager = notificationManager; } @@ -164,9 +155,6 @@ public abstract class ThreadListControllerImpl<G extends BaseGroup, I extends Th if (LOG.isLoggable(INFO)) LOG.info("Loading headers took " + duration + " ms"); - // Update timestamp of newest item - updateNewestTimeStamp(headers); - // Load bodies now = System.currentTimeMillis(); loadBodies(headers); @@ -259,6 +247,63 @@ public abstract class ThreadListControllerImpl<G extends BaseGroup, I extends Th send(body, null, resultHandler); } + @Override + public void send(final String body, @Nullable final MessageId parentId, + final ResultExceptionHandler<I, DbException> handler) { + cryptoExecutor.execute(new Runnable() { + @Override + public void run() { + LOG.info("Creating message..."); + try { + M msg = createLocalMessage(groupId, body, parentId); + bodyCache.put(msg.getMessage().getId(), body); + storePost(msg, handler); + } catch (DbException e) { + if (LOG.isLoggable(WARNING)) + LOG.log(WARNING, e.toString(), e); + handler.onException(e); + } + } + }); + } + + /** + * This should only be run from the DbThread. + * + * @throws DbException + */ + protected abstract M createLocalMessage(GroupId g, String body, + @Nullable MessageId parentId) throws DbException; + + private void storePost(final M p, + final ResultExceptionHandler<I, DbException> resultHandler) { + runOnDbThread(new Runnable() { + @Override + public void run() { + try { + LOG.info("Store message..."); + long now = System.currentTimeMillis(); + H h = addLocalMessage(p); + long duration = System.currentTimeMillis() - now; + if (LOG.isLoggable(INFO)) + LOG.info("Storing message took " + duration + " ms"); + resultHandler.onResult(buildItem(h)); + } catch (DbException e) { + if (LOG.isLoggable(WARNING)) + LOG.log(WARNING, e.toString(), e); + resultHandler.onException(e); + } + } + }); + } + + /** + * This should only be run from the DbThread. + * + * @throws DbException + */ + protected abstract H addLocalMessage(M message) throws DbException; + @Override public void deleteGroupItem( final ResultExceptionHandler<Void, DbException> handler) { @@ -303,20 +348,6 @@ public abstract class ThreadListControllerImpl<G extends BaseGroup, I extends Th */ protected abstract I buildItem(H header); - private void updateNewestTimeStamp(Collection<H> headers) { - for (H h : headers) { - updateNewestTimestamp(h.getTimestamp()); - } - } - - protected void updateNewestTimestamp(long update) { - long newest = newestTimeStamp.get(); - while (newest < update) { - if (newestTimeStamp.compareAndSet(newest, update)) return; - newest = newestTimeStamp.get(); - } - } - private void checkGroupId() { if (groupId == null) { throw new IllegalStateException( diff --git a/briar-api/src/org/briarproject/api/forum/ForumManager.java b/briar-api/src/org/briarproject/api/forum/ForumManager.java index 8c35d05e368420f38e6356b77728dc3d3e2f39a6..edfd53f5508580907090f0944bc380fea4515651 100644 --- a/briar-api/src/org/briarproject/api/forum/ForumManager.java +++ b/briar-api/src/org/briarproject/api/forum/ForumManager.java @@ -6,6 +6,7 @@ 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 org.jetbrains.annotations.Nullable; import java.util.Collection; @@ -20,8 +21,12 @@ public interface ForumManager extends MessageTracker { /** Unsubscribes from a forum. */ void removeForum(Forum f) throws DbException; + /** Creates a local forum post. */ + ForumPost createLocalPost(GroupId groupId, String text, + @Nullable MessageId parentId) throws DbException; + /** Stores a local forum post. */ - void addLocalPost(ForumPost p) throws DbException; + ForumPostHeader addLocalPost(ForumPost p) throws DbException; /** Returns the forum with the given ID. */ Forum getForum(GroupId g) throws DbException; diff --git a/briar-api/src/org/briarproject/api/forum/ForumPostFactory.java b/briar-api/src/org/briarproject/api/forum/ForumPostFactory.java index e05edc8831b3538458c44175e8a005d59d56d878..1d6aa9e76d9379b1aaa78ba28f34a849153d25dc 100644 --- a/briar-api/src/org/briarproject/api/forum/ForumPostFactory.java +++ b/briar-api/src/org/briarproject/api/forum/ForumPostFactory.java @@ -1,8 +1,7 @@ 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.identity.LocalAuthor; import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.MessageId; @@ -15,7 +14,6 @@ public interface ForumPostFactory { throws FormatException; ForumPost createPseudonymousPost(GroupId groupId, long timestamp, - MessageId parent, Author author, String contentType, byte[] body, - PrivateKey privateKey) throws FormatException, - GeneralSecurityException; + MessageId parent, LocalAuthor author, String body) + throws FormatException, GeneralSecurityException; } diff --git a/briar-api/src/org/briarproject/api/privategroup/PrivateGroupManager.java b/briar-api/src/org/briarproject/api/privategroup/PrivateGroupManager.java index a7fbd0cb12a5421e04d3c1c37eacebb09bf43c19..07ef1c002217399f893d71e03a6e15d6c776c65e 100644 --- a/briar-api/src/org/briarproject/api/privategroup/PrivateGroupManager.java +++ b/briar-api/src/org/briarproject/api/privategroup/PrivateGroupManager.java @@ -7,6 +7,7 @@ import org.briarproject.api.sync.ClientId; import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.MessageId; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Collection; @@ -19,8 +20,12 @@ public interface PrivateGroupManager extends MessageTracker { /** Removes a dissolved private group. */ void removePrivateGroup(GroupId g) throws DbException; + /** Creates a local group message. */ + GroupMessage createLocalMessage(GroupId groupId, String text, + @Nullable MessageId parentId) throws DbException; + /** Stores (and sends) a local group message. */ - void addLocalMessage(GroupMessage p) throws DbException; + GroupMessageHeader addLocalMessage(GroupMessage p) throws DbException; /** Returns the private group with the given ID. */ @NotNull diff --git a/briar-core/src/org/briarproject/forum/ForumManagerImpl.java b/briar-core/src/org/briarproject/forum/ForumManagerImpl.java index 77a7712e57ae0b4769e0a4ccee6c560981a08cce..ce47a5c3ee80adc3d6602ff0ec22d459f67a44a0 100644 --- a/briar-core/src/org/briarproject/forum/ForumManagerImpl.java +++ b/briar-core/src/org/briarproject/forum/ForumManagerImpl.java @@ -13,19 +13,24 @@ import org.briarproject.api.forum.Forum; import org.briarproject.api.forum.ForumFactory; import org.briarproject.api.forum.ForumManager; import org.briarproject.api.forum.ForumPost; +import org.briarproject.api.forum.ForumPostFactory; import org.briarproject.api.forum.ForumPostHeader; import org.briarproject.api.identity.Author; import org.briarproject.api.identity.Author.Status; import org.briarproject.api.identity.AuthorId; import org.briarproject.api.identity.IdentityManager; +import org.briarproject.api.identity.LocalAuthor; 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.system.Clock; import org.briarproject.clients.BdfIncomingMessageHook; import org.briarproject.util.StringUtils; +import org.jetbrains.annotations.Nullable; +import java.security.GeneralSecurityException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -47,6 +52,7 @@ import static org.briarproject.api.forum.ForumConstants.KEY_PARENT; import static org.briarproject.api.forum.ForumConstants.KEY_PUBLIC_NAME; import static org.briarproject.api.forum.ForumConstants.KEY_TIMESTAMP; import static org.briarproject.api.identity.Author.Status.ANONYMOUS; +import static org.briarproject.api.identity.Author.Status.OURSELVES; import static org.briarproject.clients.BdfConstants.MSG_KEY_READ; class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager { @@ -57,16 +63,21 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager { private final IdentityManager identityManager; private final ForumFactory forumFactory; + private final ForumPostFactory forumPostFactory; + private final Clock clock; private final List<RemoveForumHook> removeHooks; @Inject ForumManagerImpl(DatabaseComponent db, IdentityManager identityManager, ClientHelper clientHelper, MetadataParser metadataParser, - ForumFactory forumFactory) { + ForumFactory forumFactory, ForumPostFactory forumPostFactory, + Clock clock) { super(db, clientHelper, metadataParser); this.identityManager = identityManager; this.forumFactory = forumFactory; + this.forumPostFactory = forumPostFactory; + this.clock = clock; removeHooks = new CopyOnWriteArrayList<RemoveForumHook>(); } @@ -118,7 +129,38 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager { } @Override - public void addLocalPost(ForumPost p) throws DbException { + public ForumPost createLocalPost(final GroupId groupId, + final String body, final @Nullable MessageId parentId) + throws DbException { + + LocalAuthor author; + GroupCount count; + Transaction txn = db.startTransaction(true); + try { + author = identityManager.getLocalAuthor(txn); + count = getGroupCount(txn, groupId); + txn.setComplete(); + } finally { + db.endTransaction(txn); + } + long timestamp = clock.currentTimeMillis(); + timestamp = Math.max(timestamp, count.getLatestMsgTime()); + + ForumPost p; + try { + p = forumPostFactory + .createPseudonymousPost(groupId, timestamp, parentId, + author, body); + } catch (GeneralSecurityException e) { + throw new RuntimeException(e); + } catch (FormatException e) { + throw new DbException(e); + } + return p; + } + + @Override + public ForumPostHeader addLocalPost(ForumPost p) throws DbException { Transaction txn = db.startTransaction(false); try { BdfDictionary meta = new BdfDictionary(); @@ -142,6 +184,8 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager { } finally { db.endTransaction(txn); } + return new ForumPostHeader(p.getMessage().getId(), p.getParent(), + p.getMessage().getTimestamp(), p.getAuthor(), OURSELVES, true); } @Override diff --git a/briar-core/src/org/briarproject/forum/ForumPostFactoryImpl.java b/briar-core/src/org/briarproject/forum/ForumPostFactoryImpl.java index a6c0b226aea4109724a72ebb36ae02ca6299a937..7c0d1e46ddc88a7fefb999340f96185cc99d22be 100644 --- a/briar-core/src/org/briarproject/forum/ForumPostFactoryImpl.java +++ b/briar-core/src/org/briarproject/forum/ForumPostFactoryImpl.java @@ -3,12 +3,13 @@ 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.KeyParser; 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.identity.LocalAuthor; import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.Message; import org.briarproject.api.sync.MessageId; @@ -49,9 +50,10 @@ class ForumPostFactoryImpl implements ForumPostFactory { @Override public ForumPost createPseudonymousPost(GroupId groupId, long timestamp, - MessageId parent, Author author, String contentType, byte[] body, - PrivateKey privateKey) throws FormatException, - GeneralSecurityException { + MessageId parent, LocalAuthor author, String bodyStr) + throws FormatException, GeneralSecurityException { + String contentType = "text/plain"; + byte[] body = StringUtils.toUtf8(bodyStr); // Validate the arguments if (StringUtils.toUtf8(contentType).length > MAX_CONTENT_TYPE_LENGTH) throw new IllegalArgumentException(); @@ -62,6 +64,10 @@ class ForumPostFactoryImpl implements ForumPostFactory { author.getPublicKey()); BdfList signed = BdfList.of(groupId, timestamp, parent, authorList, contentType, body); + // Get private key + KeyParser keyParser = crypto.getSignatureKeyParser(); + byte[] k = author.getPrivateKey(); + PrivateKey privateKey = keyParser.parsePrivateKey(k); // Generate the signature Signature signature = crypto.getSignature(); signature.initSign(privateKey); diff --git a/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java b/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java index d9483d33602d7b67dc9955f87be27bf573b4f538..b0ef7e072db3382199f5d99fad503c12f0a7df4f 100644 --- a/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java +++ b/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java @@ -9,7 +9,9 @@ import org.briarproject.api.db.DatabaseComponent; import org.briarproject.api.db.DbException; import org.briarproject.api.db.Transaction; import org.briarproject.api.identity.IdentityManager; +import org.briarproject.api.identity.LocalAuthor; import org.briarproject.api.privategroup.GroupMessage; +import org.briarproject.api.privategroup.GroupMessageFactory; import org.briarproject.api.privategroup.GroupMessageHeader; import org.briarproject.api.privategroup.PrivateGroup; import org.briarproject.api.privategroup.PrivateGroupFactory; @@ -19,16 +21,21 @@ 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.system.Clock; import org.briarproject.clients.BdfIncomingMessageHook; import org.briarproject.util.StringUtils; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.security.GeneralSecurityException; import java.util.Collection; import java.util.Collections; import java.util.logging.Logger; import javax.inject.Inject; +import static org.briarproject.api.identity.Author.Status.OURSELVES; + public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements PrivateGroupManager { @@ -40,16 +47,21 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements private final IdentityManager identityManager; private final PrivateGroupFactory privateGroupFactory; + private final GroupMessageFactory groupMessageFactory; + private final Clock clock; @Inject PrivateGroupManagerImpl(ClientHelper clientHelper, MetadataParser metadataParser, DatabaseComponent db, IdentityManager identityManager, - PrivateGroupFactory privateGroupFactory) { + PrivateGroupFactory privateGroupFactory, + GroupMessageFactory groupMessageFactory, Clock clock) { super(db, clientHelper, metadataParser); this.identityManager = identityManager; this.privateGroupFactory = privateGroupFactory; + this.groupMessageFactory = groupMessageFactory; + this.clock = clock; } @NotNull @@ -64,7 +76,25 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements } @Override - public void addLocalMessage(GroupMessage m) throws DbException { + public GroupMessage createLocalMessage(GroupId groupId, String body, + @Nullable MessageId parentId) throws DbException { + + long timestamp = clock.currentTimeMillis(); + LocalAuthor author = identityManager.getLocalAuthor(); + try { + return groupMessageFactory + .createGroupMessage(groupId, timestamp, parentId, author, + body); + } catch (FormatException e) { + throw new DbException(e); + } catch (GeneralSecurityException e) { + throw new RuntimeException(e); + } + } + + @Override + public GroupMessageHeader addLocalMessage(GroupMessage m) + throws DbException { Transaction txn = db.startTransaction(false); try { BdfDictionary meta = new BdfDictionary(); @@ -76,6 +106,9 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements } finally { db.endTransaction(txn); } + return new GroupMessageHeader(m.getMessage().getGroupId(), + m.getMessage().getId(), m.getParent(), + m.getMessage().getTimestamp(), m.getAuthor(), OURSELVES, true); } @NotNull