diff --git a/briar-api/src/org/briarproject/api/blogs/BlogConstants.java b/briar-api/src/org/briarproject/api/blogs/BlogConstants.java index 60f06a641b5591ed79c35d32e785d3265358cff6..738e012a3ef2872f1c341aacc7e5a6a68d5a7da5 100644 --- a/briar-api/src/org/briarproject/api/blogs/BlogConstants.java +++ b/briar-api/src/org/briarproject/api/blogs/BlogConstants.java @@ -22,6 +22,12 @@ public interface BlogConstants { /** The maximum length of a blog post's body in bytes. */ int MAX_BLOG_POST_BODY_LENGTH = MAX_MESSAGE_BODY_LENGTH - 1024; + /* Blog Sharing Constants */ + String BLOG_TITLE = "blogTitle"; + String BLOG_DESC = "blogDescription"; + String BLOG_AUTHOR_NAME = "blogAuthorName"; + String BLOG_PUBLIC_KEY = "blogPublicKey"; + // Metadata keys String KEY_DESCRIPTION = "description"; String KEY_TITLE = "title"; diff --git a/briar-api/src/org/briarproject/api/blogs/BlogInvitationMessage.java b/briar-api/src/org/briarproject/api/blogs/BlogInvitationMessage.java new file mode 100644 index 0000000000000000000000000000000000000000..9306da5726c5a74cea45a1524f573949c6f686df --- /dev/null +++ b/briar-api/src/org/briarproject/api/blogs/BlogInvitationMessage.java @@ -0,0 +1,26 @@ +package org.briarproject.api.blogs; + +import org.briarproject.api.clients.SessionId; +import org.briarproject.api.contact.ContactId; +import org.briarproject.api.sharing.InvitationMessage; +import org.briarproject.api.sync.MessageId; + +public class BlogInvitationMessage extends InvitationMessage { + + private final String blogTitle; + + public BlogInvitationMessage(MessageId id, SessionId sessionId, + ContactId contactId, String blogTitle, String message, + boolean available, long time, boolean local, boolean sent, + boolean seen, boolean read) { + + super(id, sessionId, contactId, message, available, time, local, sent, + seen, read); + this.blogTitle = blogTitle; + } + + public String getBlogTitle() { + return blogTitle; + } + +} diff --git a/briar-api/src/org/briarproject/api/blogs/BlogSharingManager.java b/briar-api/src/org/briarproject/api/blogs/BlogSharingManager.java new file mode 100644 index 0000000000000000000000000000000000000000..ec9f23e49df4910fc2bdc5935fd98b4e9eed4cbd --- /dev/null +++ b/briar-api/src/org/briarproject/api/blogs/BlogSharingManager.java @@ -0,0 +1,60 @@ +package org.briarproject.api.blogs; + +import org.briarproject.api.contact.Contact; +import org.briarproject.api.contact.ContactId; +import org.briarproject.api.db.DbException; +import org.briarproject.api.sharing.SharingManager; +import org.briarproject.api.sync.ClientId; +import org.briarproject.api.sync.GroupId; + +import java.util.Collection; + +public interface BlogSharingManager + extends SharingManager<Blog, BlogInvitationMessage> { + + /** + * Returns the unique ID of the blog sharing client. + */ + ClientId getClientId(); + + /** + * Sends an invitation to share the given blog with the given contact + * and sends an optional message along with it. + */ + void sendInvitation(GroupId groupId, ContactId contactId, + String message) throws DbException; + + /** + * Responds to a pending blog invitation + */ + void respondToInvitation(Blog b, Contact c, boolean accept) + throws DbException; + + /** + * Returns all blogs sharing messages sent by the Contact + * identified by contactId. + */ + Collection<BlogInvitationMessage> getInvitationMessages( + ContactId contactId) throws DbException; + + /** + * Returns all blogs to which the user could subscribe. + */ + Collection<Blog> getAvailable() throws DbException; + + /** + * Returns all contacts who are sharing the given blog with us. + */ + Collection<Contact> getSharedBy(GroupId g) throws DbException; + + /** + * Returns the IDs of all contacts with whom the given blog is shared. + */ + Collection<Contact> getSharedWith(GroupId g) throws DbException; + + /** + * Returns true if the blog 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/blogs/BlogSharingMessage.java b/briar-api/src/org/briarproject/api/blogs/BlogSharingMessage.java new file mode 100644 index 0000000000000000000000000000000000000000..105b0d2a3f981c27db33f36fbc072b296f93689c --- /dev/null +++ b/briar-api/src/org/briarproject/api/blogs/BlogSharingMessage.java @@ -0,0 +1,89 @@ +package org.briarproject.api.blogs; + +import org.briarproject.api.FormatException; +import org.briarproject.api.clients.SessionId; +import org.briarproject.api.data.BdfDictionary; +import org.briarproject.api.data.BdfList; +import org.briarproject.api.sharing.SharingMessage.Invitation; +import org.briarproject.api.sync.GroupId; + +import static org.briarproject.api.blogs.BlogConstants.BLOG_AUTHOR_NAME; +import static org.briarproject.api.blogs.BlogConstants.BLOG_DESC; +import static org.briarproject.api.blogs.BlogConstants.BLOG_PUBLIC_KEY; +import static org.briarproject.api.blogs.BlogConstants.BLOG_TITLE; +import static org.briarproject.api.sharing.SharingConstants.INVITATION_MSG; +import static org.briarproject.api.sharing.SharingConstants.SESSION_ID; + +public interface BlogSharingMessage { + + class BlogInvitation extends Invitation { + + private final String blogTitle; + private final String blogDesc; + private final String blogAuthorName; + private final byte[] blogPublicKey; + + public BlogInvitation(GroupId groupId, SessionId sessionId, + String blogTitle, String blogDesc, String blogAuthorName, + byte[] blogPublicKey, String message) { + + super(groupId, sessionId, message); + + this.blogTitle = blogTitle; + this.blogDesc = blogDesc; + this.blogAuthorName = blogAuthorName; + this.blogPublicKey = blogPublicKey; + } + + @Override + public BdfList toBdfList() { + BdfList list = super.toBdfList(); + list.add(blogTitle); + list.add(blogDesc); + list.add(BdfList.of(blogAuthorName, blogPublicKey)); + if (message != null) list.add(message); + return list; + } + + @Override + public BdfDictionary toBdfDictionary() { + BdfDictionary d = toBdfDictionaryHelper(); + d.put(BLOG_TITLE, blogTitle); + d.put(BLOG_DESC, blogDesc); + d.put(BLOG_AUTHOR_NAME, blogAuthorName); + d.put(BLOG_PUBLIC_KEY, blogPublicKey); + if (message != null) d.put(INVITATION_MSG, message); + return d; + } + + public static BlogInvitation from(GroupId groupId, BdfDictionary d) + throws FormatException { + + SessionId sessionId = new SessionId(d.getRaw(SESSION_ID)); + String blogTitle = d.getString(BLOG_TITLE); + String blogDesc = d.getString(BLOG_DESC); + String blogAuthorName = d.getString(BLOG_AUTHOR_NAME); + byte[] blogPublicKey = d.getRaw(BLOG_PUBLIC_KEY); + String message = d.getOptionalString(INVITATION_MSG); + + return new BlogInvitation(groupId, sessionId, blogTitle, + blogDesc, blogAuthorName, blogPublicKey, message); + } + + public String getBlogTitle() { + return blogTitle; + } + + public String getBlogDesc() { + return blogDesc; + } + + public String getBlogAuthorName() { + return blogAuthorName; + } + + public byte[] getBlogPublicKey() { + return blogPublicKey; + } + } +} diff --git a/briar-api/src/org/briarproject/api/event/BlogInvitationReceivedEvent.java b/briar-api/src/org/briarproject/api/event/BlogInvitationReceivedEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..12d8d4cc4b8dec2dd91f2cf4bf1f80322f56f421 --- /dev/null +++ b/briar-api/src/org/briarproject/api/event/BlogInvitationReceivedEvent.java @@ -0,0 +1,18 @@ +package org.briarproject.api.event; + +import org.briarproject.api.blogs.Blog; +import org.briarproject.api.contact.ContactId; + +public class BlogInvitationReceivedEvent extends InvitationReceivedEvent { + + private final Blog blog; + + public BlogInvitationReceivedEvent(Blog blog, ContactId contactId) { + super(contactId); + this.blog = blog; + } + + public Blog getBlog() { + return blog; + } +} diff --git a/briar-api/src/org/briarproject/api/event/BlogInvitationResponseReceivedEvent.java b/briar-api/src/org/briarproject/api/event/BlogInvitationResponseReceivedEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..b6344ad928dd3c5e14155ad7c8dd7c70c69e3f38 --- /dev/null +++ b/briar-api/src/org/briarproject/api/event/BlogInvitationResponseReceivedEvent.java @@ -0,0 +1,18 @@ +package org.briarproject.api.event; + +import org.briarproject.api.contact.ContactId; + +public class BlogInvitationResponseReceivedEvent extends InvitationResponseReceivedEvent { + + private final String blogTitle; + + public BlogInvitationResponseReceivedEvent(String blogTitle, + ContactId contactId) { + super(contactId); + this.blogTitle = blogTitle; + } + + public String getBlogTitle() { + return blogTitle; + } +} diff --git a/briar-core/src/org/briarproject/sharing/BlogInviteeSessionState.java b/briar-core/src/org/briarproject/sharing/BlogInviteeSessionState.java new file mode 100644 index 0000000000000000000000000000000000000000..7bb3295b7b02a925718b08ca2da3875a25d58980 --- /dev/null +++ b/briar-core/src/org/briarproject/sharing/BlogInviteeSessionState.java @@ -0,0 +1,57 @@ +package org.briarproject.sharing; + +import org.briarproject.api.clients.SessionId; +import org.briarproject.api.contact.ContactId; +import org.briarproject.api.data.BdfDictionary; +import org.briarproject.api.sync.GroupId; +import org.briarproject.api.sync.MessageId; + +import static org.briarproject.api.blogs.BlogConstants.BLOG_AUTHOR_NAME; +import static org.briarproject.api.blogs.BlogConstants.BLOG_DESC; +import static org.briarproject.api.blogs.BlogConstants.BLOG_PUBLIC_KEY; +import static org.briarproject.api.blogs.BlogConstants.BLOG_TITLE; + +public class BlogInviteeSessionState extends InviteeSessionState { + + private final String blogTitle; + private final String blogDesc; + private final String blogAuthorName; + private final byte[] blogPublicKey; + + public BlogInviteeSessionState(SessionId sessionId, MessageId storageId, + GroupId groupId, State state, ContactId contactId, GroupId blogId, + String blogTitle, String blogDesc, String blogAuthorName, + byte[] blogPublicKey) { + super(sessionId, storageId, groupId, state, contactId, blogId); + + this.blogTitle = blogTitle; + this.blogDesc = blogDesc; + this.blogAuthorName = blogAuthorName; + this.blogPublicKey = blogPublicKey; + } + + public BdfDictionary toBdfDictionary() { + BdfDictionary d = super.toBdfDictionary(); + d.put(BLOG_TITLE, getBlogTitle()); + d.put(BLOG_DESC, getBlogDesc()); + d.put(BLOG_AUTHOR_NAME, getBlogAuthorName()); + d.put(BLOG_PUBLIC_KEY, getBlogPublicKey()); + return d; + } + + public String getBlogTitle() { + return blogTitle; + } + + public String getBlogDesc() { + return blogDesc; + } + + public String getBlogAuthorName() { + return blogAuthorName; + } + + public byte[] getBlogPublicKey() { + return blogPublicKey; + } +} diff --git a/briar-core/src/org/briarproject/sharing/BlogSharerSessionState.java b/briar-core/src/org/briarproject/sharing/BlogSharerSessionState.java new file mode 100644 index 0000000000000000000000000000000000000000..16ef1355b2183ab4d45c7074fef9e4b5c37b5e41 --- /dev/null +++ b/briar-core/src/org/briarproject/sharing/BlogSharerSessionState.java @@ -0,0 +1,57 @@ +package org.briarproject.sharing; + +import org.briarproject.api.clients.SessionId; +import org.briarproject.api.contact.ContactId; +import org.briarproject.api.data.BdfDictionary; +import org.briarproject.api.sync.GroupId; +import org.briarproject.api.sync.MessageId; + +import static org.briarproject.api.blogs.BlogConstants.BLOG_AUTHOR_NAME; +import static org.briarproject.api.blogs.BlogConstants.BLOG_DESC; +import static org.briarproject.api.blogs.BlogConstants.BLOG_PUBLIC_KEY; +import static org.briarproject.api.blogs.BlogConstants.BLOG_TITLE; + +public class BlogSharerSessionState extends SharerSessionState { + + private final String blogTitle; + private final String blogDesc; + private final String blogAuthorName; + private final byte[] blogPublicKey; + + public BlogSharerSessionState(SessionId sessionId, MessageId storageId, + GroupId groupId, State state, ContactId contactId, GroupId blogId, + String blogTitle, String blogDesc, String blogAuthorName, + byte[] blogPublicKey) { + super(sessionId, storageId, groupId, state, contactId, blogId); + + this.blogTitle = blogTitle; + this.blogDesc = blogDesc; + this.blogAuthorName = blogAuthorName; + this.blogPublicKey = blogPublicKey; + } + + public BdfDictionary toBdfDictionary() { + BdfDictionary d = super.toBdfDictionary(); + d.put(BLOG_TITLE, getBlogTitle()); + d.put(BLOG_DESC, getBlogDesc()); + d.put(BLOG_AUTHOR_NAME, getBlogAuthorName()); + d.put(BLOG_PUBLIC_KEY, getBlogPublicKey()); + return d; + } + + public String getBlogTitle() { + return blogTitle; + } + + public String getBlogDesc() { + return blogDesc; + } + + public String getBlogAuthorName() { + return blogAuthorName; + } + + public byte[] getBlogPublicKey() { + return blogPublicKey; + } +} diff --git a/briar-core/src/org/briarproject/sharing/BlogSharingManagerImpl.java b/briar-core/src/org/briarproject/sharing/BlogSharingManagerImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..ba67ff635ee898c342994773cf8f5b4dd9787160 --- /dev/null +++ b/briar-core/src/org/briarproject/sharing/BlogSharingManagerImpl.java @@ -0,0 +1,293 @@ +package org.briarproject.sharing; + +import org.briarproject.api.FormatException; +import org.briarproject.api.blogs.Blog; +import org.briarproject.api.blogs.BlogFactory; +import org.briarproject.api.blogs.BlogInvitationMessage; +import org.briarproject.api.blogs.BlogManager; +import org.briarproject.api.blogs.BlogSharingManager; +import org.briarproject.api.blogs.BlogSharingMessage.BlogInvitation; +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.ContactId; +import org.briarproject.api.data.BdfDictionary; +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.Transaction; +import org.briarproject.api.event.BlogInvitationReceivedEvent; +import org.briarproject.api.event.BlogInvitationResponseReceivedEvent; +import org.briarproject.api.identity.Author; +import org.briarproject.api.identity.AuthorFactory; +import org.briarproject.api.sync.ClientId; +import org.briarproject.api.sync.GroupId; +import org.briarproject.api.sync.MessageId; +import org.briarproject.api.system.Clock; +import org.briarproject.util.StringUtils; + +import java.security.SecureRandom; + +import javax.inject.Inject; + +import static org.briarproject.api.blogs.BlogConstants.BLOG_AUTHOR_NAME; +import static org.briarproject.api.blogs.BlogConstants.BLOG_DESC; +import static org.briarproject.api.blogs.BlogConstants.BLOG_PUBLIC_KEY; +import static org.briarproject.api.blogs.BlogConstants.BLOG_TITLE; + +class BlogSharingManagerImpl extends + SharingManagerImpl<Blog, BlogInvitation, BlogInvitationMessage, BlogInviteeSessionState, BlogSharerSessionState, BlogInvitationReceivedEvent, BlogInvitationResponseReceivedEvent> + implements BlogSharingManager { + + static final ClientId CLIENT_ID = new ClientId(StringUtils.fromHexString( + "bee438b5de0b3a685badc4e49d76e72d" + + "21e01c4b569a775112756bdae267a028")); + + private final BlogManager blogManager; + + private final SFactory sFactory; + private final IFactory iFactory; + private final ISFactory isFactory; + private final SSFactory ssFactory; + private final IRFactory irFactory; + private final IRRFactory irrFactory; + + @Inject + BlogSharingManagerImpl(AuthorFactory authorFactory, BlogFactory blogFactory, + BlogManager blogManager, ClientHelper clientHelper, Clock clock, + DatabaseComponent db, MessageQueueManager messageQueueManager, + MetadataEncoder metadataEncoder, MetadataParser metadataParser, + PrivateGroupFactory privateGroupFactory, SecureRandom random) { + + super(db, messageQueueManager, clientHelper, metadataParser, + metadataEncoder, random, privateGroupFactory, clock); + this.blogManager = blogManager; + + sFactory = new SFactory(authorFactory, blogFactory, blogManager); + iFactory = new IFactory(); + isFactory = new ISFactory(); + ssFactory = new SSFactory(); + irFactory = new IRFactory(sFactory); + irrFactory = new IRRFactory(); + } + + @Override + public ClientId getClientId() { + return CLIENT_ID; + } + + @Override + protected ClientId getShareableClientId() { + return blogManager.getClientId(); + } + + @Override + protected BlogInvitationMessage createInvitationMessage(MessageId id, + BlogInvitation msg, ContactId contactId, boolean available, + long time, boolean local, boolean sent, boolean seen, + boolean read) { + return new BlogInvitationMessage(id, msg.getSessionId(), contactId, + msg.getBlogTitle(), msg.getMessage(), available, time, local, + sent, seen, read); + } + + @Override + protected ShareableFactory<Blog, BlogInvitation, BlogInviteeSessionState, BlogSharerSessionState> getSFactory() { + return sFactory; + } + + @Override + protected InvitationFactory<BlogInvitation, BlogSharerSessionState> getIFactory() { + return iFactory; + } + + @Override + protected InviteeSessionStateFactory<Blog, BlogInviteeSessionState> getISFactory() { + return isFactory; + } + + @Override + protected SharerSessionStateFactory<Blog, BlogSharerSessionState> getSSFactory() { + return ssFactory; + } + + @Override + protected InvitationReceivedEventFactory<BlogInviteeSessionState, BlogInvitationReceivedEvent> getIRFactory() { + return irFactory; + } + + @Override + protected InvitationResponseReceivedEventFactory<BlogSharerSessionState, BlogInvitationResponseReceivedEvent> getIRRFactory() { + return irrFactory; + } + + static class SFactory implements + ShareableFactory<Blog, BlogInvitation, BlogInviteeSessionState, BlogSharerSessionState> { + + private final AuthorFactory authorFactory; + private final BlogFactory blogFactory; + private final BlogManager blogManager; + + SFactory(AuthorFactory authorFactory, BlogFactory BlogFactory, + BlogManager BlogManager) { + this.authorFactory = authorFactory; + this.blogFactory = BlogFactory; + this.blogManager = BlogManager; + } + + @Override + public BdfList encode(Blog f) { + return BdfList.of(f.getName(), f.getDescription(), + BdfList.of(f.getAuthor().getName(), + f.getAuthor().getPublicKey())); + } + + @Override + public Blog get(Transaction txn, GroupId groupId) + throws DbException { + return blogManager.getBlog(txn, groupId); + } + + @Override + public Blog parse(BdfList shareable) throws FormatException { + Author author = authorFactory + .createAuthor(shareable.getList(2).getString(0), + shareable.getList(2).getRaw(1)); + return blogFactory + .createBlog(shareable.getString(0), shareable.getString(1), + author); + } + + @Override + public Blog parse(BlogInvitation msg) { + Author author = authorFactory.createAuthor(msg.getBlogAuthorName(), + msg.getBlogPublicKey()); + return blogFactory + .createBlog(msg.getBlogTitle(), msg.getBlogDesc(), author); + } + + public Blog parse(BlogInviteeSessionState state) { + Author author = authorFactory + .createAuthor(state.getBlogAuthorName(), + state.getBlogPublicKey()); + return blogFactory + .createBlog(state.getBlogTitle(), state.getBlogDesc(), + author); + } + + @Override + public Blog parse(BlogSharerSessionState state) { + Author author = authorFactory + .createAuthor(state.getBlogAuthorName(), + state.getBlogPublicKey()); + return blogFactory + .createBlog(state.getBlogTitle(), state.getBlogDesc(), + author); + } + } + + static class IFactory implements + InvitationFactory<BlogInvitation, BlogSharerSessionState> { + @Override + public BlogInvitation build(GroupId groupId, BdfDictionary d) + throws FormatException { + return BlogInvitation.from(groupId, d); + } + + @Override + public BlogInvitation build(BlogSharerSessionState localState) { + return new BlogInvitation(localState.getGroupId(), + localState.getSessionId(), localState.getBlogTitle(), + localState.getBlogDesc(), localState.getBlogAuthorName(), + localState.getBlogPublicKey(), localState.getMessage()); + } + } + + static class ISFactory implements + InviteeSessionStateFactory<Blog, BlogInviteeSessionState> { + @Override + public BlogInviteeSessionState build(SessionId sessionId, + MessageId storageId, GroupId groupId, + InviteeSessionState.State state, ContactId contactId, + GroupId blogId, BdfDictionary d) throws FormatException { + String blogTitle = d.getString(BLOG_TITLE); + String blogDesc = d.getString(BLOG_DESC); + String blogAuthorName = d.getString(BLOG_AUTHOR_NAME); + byte[] blogPublicKey = d.getRaw(BLOG_PUBLIC_KEY); + return new BlogInviteeSessionState(sessionId, storageId, + groupId, state, contactId, blogId, blogTitle, blogDesc, + blogAuthorName, blogPublicKey); + } + + @Override + public BlogInviteeSessionState build(SessionId sessionId, + MessageId storageId, GroupId groupId, + InviteeSessionState.State state, ContactId contactId, + Blog blog) { + return new BlogInviteeSessionState(sessionId, storageId, + groupId, state, contactId, blog.getId(), blog.getName(), + blog.getDescription(), blog.getAuthor().getName(), + blog.getAuthor().getPublicKey()); + } + } + + static class SSFactory implements + SharerSessionStateFactory<Blog, BlogSharerSessionState> { + @Override + public BlogSharerSessionState build(SessionId sessionId, + MessageId storageId, GroupId groupId, + SharerSessionState.State state, ContactId contactId, + GroupId blogId, BdfDictionary d) throws FormatException { + String blogTitle = d.getString(BLOG_TITLE); + String blogDesc = d.getString(BLOG_DESC); + String blogAuthorName = d.getString(BLOG_AUTHOR_NAME); + byte[] blogPublicKey = d.getRaw(BLOG_PUBLIC_KEY); + return new BlogSharerSessionState(sessionId, storageId, + groupId, state, contactId, blogId, blogTitle, blogDesc, + blogAuthorName, blogPublicKey); + } + + @Override + public BlogSharerSessionState build(SessionId sessionId, + MessageId storageId, GroupId groupId, + SharerSessionState.State state, ContactId contactId, + Blog blog) { + return new BlogSharerSessionState(sessionId, storageId, + groupId, state, contactId, blog.getId(), blog.getName(), + blog.getDescription(), blog.getAuthor().getName(), + blog.getAuthor().getPublicKey()); + } + } + + static class IRFactory implements + InvitationReceivedEventFactory<BlogInviteeSessionState, BlogInvitationReceivedEvent> { + + private final SFactory sFactory; + + IRFactory(SFactory sFactory) { + this.sFactory = sFactory; + } + + @Override + public BlogInvitationReceivedEvent build( + BlogInviteeSessionState localState) { + Blog blog = sFactory.parse(localState); + ContactId contactId = localState.getContactId(); + return new BlogInvitationReceivedEvent(blog, contactId); + } + } + + static class IRRFactory implements + InvitationResponseReceivedEventFactory<BlogSharerSessionState, BlogInvitationResponseReceivedEvent> { + @Override + public BlogInvitationResponseReceivedEvent build( + BlogSharerSessionState localState) { + String title = localState.getBlogTitle(); + ContactId c = localState.getContactId(); + return new BlogInvitationResponseReceivedEvent(title, c); + } + } +} diff --git a/briar-core/src/org/briarproject/sharing/BlogSharingValidator.java b/briar-core/src/org/briarproject/sharing/BlogSharingValidator.java new file mode 100644 index 0000000000000000000000000000000000000000..26b89bb52c512c118e02ea5075226e42b5829eda --- /dev/null +++ b/briar-core/src/org/briarproject/sharing/BlogSharingValidator.java @@ -0,0 +1,98 @@ +package org.briarproject.sharing; + +import org.briarproject.api.FormatException; +import org.briarproject.api.clients.BdfMessageContext; +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 javax.inject.Inject; + +import static org.briarproject.api.blogs.BlogConstants.BLOG_AUTHOR_NAME; +import static org.briarproject.api.blogs.BlogConstants.BLOG_DESC; +import static org.briarproject.api.blogs.BlogConstants.BLOG_TITLE; +import static org.briarproject.api.blogs.BlogConstants.BLOG_PUBLIC_KEY; +import static org.briarproject.api.blogs.BlogConstants.MAX_BLOG_DESC_LENGTH; +import static org.briarproject.api.blogs.BlogConstants.MAX_BLOG_TITLE_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.sharing.SharingConstants.INVITATION_MSG; +import static org.briarproject.api.sharing.SharingConstants.LOCAL; +import static org.briarproject.api.sharing.SharingConstants.SESSION_ID; +import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ABORT; +import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_ACCEPT; +import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_DECLINE; +import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_INVITATION; +import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_LEAVE; +import static org.briarproject.api.sharing.SharingConstants.TIME; +import static org.briarproject.api.sharing.SharingConstants.TYPE; +import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH; + +class BlogSharingValidator extends BdfMessageValidator { + + @Inject + BlogSharingValidator(ClientHelper clientHelper, + MetadataEncoder metadataEncoder, Clock clock) { + super(clientHelper, metadataEncoder, clock); + } + + @Override + protected BdfMessageContext 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, 5, 6); + + String name = body.getString(2); + checkLength(name, 1, MAX_BLOG_TITLE_LENGTH); + + String desc = body.getString(3); + checkLength(desc, 1, MAX_BLOG_DESC_LENGTH); + + BdfList author = body.getList(4); + checkSize(author, 2); + + String authorName = author.getString(0); + checkLength(name, 1, MAX_AUTHOR_NAME_LENGTH); + + byte[] publicKey = author.getRaw(1); + checkLength(publicKey, 1, MAX_PUBLIC_KEY_LENGTH); + + d.put(BLOG_TITLE, name); + d.put(BLOG_DESC, desc); + d.put(BLOG_AUTHOR_NAME, authorName); + d.put(BLOG_PUBLIC_KEY, publicKey); + + if (body.size() > 5) { + String msg = body.getString(5); + 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(LOCAL, false); + d.put(TIME, m.getTimestamp()); + return new BdfMessageContext(d); + } +} diff --git a/briar-core/src/org/briarproject/sharing/SharingModule.java b/briar-core/src/org/briarproject/sharing/SharingModule.java index 228af6ed93b0703e31d4d377b20d3ad8474935bf..d62c7dccf7945810b7d271e85c4ac43e78131268 100644 --- a/briar-core/src/org/briarproject/sharing/SharingModule.java +++ b/briar-core/src/org/briarproject/sharing/SharingModule.java @@ -1,5 +1,6 @@ package org.briarproject.sharing; +import org.briarproject.api.blogs.BlogSharingManager; import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.MessageQueueManager; import org.briarproject.api.contact.ContactManager; @@ -19,12 +20,46 @@ import dagger.Provides; public class SharingModule { public static class EagerSingletons { + @Inject + BlogSharingValidator blogSharingValidator; @Inject ForumSharingValidator forumSharingValidator; @Inject ForumSharingManager forumSharingManager; } + @Provides + @Singleton + BlogSharingValidator provideBlogSharingValidator( + MessageQueueManager messageQueueManager, ClientHelper clientHelper, + MetadataEncoder metadataEncoder, Clock clock) { + + BlogSharingValidator + validator = new BlogSharingValidator(clientHelper, + metadataEncoder, clock); + messageQueueManager.registerMessageValidator( + BlogSharingManagerImpl.CLIENT_ID, validator); + + return validator; + } + + @Provides + @Singleton + BlogSharingManager provideBlogSharingManager( + LifecycleManager lifecycleManager, + ContactManager contactManager, + MessageQueueManager messageQueueManager, + BlogSharingManagerImpl blogSharingManager) { + + lifecycleManager.registerClient(blogSharingManager); + contactManager.registerAddContactHook(blogSharingManager); + contactManager.registerRemoveContactHook(blogSharingManager); + messageQueueManager.registerIncomingMessageHook( + BlogSharingManagerImpl.CLIENT_ID, blogSharingManager); + + return blogSharingManager; + } + @Provides @Singleton ForumSharingValidator provideForumSharingValidator(