mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-16 12:49:55 +01:00
Merge branch '892-separate-rss-blog' into 'master'
Separate RSS posts from personal blog posts Closes #892 See merge request !520
This commit is contained in:
@@ -13,7 +13,9 @@ import javax.annotation.concurrent.Immutable;
|
|||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public class Author {
|
public class Author {
|
||||||
|
|
||||||
public enum Status {ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES}
|
public enum Status {
|
||||||
|
NONE, ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES
|
||||||
|
}
|
||||||
|
|
||||||
private final AuthorId id;
|
private final AuthorId id;
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|||||||
@@ -68,8 +68,8 @@ import static org.briarproject.bramble.db.ExponentialBackoff.calculateExpiry;
|
|||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
abstract class JdbcDatabase implements Database<Connection> {
|
abstract class JdbcDatabase implements Database<Connection> {
|
||||||
|
|
||||||
private static final int SCHEMA_VERSION = 29;
|
private static final int SCHEMA_VERSION = 30;
|
||||||
private static final int MIN_SCHEMA_VERSION = 29;
|
private static final int MIN_SCHEMA_VERSION = 30;
|
||||||
|
|
||||||
private static final String CREATE_SETTINGS =
|
private static final String CREATE_SETTINGS =
|
||||||
"CREATE TABLE settings"
|
"CREATE TABLE settings"
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package org.briarproject.bramble.test;
|
||||||
|
|
||||||
|
import javax.net.SocketFactory;
|
||||||
|
|
||||||
|
import dagger.Module;
|
||||||
|
import dagger.Provides;
|
||||||
|
|
||||||
|
@Module
|
||||||
|
public class TestSocksModule {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
SocketFactory provideSocketFactory() {
|
||||||
|
return SocketFactory.getDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -48,6 +48,10 @@ public class BlogPostItem implements Comparable<BlogPostItem> {
|
|||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isRssFeed() {
|
||||||
|
return header.isRssFeed();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isRead() {
|
public boolean isRead() {
|
||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,7 +108,8 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
|||||||
author.setAuthor(a);
|
author.setAuthor(a);
|
||||||
author.setAuthorStatus(post.getAuthorStatus());
|
author.setAuthorStatus(post.getAuthorStatus());
|
||||||
author.setDate(post.getTimestamp());
|
author.setDate(post.getTimestamp());
|
||||||
author.setPersona(AuthorView.NORMAL);
|
author.setPersona(
|
||||||
|
item.isRssFeed() ? AuthorView.RSS_FEED : AuthorView.NORMAL);
|
||||||
// TODO make author clickable more often #624
|
// TODO make author clickable more often #624
|
||||||
if (item.getHeader().getType() == POST) {
|
if (item.getHeader().getType() == POST) {
|
||||||
author.setBlogLink(post.getGroupId());
|
author.setBlogLink(post.getGroupId());
|
||||||
@@ -168,7 +169,9 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
|||||||
reblogger.setVisibility(VISIBLE);
|
reblogger.setVisibility(VISIBLE);
|
||||||
reblogger.setPersona(AuthorView.REBLOGGER);
|
reblogger.setPersona(AuthorView.REBLOGGER);
|
||||||
|
|
||||||
author.setPersona(AuthorView.COMMENTER);
|
author.setPersona(item.getHeader().getRootPost().isRssFeed() ?
|
||||||
|
AuthorView.RSS_FEED_REBLOGGED :
|
||||||
|
AuthorView.COMMENTER);
|
||||||
|
|
||||||
// comments
|
// comments
|
||||||
for (BlogCommentHeader c : item.getComments()) {
|
for (BlogCommentHeader c : item.getComments()) {
|
||||||
|
|||||||
@@ -179,7 +179,6 @@ public class FeedFragment extends BaseFragment implements
|
|||||||
case R.id.action_rss_feeds_import:
|
case R.id.action_rss_feeds_import:
|
||||||
Intent i2 =
|
Intent i2 =
|
||||||
new Intent(getActivity(), RssFeedImportActivity.class);
|
new Intent(getActivity(), RssFeedImportActivity.class);
|
||||||
i2.putExtra(GROUP_ID, personalBlog.getId().getBytes());
|
|
||||||
startActivity(i2);
|
startActivity(i2);
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_rss_feeds_manage:
|
case R.id.action_rss_feeds_manage:
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageButton;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
@@ -39,12 +39,7 @@ class RssFeedAdapter extends BriarAdapter<Feed, RssFeedAdapter.FeedViewHolder> {
|
|||||||
if (item == null) return;
|
if (item == null) return;
|
||||||
|
|
||||||
// Feed Title
|
// Feed Title
|
||||||
if (item.getTitle() != null) {
|
ui.title.setText(item.getTitle());
|
||||||
ui.title.setText(item.getTitle());
|
|
||||||
ui.title.setVisibility(VISIBLE);
|
|
||||||
} else {
|
|
||||||
ui.title.setVisibility(GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete Button
|
// Delete Button
|
||||||
ui.delete.setOnClickListener(new OnClickListener() {
|
ui.delete.setOnClickListener(new OnClickListener() {
|
||||||
@@ -75,6 +70,14 @@ class RssFeedAdapter extends BriarAdapter<Feed, RssFeedAdapter.FeedViewHolder> {
|
|||||||
} else {
|
} else {
|
||||||
ui.description.setVisibility(GONE);
|
ui.description.setVisibility(GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Open feed's blog when clicked
|
||||||
|
ui.layout.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
listener.onFeedClick(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -99,8 +102,9 @@ class RssFeedAdapter extends BriarAdapter<Feed, RssFeedAdapter.FeedViewHolder> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static class FeedViewHolder extends RecyclerView.ViewHolder {
|
static class FeedViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
private final View layout;
|
||||||
private final TextView title;
|
private final TextView title;
|
||||||
private final ImageView delete;
|
private final ImageButton delete;
|
||||||
private final TextView imported;
|
private final TextView imported;
|
||||||
private final TextView updated;
|
private final TextView updated;
|
||||||
private final TextView author;
|
private final TextView author;
|
||||||
@@ -110,8 +114,9 @@ class RssFeedAdapter extends BriarAdapter<Feed, RssFeedAdapter.FeedViewHolder> {
|
|||||||
private FeedViewHolder(View v) {
|
private FeedViewHolder(View v) {
|
||||||
super(v);
|
super(v);
|
||||||
|
|
||||||
|
layout = v;
|
||||||
title = (TextView) v.findViewById(R.id.titleView);
|
title = (TextView) v.findViewById(R.id.titleView);
|
||||||
delete = (ImageView) v.findViewById(R.id.deleteButton);
|
delete = (ImageButton) v.findViewById(R.id.deleteButton);
|
||||||
imported = (TextView) v.findViewById(R.id.importedView);
|
imported = (TextView) v.findViewById(R.id.importedView);
|
||||||
updated = (TextView) v.findViewById(R.id.updatedView);
|
updated = (TextView) v.findViewById(R.id.updatedView);
|
||||||
author = (TextView) v.findViewById(R.id.authorView);
|
author = (TextView) v.findViewById(R.id.authorView);
|
||||||
@@ -121,6 +126,7 @@ class RssFeedAdapter extends BriarAdapter<Feed, RssFeedAdapter.FeedViewHolder> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface RssFeedListener {
|
interface RssFeedListener {
|
||||||
|
void onFeedClick(Feed feed);
|
||||||
void onDeleteClick(Feed feed);
|
void onDeleteClick(Feed feed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package org.briarproject.briar.android.blog;
|
package org.briarproject.briar.android.blog;
|
||||||
|
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
@@ -15,7 +14,6 @@ import android.widget.ProgressBar;
|
|||||||
|
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||||
import org.briarproject.bramble.api.sync.GroupId;
|
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||||
import org.briarproject.briar.android.activity.BriarActivity;
|
import org.briarproject.briar.android.activity.BriarActivity;
|
||||||
@@ -44,9 +42,6 @@ public class RssFeedImportActivity extends BriarActivity {
|
|||||||
@IoExecutor
|
@IoExecutor
|
||||||
Executor ioExecutor;
|
Executor ioExecutor;
|
||||||
|
|
||||||
// Fields that are accessed from background threads must be volatile
|
|
||||||
private volatile GroupId groupId = null;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
volatile FeedManager feedManager;
|
volatile FeedManager feedManager;
|
||||||
@@ -55,12 +50,6 @@ public class RssFeedImportActivity extends BriarActivity {
|
|||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
// GroupId from Intent
|
|
||||||
Intent i = getIntent();
|
|
||||||
byte[] b = i.getByteArrayExtra(GROUP_ID);
|
|
||||||
if (b == null) throw new IllegalStateException("No Group in intent.");
|
|
||||||
groupId = new GroupId(b);
|
|
||||||
|
|
||||||
setContentView(R.layout.activity_rss_feed_import);
|
setContentView(R.layout.activity_rss_feed_import);
|
||||||
|
|
||||||
urlInput = (EditText) findViewById(R.id.urlInput);
|
urlInput = (EditText) findViewById(R.id.urlInput);
|
||||||
@@ -128,7 +117,7 @@ public class RssFeedImportActivity extends BriarActivity {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
feedManager.addFeed(url, groupId);
|
feedManager.addFeed(url);
|
||||||
feedImported();
|
feedImported();
|
||||||
} catch (DbException | IOException e) {
|
} catch (DbException | IOException e) {
|
||||||
if (LOG.isLoggable(WARNING))
|
if (LOG.isLoggable(WARNING))
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
package org.briarproject.briar.android.blog;
|
package org.briarproject.briar.android.blog;
|
||||||
|
|
||||||
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.design.widget.Snackbar;
|
import android.support.design.widget.Snackbar;
|
||||||
|
import android.support.v7.app.AlertDialog;
|
||||||
import android.support.v7.widget.LinearLayoutManager;
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
import org.briarproject.bramble.api.sync.GroupId;
|
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||||
import org.briarproject.briar.android.activity.BriarActivity;
|
import org.briarproject.briar.android.activity.BriarActivity;
|
||||||
@@ -23,6 +24,7 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
||||||
import static android.support.design.widget.Snackbar.LENGTH_LONG;
|
import static android.support.design.widget.Snackbar.LENGTH_LONG;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
|
|
||||||
@@ -34,7 +36,6 @@ public class RssFeedManageActivity extends BriarActivity
|
|||||||
|
|
||||||
private BriarRecyclerView list;
|
private BriarRecyclerView list;
|
||||||
private RssFeedAdapter adapter;
|
private RssFeedAdapter adapter;
|
||||||
private GroupId groupId;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
@@ -44,12 +45,6 @@ public class RssFeedManageActivity extends BriarActivity
|
|||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
// GroupId from Intent
|
|
||||||
Intent i = getIntent();
|
|
||||||
byte[] b = i.getByteArrayExtra(GROUP_ID);
|
|
||||||
if (b == null) throw new IllegalStateException("No Group in intent.");
|
|
||||||
groupId = new GroupId(b);
|
|
||||||
|
|
||||||
setContentView(R.layout.activity_rss_feed_manage);
|
setContentView(R.layout.activity_rss_feed_manage);
|
||||||
|
|
||||||
adapter = new RssFeedAdapter(this, this);
|
adapter = new RssFeedAdapter(this, this);
|
||||||
@@ -87,7 +82,6 @@ public class RssFeedManageActivity extends BriarActivity
|
|||||||
return true;
|
return true;
|
||||||
case R.id.action_rss_feeds_import:
|
case R.id.action_rss_feeds_import:
|
||||||
Intent i = new Intent(this, RssFeedImportActivity.class);
|
Intent i = new Intent(this, RssFeedImportActivity.class);
|
||||||
i.putExtra(GROUP_ID, groupId.getBytes());
|
|
||||||
startActivity(i);
|
startActivity(i);
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
@@ -100,21 +94,32 @@ public class RssFeedManageActivity extends BriarActivity
|
|||||||
component.inject(this);
|
component.inject(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFeedClick(Feed feed) {
|
||||||
|
Intent i = new Intent(this, BlogActivity.class);
|
||||||
|
i.putExtra(GROUP_ID, feed.getBlogId().getBytes());
|
||||||
|
i.setFlags(FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
|
startActivity(i);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDeleteClick(final Feed feed) {
|
public void onDeleteClick(final Feed feed) {
|
||||||
runOnDbThread(new Runnable() {
|
DialogInterface.OnClickListener okListener =
|
||||||
@Override
|
new DialogInterface.OnClickListener() {
|
||||||
public void run() {
|
@Override
|
||||||
try {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
feedManager.removeFeed(feed.getUrl());
|
deleteFeed(feed);
|
||||||
onFeedDeleted(feed);
|
}
|
||||||
} catch (DbException e) {
|
};
|
||||||
if (LOG.isLoggable(WARNING))
|
AlertDialog.Builder builder = new AlertDialog.Builder(this,
|
||||||
LOG.log(WARNING, e.toString(), e);
|
R.style.BriarDialogTheme);
|
||||||
onDeleteError();
|
builder.setTitle(getString(R.string.blogs_rss_remove_feed));
|
||||||
}
|
builder.setMessage(
|
||||||
}
|
getString(R.string.blogs_rss_remove_feed_dialog_message));
|
||||||
});
|
builder.setPositiveButton(R.string.cancel, null);
|
||||||
|
builder.setNegativeButton(R.string.blogs_rss_remove_feed_ok,
|
||||||
|
okListener);
|
||||||
|
builder.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadFeeds() {
|
private void loadFeeds() {
|
||||||
@@ -149,6 +154,22 @@ public class RssFeedManageActivity extends BriarActivity
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void deleteFeed(final Feed feed) {
|
||||||
|
runOnDbThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
feedManager.removeFeed(feed);
|
||||||
|
onFeedDeleted(feed);
|
||||||
|
} catch (DbException e) {
|
||||||
|
if (LOG.isLoggable(WARNING))
|
||||||
|
LOG.log(WARNING, e.toString(), e);
|
||||||
|
onDeleteError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void onLoadError() {
|
private void onLoadError() {
|
||||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import static android.content.Context.LAYOUT_INFLATER_SERVICE;
|
|||||||
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
||||||
import static android.graphics.Typeface.BOLD;
|
import static android.graphics.Typeface.BOLD;
|
||||||
import static android.util.TypedValue.COMPLEX_UNIT_PX;
|
import static android.util.TypedValue.COMPLEX_UNIT_PX;
|
||||||
|
import static org.briarproject.bramble.api.identity.Author.Status.NONE;
|
||||||
import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
|
import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
|
||||||
import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
|
import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
|
||||||
|
|
||||||
@@ -40,6 +41,8 @@ public class AuthorView extends RelativeLayout {
|
|||||||
public static final int REBLOGGER = 1;
|
public static final int REBLOGGER = 1;
|
||||||
public static final int COMMENTER = 2;
|
public static final int COMMENTER = 2;
|
||||||
public static final int LIST = 3;
|
public static final int LIST = 3;
|
||||||
|
public static final int RSS_FEED = 4;
|
||||||
|
public static final int RSS_FEED_REBLOGGED = 5;
|
||||||
|
|
||||||
private final CircleImageView avatar;
|
private final CircleImageView avatar;
|
||||||
private final ImageView avatarIcon;
|
private final ImageView avatarIcon;
|
||||||
@@ -83,7 +86,13 @@ public class AuthorView extends RelativeLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setAuthorStatus(Status status) {
|
public void setAuthorStatus(Status status) {
|
||||||
trustIndicator.setTrustLevel(status);
|
if (status != NONE) {
|
||||||
|
trustIndicator.setTrustLevel(status);
|
||||||
|
trustIndicator.setVisibility(VISIBLE);
|
||||||
|
} else {
|
||||||
|
trustIndicator.setVisibility(GONE);
|
||||||
|
}
|
||||||
|
|
||||||
if (status == OURSELVES) {
|
if (status == OURSELVES) {
|
||||||
authorName.setTypeface(authorNameTypeface, BOLD);
|
authorName.setTypeface(authorNameTypeface, BOLD);
|
||||||
} else {
|
} else {
|
||||||
@@ -124,10 +133,17 @@ public class AuthorView extends RelativeLayout {
|
|||||||
setOnClickListener(null);
|
setOnClickListener(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Styles this view for a different persona.
|
||||||
|
*
|
||||||
|
* Attention: RSS_FEED and RSS_FEED_REBLOGGED change the avatar
|
||||||
|
* and override the one set by
|
||||||
|
* {@link AuthorView#setAuthor(Author)}.
|
||||||
|
*/
|
||||||
public void setPersona(int persona) {
|
public void setPersona(int persona) {
|
||||||
switch (persona) {
|
switch (persona) {
|
||||||
case NORMAL:
|
case NORMAL:
|
||||||
avatarIcon.setVisibility(VISIBLE);
|
avatarIcon.setVisibility(INVISIBLE);
|
||||||
date.setVisibility(VISIBLE);
|
date.setVisibility(VISIBLE);
|
||||||
setAvatarSize(R.dimen.blogs_avatar_normal_size);
|
setAvatarSize(R.dimen.blogs_avatar_normal_size);
|
||||||
setTextSize(authorName, R.dimen.text_size_small);
|
setTextSize(authorName, R.dimen.text_size_small);
|
||||||
@@ -158,6 +174,24 @@ public class AuthorView extends RelativeLayout {
|
|||||||
setCenterVertical(authorName, true);
|
setCenterVertical(authorName, true);
|
||||||
setCenterVertical(trustIndicator, true);
|
setCenterVertical(trustIndicator, true);
|
||||||
break;
|
break;
|
||||||
|
case RSS_FEED:
|
||||||
|
avatarIcon.setVisibility(INVISIBLE);
|
||||||
|
date.setVisibility(VISIBLE);
|
||||||
|
avatar.setImageResource(R.drawable.ic_rss_feed);
|
||||||
|
setAvatarSize(R.dimen.blogs_avatar_normal_size);
|
||||||
|
setTextSize(authorName, R.dimen.text_size_small);
|
||||||
|
setCenterVertical(authorName, false);
|
||||||
|
setCenterVertical(trustIndicator, false);
|
||||||
|
break;
|
||||||
|
case RSS_FEED_REBLOGGED:
|
||||||
|
avatarIcon.setVisibility(INVISIBLE);
|
||||||
|
date.setVisibility(VISIBLE);
|
||||||
|
avatar.setImageResource(R.drawable.ic_rss_feed);
|
||||||
|
setAvatarSize(R.dimen.blogs_avatar_comment_size);
|
||||||
|
setTextSize(authorName, R.dimen.text_size_tiny);
|
||||||
|
setCenterVertical(authorName, false);
|
||||||
|
setCenterVertical(trustIndicator, false);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
25
briar-android/src/main/res/drawable/ic_rss_feed.xml
Normal file
25
briar-android/src/main/res/drawable/ic_rss_feed.xml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="30dp"
|
||||||
|
android:height="30dp"
|
||||||
|
android:viewportHeight="30"
|
||||||
|
android:viewportWidth="30">
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:fillColor="#ffa500"
|
||||||
|
android:pathData="M0,8.88178e-16 L30,8.88178e-16 L30,30 L0,30 L0,8.88178e-16 Z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:pathData="M8.9322,18.0339 C10.6078,18.0339,11.9661,19.3922,11.9661,21.0678
|
||||||
|
C11.9661,22.7434,10.6078,24.1017,8.9322,24.1017
|
||||||
|
C7.25663,24.1017,5.8983,22.7434,5.8983,21.0678
|
||||||
|
C5.8983,19.3922,7.25663,18.0339,8.9322,18.0339 Z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:pathData="M5.8983,15 A9.1016949,9.1016949,0,0,1,15,24.1017 L18.0339,24.1017
|
||||||
|
A12.135593,12.135593,0,0,0,5.8983,11.9661 Z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:pathData="M5.8983,8.9322 A15.169492,15.169492,0,0,1,21.0678,24.1017 L24.1017,24.1017
|
||||||
|
A18.20339,18.20339,0,0,0,5.8983,5.8983 Z"/>
|
||||||
|
</vector>
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
android:textSize="@dimen/text_size_medium"
|
android:textSize="@dimen/text_size_medium"
|
||||||
tools:text="This is a name of a RSS Feed"/>
|
tools:text="This is a name of a RSS Feed"/>
|
||||||
|
|
||||||
<ImageView
|
<ImageButton
|
||||||
android:id="@+id/deleteButton"
|
android:id="@+id/deleteButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
<enum name="reblogger" value="1"/>
|
<enum name="reblogger" value="1"/>
|
||||||
<enum name="commenter" value="2"/>
|
<enum name="commenter" value="2"/>
|
||||||
<enum name="list" value="3"/>
|
<enum name="list" value="3"/>
|
||||||
|
<enum name="rss_feed" value="4"/>
|
||||||
|
<enum name="rss_feed_reblogged" value="5"/>
|
||||||
</attr>
|
</attr>
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
|
|||||||
@@ -304,6 +304,9 @@
|
|||||||
<string name="blogs_rss_feeds_manage_imported">Imported:</string>
|
<string name="blogs_rss_feeds_manage_imported">Imported:</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">Author:</string>
|
<string name="blogs_rss_feeds_manage_author">Author:</string>
|
||||||
<string name="blogs_rss_feeds_manage_updated">Last Updated:</string>
|
<string name="blogs_rss_feeds_manage_updated">Last Updated:</string>
|
||||||
|
<string name="blogs_rss_remove_feed">Remove Feed</string>
|
||||||
|
<string name="blogs_rss_remove_feed_dialog_message">Are you sure you want to remove this feed and all its posts?\nAny posts you have shared will not be removed from other people\'s devices.</string>
|
||||||
|
<string name="blogs_rss_remove_feed_ok">Remove Feed</string>
|
||||||
<string name="blogs_rss_feeds_manage_delete_error">The feed could not be deleted!</string>
|
<string name="blogs_rss_feeds_manage_delete_error">The feed could not be deleted!</string>
|
||||||
<string name="blogs_rss_feeds_manage_empty_state">You haven\'t imported any RSS feeds.\n\nWhy don\'t you click the plus in the top right screen corner to add your first?</string>
|
<string name="blogs_rss_feeds_manage_empty_state">You haven\'t imported any RSS feeds.\n\nWhy don\'t you click the plus in the top right screen corner to add your first?</string>
|
||||||
<string name="blogs_rss_feeds_manage_error">There was a problem loading your feeds. Please try again later.</string>
|
<string name="blogs_rss_feeds_manage_error">There was a problem loading your feeds. Please try again later.</string>
|
||||||
|
|||||||
@@ -13,16 +13,22 @@ import javax.annotation.concurrent.Immutable;
|
|||||||
public class Blog extends BaseGroup implements Shareable {
|
public class Blog extends BaseGroup implements Shareable {
|
||||||
|
|
||||||
private final Author author;
|
private final Author author;
|
||||||
|
private final boolean rssFeed;
|
||||||
|
|
||||||
public Blog(Group group, Author author) {
|
public Blog(Group group, Author author, boolean rssFeed) {
|
||||||
super(group);
|
super(group);
|
||||||
this.author = author;
|
this.author = author;
|
||||||
|
this.rssFeed = rssFeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Author getAuthor() {
|
public Author getAuthor() {
|
||||||
return author;
|
return author;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isRssFeed() {
|
||||||
|
return rssFeed;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
return o instanceof Blog && super.equals(o);
|
return o instanceof Blog && super.equals(o);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class BlogCommentHeader extends BlogPostHeader {
|
|||||||
Status authorStatus, boolean read) {
|
Status authorStatus, boolean read) {
|
||||||
|
|
||||||
super(type, groupId, id, parent.getId(), timestamp,
|
super(type, groupId, id, parent.getId(), timestamp,
|
||||||
timeReceived, author, authorStatus, read);
|
timeReceived, author, authorStatus, false, read);
|
||||||
|
|
||||||
if (type != COMMENT && type != WRAPPED_COMMENT)
|
if (type != COMMENT && type != WRAPPED_COMMENT)
|
||||||
throw new IllegalArgumentException("Incompatible Message Type");
|
throw new IllegalArgumentException("Incompatible Message Type");
|
||||||
@@ -43,4 +43,11 @@ public class BlogCommentHeader extends BlogPostHeader {
|
|||||||
public BlogPostHeader getParent() {
|
public BlogPostHeader getParent() {
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BlogPostHeader getRootPost() {
|
||||||
|
if (parent instanceof BlogCommentHeader)
|
||||||
|
return ((BlogCommentHeader) parent).getRootPost();
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ public interface BlogConstants {
|
|||||||
String KEY_AUTHOR_NAME = "name";
|
String KEY_AUTHOR_NAME = "name";
|
||||||
String KEY_PUBLIC_KEY = "publicKey";
|
String KEY_PUBLIC_KEY = "publicKey";
|
||||||
String KEY_AUTHOR = "author";
|
String KEY_AUTHOR = "author";
|
||||||
|
String KEY_RSS_FEED = "rssFeed";
|
||||||
String KEY_READ = "read";
|
String KEY_READ = "read";
|
||||||
String KEY_COMMENT = "comment";
|
String KEY_COMMENT = "comment";
|
||||||
String KEY_ORIGINAL_MSG_ID = "originalMessageId";
|
String KEY_ORIGINAL_MSG_ID = "originalMessageId";
|
||||||
|
|||||||
@@ -13,6 +13,11 @@ public interface BlogFactory {
|
|||||||
*/
|
*/
|
||||||
Blog createBlog(Author author);
|
Blog createBlog(Author author);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a RSS feed blog for a given author.
|
||||||
|
*/
|
||||||
|
Blog createFeedBlog(Author author);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a blog with the given Group
|
* Parses a blog with the given Group
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -41,6 +41,11 @@ public interface BlogManager {
|
|||||||
*/
|
*/
|
||||||
void removeBlog(Blog b) throws DbException;
|
void removeBlog(Blog b) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes and deletes a blog with the given {@link Transaction}.
|
||||||
|
*/
|
||||||
|
void removeBlog(Transaction txn, Blog b) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores a local blog post.
|
* Stores a local blog post.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -17,21 +17,23 @@ public class BlogPostHeader extends PostHeader {
|
|||||||
private final MessageType type;
|
private final MessageType type;
|
||||||
private final GroupId groupId;
|
private final GroupId groupId;
|
||||||
private final long timeReceived;
|
private final long timeReceived;
|
||||||
|
private final boolean rssFeed;
|
||||||
|
|
||||||
public BlogPostHeader(MessageType type, GroupId groupId, MessageId id,
|
public BlogPostHeader(MessageType type, GroupId groupId, MessageId id,
|
||||||
@Nullable MessageId parentId, long timestamp, long timeReceived,
|
@Nullable MessageId parentId, long timestamp, long timeReceived,
|
||||||
Author author, Status authorStatus, boolean read) {
|
Author author, Status authorStatus, boolean rssFeed, boolean read) {
|
||||||
super(id, parentId, timestamp, author, authorStatus, read);
|
super(id, parentId, timestamp, author, authorStatus, read);
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.groupId = groupId;
|
this.groupId = groupId;
|
||||||
this.timeReceived = timeReceived;
|
this.timeReceived = timeReceived;
|
||||||
|
this.rssFeed = rssFeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlogPostHeader(MessageType type, GroupId groupId, MessageId id,
|
public BlogPostHeader(MessageType type, GroupId groupId, MessageId id,
|
||||||
long timestamp, long timeReceived, Author author,
|
long timestamp, long timeReceived, Author author,
|
||||||
Status authorStatus, boolean read) {
|
Status authorStatus, boolean rssFeed, boolean read) {
|
||||||
this(type, groupId, id, null, timestamp, timeReceived, author,
|
this(type, groupId, id, null, timestamp, timeReceived, author,
|
||||||
authorStatus, read);
|
authorStatus, rssFeed, read);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MessageType getType() {
|
public MessageType getType() {
|
||||||
@@ -45,4 +47,9 @@ public class BlogPostHeader extends PostHeader {
|
|||||||
public long getTimeReceived() {
|
public long getTimeReceived() {
|
||||||
return timeReceived;
|
return timeReceived;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isRssFeed() {
|
||||||
|
return rssFeed;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,31 @@
|
|||||||
package org.briarproject.briar.api.feed;
|
package org.briarproject.briar.api.feed;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.FormatException;
|
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||||
import org.briarproject.bramble.api.data.BdfDictionary;
|
|
||||||
import org.briarproject.bramble.api.data.BdfEntry;
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.api.sync.GroupId;
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
|
import org.briarproject.briar.api.blog.Blog;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
|
|
||||||
import static org.briarproject.briar.api.feed.FeedConstants.KEY_BLOG_GROUP_ID;
|
|
||||||
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_ADDED;
|
|
||||||
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_AUTHOR;
|
|
||||||
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_DESC;
|
|
||||||
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_LAST_ENTRY;
|
|
||||||
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_TITLE;
|
|
||||||
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_UPDATED;
|
|
||||||
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_URL;
|
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public class Feed {
|
public class Feed {
|
||||||
|
|
||||||
private final String url;
|
private final String url;
|
||||||
private final GroupId blogId;
|
private final Blog blog;
|
||||||
|
private final LocalAuthor localAuthor;
|
||||||
@Nullable
|
@Nullable
|
||||||
private final String title, description, author;
|
private final String description, author;
|
||||||
private final long added, updated, lastEntryTime;
|
private final long added, updated, lastEntryTime;
|
||||||
|
|
||||||
public Feed(String url, GroupId blogId, @Nullable String title,
|
public Feed(String url, Blog blog, LocalAuthor localAuthor,
|
||||||
@Nullable String description, @Nullable String author,
|
@Nullable String description, @Nullable String author, long added,
|
||||||
long added, long updated, long lastEntryTime) {
|
long updated, long lastEntryTime) {
|
||||||
|
|
||||||
this.url = url;
|
this.url = url;
|
||||||
this.blogId = blogId;
|
this.blog = blog;
|
||||||
this.title = title;
|
this.localAuthor = localAuthor;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.author = author;
|
this.author = author;
|
||||||
this.added = added;
|
this.added = added;
|
||||||
@@ -42,13 +33,13 @@ public class Feed {
|
|||||||
this.lastEntryTime = lastEntryTime;
|
this.lastEntryTime = lastEntryTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Feed(String url, GroupId blogId, @Nullable String title,
|
public Feed(String url, Blog blog, LocalAuthor localAuthor,
|
||||||
@Nullable String description, @Nullable String author, long added) {
|
@Nullable String description, @Nullable String author, long added) {
|
||||||
this(url, blogId, title, description, author, added, 0L, 0L);
|
this(url, blog, localAuthor, description, author, added, 0L, 0L);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Feed(String url, GroupId blogId, long added) {
|
public Feed(String url, Blog blog, LocalAuthor localAuthor, long added) {
|
||||||
this(url, blogId, null, null, null, added, 0L, 0L);
|
this(url, blog, localAuthor, null, null, added, 0L, 0L);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUrl() {
|
public String getUrl() {
|
||||||
@@ -56,39 +47,19 @@ public class Feed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public GroupId getBlogId() {
|
public GroupId getBlogId() {
|
||||||
return blogId;
|
return blog.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BdfDictionary toBdfDictionary() {
|
public Blog getBlog() {
|
||||||
BdfDictionary d = BdfDictionary.of(
|
return blog;
|
||||||
new BdfEntry(KEY_FEED_URL, url),
|
|
||||||
new BdfEntry(KEY_BLOG_GROUP_ID, blogId.getBytes()),
|
|
||||||
new BdfEntry(KEY_FEED_ADDED, added),
|
|
||||||
new BdfEntry(KEY_FEED_UPDATED, updated),
|
|
||||||
new BdfEntry(KEY_FEED_LAST_ENTRY, lastEntryTime)
|
|
||||||
);
|
|
||||||
if (title != null) d.put(KEY_FEED_TITLE, title);
|
|
||||||
if (description != null) d.put(KEY_FEED_DESC, description);
|
|
||||||
if (author != null) d.put(KEY_FEED_AUTHOR, author);
|
|
||||||
return d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Feed from(BdfDictionary d) throws FormatException {
|
public LocalAuthor getLocalAuthor() {
|
||||||
String url = d.getString(KEY_FEED_URL);
|
return localAuthor;
|
||||||
GroupId blogId = new GroupId(d.getRaw(KEY_BLOG_GROUP_ID));
|
|
||||||
String title = d.getOptionalString(KEY_FEED_TITLE);
|
|
||||||
String desc = d.getOptionalString(KEY_FEED_DESC);
|
|
||||||
String author = d.getOptionalString(KEY_FEED_AUTHOR);
|
|
||||||
long added = d.getLong(KEY_FEED_ADDED, 0L);
|
|
||||||
long updated = d.getLong(KEY_FEED_UPDATED, 0L);
|
|
||||||
long lastEntryTime = d.getLong(KEY_FEED_LAST_ENTRY, 0L);
|
|
||||||
return new Feed(url, blogId, title, desc, author, added, updated,
|
|
||||||
lastEntryTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public String getTitle() {
|
public String getTitle() {
|
||||||
return title;
|
return blog.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -118,20 +89,9 @@ public class Feed {
|
|||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o instanceof Feed) {
|
if (o instanceof Feed) {
|
||||||
Feed f = (Feed) o;
|
Feed f = (Feed) o;
|
||||||
return url.equals(f.url) && blogId.equals(f.getBlogId()) &&
|
return blog.equals(f.blog);
|
||||||
equalsWithNull(title, f.getTitle()) &&
|
|
||||||
equalsWithNull(description, f.getDescription()) &&
|
|
||||||
equalsWithNull(author, f.getAuthor()) &&
|
|
||||||
added == f.getAdded() &&
|
|
||||||
updated == f.getUpdated() &&
|
|
||||||
lastEntryTime == f.getLastEntryTime();
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean equalsWithNull(@Nullable Object a, @Nullable Object b) {
|
|
||||||
if (a == b) return true;
|
|
||||||
if (a == null || b == null) return false;
|
|
||||||
return a.equals(b);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,9 @@ public interface FeedConstants {
|
|||||||
// group metadata keys
|
// group metadata keys
|
||||||
String KEY_FEEDS = "feeds";
|
String KEY_FEEDS = "feeds";
|
||||||
String KEY_FEED_URL = "feedURL";
|
String KEY_FEED_URL = "feedURL";
|
||||||
String KEY_BLOG_GROUP_ID = "blogGroupId";
|
String KEY_BLOG_TITLE = "blogTitle";
|
||||||
String KEY_FEED_TITLE = "feedTitle";
|
String KEY_PUBLIC_KEY = "publicKey";
|
||||||
|
String KEY_PRIVATE_KEY = "privateKey";
|
||||||
String KEY_FEED_DESC = "feedDesc";
|
String KEY_FEED_DESC = "feedDesc";
|
||||||
String KEY_FEED_AUTHOR = "feedAuthor";
|
String KEY_FEED_AUTHOR = "feedAuthor";
|
||||||
String KEY_FEED_ADDED = "feedAdded";
|
String KEY_FEED_ADDED = "feedAdded";
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package org.briarproject.briar.api.feed;
|
|||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.api.sync.ClientId;
|
import org.briarproject.bramble.api.sync.ClientId;
|
||||||
import org.briarproject.bramble.api.sync.GroupId;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -17,14 +16,14 @@ public interface FeedManager {
|
|||||||
ClientId CLIENT_ID = new ClientId("org.briarproject.briar.feed");
|
ClientId CLIENT_ID = new ClientId("org.briarproject.briar.feed");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an RSS feed.
|
* Adds an RSS feed as a new dedicated blog.
|
||||||
*/
|
*/
|
||||||
void addFeed(String url, GroupId g) throws DbException, IOException;
|
void addFeed(String url) throws DbException, IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes an RSS feed.
|
* Removes an RSS feed.
|
||||||
*/
|
*/
|
||||||
void removeFeed(String url) throws DbException;
|
void removeFeed(Feed feed) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of all added RSS feeds
|
* Returns a list of all added RSS feeds
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.briarproject.briar;
|
|||||||
|
|
||||||
import org.briarproject.briar.blog.BlogModule;
|
import org.briarproject.briar.blog.BlogModule;
|
||||||
import org.briarproject.briar.client.BriarClientModule;
|
import org.briarproject.briar.client.BriarClientModule;
|
||||||
|
import org.briarproject.briar.feed.DnsModule;
|
||||||
import org.briarproject.briar.feed.FeedModule;
|
import org.briarproject.briar.feed.FeedModule;
|
||||||
import org.briarproject.briar.forum.ForumModule;
|
import org.briarproject.briar.forum.ForumModule;
|
||||||
import org.briarproject.briar.introduction.IntroductionModule;
|
import org.briarproject.briar.introduction.IntroductionModule;
|
||||||
@@ -16,6 +17,7 @@ import dagger.Module;
|
|||||||
BlogModule.class,
|
BlogModule.class,
|
||||||
BriarClientModule.class,
|
BriarClientModule.class,
|
||||||
FeedModule.class,
|
FeedModule.class,
|
||||||
|
DnsModule.class,
|
||||||
ForumModule.class,
|
ForumModule.class,
|
||||||
GroupInvitationModule.class,
|
GroupInvitationModule.class,
|
||||||
IntroductionModule.class,
|
IntroductionModule.class,
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ import org.briarproject.briar.api.blog.BlogFactory;
|
|||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
|
||||||
|
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class BlogFactoryImpl implements BlogFactory {
|
class BlogFactoryImpl implements BlogFactory {
|
||||||
@@ -33,28 +36,46 @@ class BlogFactoryImpl implements BlogFactory {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Blog createBlog(Author a) {
|
public Blog createBlog(Author a) {
|
||||||
|
return createBlog(a, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Blog createFeedBlog(Author a) {
|
||||||
|
return createBlog(a, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Blog createBlog(Author a, boolean rssFeed) {
|
||||||
try {
|
try {
|
||||||
BdfList blog = BdfList.of(
|
BdfList blog = BdfList.of(
|
||||||
a.getName(),
|
a.getName(),
|
||||||
a.getPublicKey()
|
a.getPublicKey(),
|
||||||
|
rssFeed
|
||||||
);
|
);
|
||||||
byte[] descriptor = clientHelper.toByteArray(blog);
|
byte[] descriptor = clientHelper.toByteArray(blog);
|
||||||
Group g = groupFactory
|
Group g = groupFactory
|
||||||
.createGroup(BlogManagerImpl.CLIENT_ID, descriptor);
|
.createGroup(BlogManagerImpl.CLIENT_ID, descriptor);
|
||||||
return new Blog(g, a);
|
return new Blog(g, a, rssFeed);
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Blog parseBlog(Group g) throws FormatException {
|
public Blog parseBlog(Group group) throws FormatException {
|
||||||
byte[] descriptor = g.getDescriptor();
|
byte[] descriptor = group.getDescriptor();
|
||||||
// Author Name, Public Key
|
// Author Name, Public Key
|
||||||
BdfList blog = clientHelper.toList(descriptor);
|
BdfList blog = clientHelper.toList(descriptor);
|
||||||
Author a =
|
String name = blog.getString(0);
|
||||||
authorFactory.createAuthor(blog.getString(0), blog.getRaw(1));
|
if (name.length() > MAX_AUTHOR_NAME_LENGTH)
|
||||||
return new Blog(g, a);
|
throw new IllegalArgumentException();
|
||||||
|
byte[] publicKey = blog.getRaw(1);
|
||||||
|
if (publicKey.length > MAX_PUBLIC_KEY_LENGTH)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
|
||||||
|
Author author =
|
||||||
|
authorFactory.createAuthor(name, publicKey);
|
||||||
|
boolean rssFeed = blog.getBoolean(2);
|
||||||
|
return new Blog(group, author, rssFeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ import static org.briarproject.briar.api.blog.BlogConstants.KEY_ORIGINAL_PARENT_
|
|||||||
import static org.briarproject.briar.api.blog.BlogConstants.KEY_PARENT_MSG_ID;
|
import static org.briarproject.briar.api.blog.BlogConstants.KEY_PARENT_MSG_ID;
|
||||||
import static org.briarproject.briar.api.blog.BlogConstants.KEY_PUBLIC_KEY;
|
import static org.briarproject.briar.api.blog.BlogConstants.KEY_PUBLIC_KEY;
|
||||||
import static org.briarproject.briar.api.blog.BlogConstants.KEY_READ;
|
import static org.briarproject.briar.api.blog.BlogConstants.KEY_READ;
|
||||||
|
import static org.briarproject.briar.api.blog.BlogConstants.KEY_RSS_FEED;
|
||||||
import static org.briarproject.briar.api.blog.BlogConstants.KEY_TIMESTAMP;
|
import static org.briarproject.briar.api.blog.BlogConstants.KEY_TIMESTAMP;
|
||||||
import static org.briarproject.briar.api.blog.BlogConstants.KEY_TIME_RECEIVED;
|
import static org.briarproject.briar.api.blog.BlogConstants.KEY_TIME_RECEIVED;
|
||||||
import static org.briarproject.briar.api.blog.BlogConstants.KEY_TYPE;
|
import static org.briarproject.briar.api.blog.BlogConstants.KEY_TYPE;
|
||||||
@@ -224,6 +225,11 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeBlog(Transaction txn, Blog b) throws DbException {
|
||||||
|
removeBlog(txn, b, false);
|
||||||
|
}
|
||||||
|
|
||||||
private void removeBlog(Transaction txn, Blog b, boolean forced)
|
private void removeBlog(Transaction txn, Blog b, boolean forced)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
if (!forced && !canBeRemoved(txn, b.getId()))
|
if (!forced && !canBeRemoved(txn, b.getId()))
|
||||||
@@ -248,15 +254,18 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
|
|||||||
@Override
|
@Override
|
||||||
public void addLocalPost(Transaction txn, BlogPost p) throws DbException {
|
public void addLocalPost(Transaction txn, BlogPost p) throws DbException {
|
||||||
try {
|
try {
|
||||||
|
GroupId groupId = p.getMessage().getGroupId();
|
||||||
|
Blog b = getBlog(txn, groupId);
|
||||||
|
|
||||||
BdfDictionary meta = new BdfDictionary();
|
BdfDictionary meta = new BdfDictionary();
|
||||||
meta.put(KEY_TYPE, POST.getInt());
|
meta.put(KEY_TYPE, POST.getInt());
|
||||||
meta.put(KEY_TIMESTAMP, p.getMessage().getTimestamp());
|
meta.put(KEY_TIMESTAMP, p.getMessage().getTimestamp());
|
||||||
meta.put(KEY_AUTHOR, authorToBdfDictionary(p.getAuthor()));
|
meta.put(KEY_AUTHOR, authorToBdfDictionary(p.getAuthor()));
|
||||||
meta.put(KEY_READ, true);
|
meta.put(KEY_READ, true);
|
||||||
|
meta.put(KEY_RSS_FEED, b.isRssFeed());
|
||||||
clientHelper.addLocalMessage(txn, p.getMessage(), meta, true);
|
clientHelper.addLocalMessage(txn, p.getMessage(), meta, true);
|
||||||
|
|
||||||
// broadcast event about new post
|
// broadcast event about new post
|
||||||
GroupId groupId = p.getMessage().getGroupId();
|
|
||||||
MessageId postId = p.getMessage().getId();
|
MessageId postId = p.getMessage().getId();
|
||||||
BlogPostHeader h =
|
BlogPostHeader h =
|
||||||
getPostHeaderFromMetadata(txn, groupId, postId, meta);
|
getPostHeaderFromMetadata(txn, groupId, postId, meta);
|
||||||
@@ -345,6 +354,7 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
|
|||||||
wMessage = blogPostFactory
|
wMessage = blogPostFactory
|
||||||
.wrapPost(groupId, wDescriptor, wTimestamp, body);
|
.wrapPost(groupId, wDescriptor, wTimestamp, body);
|
||||||
meta.put(KEY_TYPE, WRAPPED_POST.getInt());
|
meta.put(KEY_TYPE, WRAPPED_POST.getInt());
|
||||||
|
meta.put(KEY_RSS_FEED, pOriginalHeader.isRssFeed());
|
||||||
} else if (type == COMMENT) {
|
} else if (type == COMMENT) {
|
||||||
Group wGroup = db.getGroup(txn, pOriginalHeader.getGroupId());
|
Group wGroup = db.getGroup(txn, pOriginalHeader.getGroupId());
|
||||||
byte[] wDescriptor = wGroup.getDescriptor();
|
byte[] wDescriptor = wGroup.getDescriptor();
|
||||||
@@ -593,8 +603,11 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
|
|||||||
String name = d.getString(KEY_AUTHOR_NAME);
|
String name = d.getString(KEY_AUTHOR_NAME);
|
||||||
byte[] publicKey = d.getRaw(KEY_PUBLIC_KEY);
|
byte[] publicKey = d.getRaw(KEY_PUBLIC_KEY);
|
||||||
Author author = new Author(authorId, name, publicKey);
|
Author author = new Author(authorId, name, publicKey);
|
||||||
|
boolean isFeedPost = meta.getBoolean(KEY_RSS_FEED, false);
|
||||||
Status authorStatus;
|
Status authorStatus;
|
||||||
if (authorStatuses.containsKey(authorId)) {
|
if (isFeedPost) {
|
||||||
|
authorStatus = Status.NONE;
|
||||||
|
} else if (authorStatuses.containsKey(authorId)) {
|
||||||
authorStatus = authorStatuses.get(authorId);
|
authorStatus = authorStatuses.get(authorId);
|
||||||
} else {
|
} else {
|
||||||
authorStatus = identityManager.getAuthorStatus(txn, authorId);
|
authorStatus = identityManager.getAuthorStatus(txn, authorId);
|
||||||
@@ -611,7 +624,7 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
|
|||||||
timestamp, timeReceived, author, authorStatus, read);
|
timestamp, timeReceived, author, authorStatus, read);
|
||||||
} else {
|
} else {
|
||||||
return new BlogPostHeader(type, groupId, id, timestamp,
|
return new BlogPostHeader(type, groupId, id, timestamp,
|
||||||
timeReceived, author, authorStatus, read);
|
timeReceived, author, authorStatus, isFeedPost, read);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import static org.briarproject.briar.api.blog.BlogConstants.KEY_ORIGINAL_PARENT_
|
|||||||
import static org.briarproject.briar.api.blog.BlogConstants.KEY_PARENT_MSG_ID;
|
import static org.briarproject.briar.api.blog.BlogConstants.KEY_PARENT_MSG_ID;
|
||||||
import static org.briarproject.briar.api.blog.BlogConstants.KEY_PUBLIC_KEY;
|
import static org.briarproject.briar.api.blog.BlogConstants.KEY_PUBLIC_KEY;
|
||||||
import static org.briarproject.briar.api.blog.BlogConstants.KEY_READ;
|
import static org.briarproject.briar.api.blog.BlogConstants.KEY_READ;
|
||||||
|
import static org.briarproject.briar.api.blog.BlogConstants.KEY_RSS_FEED;
|
||||||
import static org.briarproject.briar.api.blog.BlogConstants.KEY_TIMESTAMP;
|
import static org.briarproject.briar.api.blog.BlogConstants.KEY_TIMESTAMP;
|
||||||
import static org.briarproject.briar.api.blog.BlogConstants.KEY_TIME_RECEIVED;
|
import static org.briarproject.briar.api.blog.BlogConstants.KEY_TIME_RECEIVED;
|
||||||
import static org.briarproject.briar.api.blog.BlogConstants.KEY_TYPE;
|
import static org.briarproject.briar.api.blog.BlogConstants.KEY_TYPE;
|
||||||
@@ -123,6 +124,7 @@ class BlogPostValidator extends BdfMessageValidator {
|
|||||||
BdfDictionary meta = new BdfDictionary();
|
BdfDictionary meta = new BdfDictionary();
|
||||||
meta.put(KEY_ORIGINAL_MSG_ID, m.getId());
|
meta.put(KEY_ORIGINAL_MSG_ID, m.getId());
|
||||||
meta.put(KEY_AUTHOR, authorToBdfDictionary(a));
|
meta.put(KEY_AUTHOR, authorToBdfDictionary(a));
|
||||||
|
meta.put(KEY_RSS_FEED, b.isRssFeed());
|
||||||
return new BdfMessageContext(meta);
|
return new BdfMessageContext(meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package org.briarproject.briar.feed;
|
||||||
|
|
||||||
|
import dagger.Module;
|
||||||
|
import dagger.Provides;
|
||||||
|
import okhttp3.Dns;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a dedicated module, so it can be replaced for testing.
|
||||||
|
*/
|
||||||
|
@Module
|
||||||
|
public class DnsModule {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
Dns provideDns(NoDns noDns) {
|
||||||
|
return noDns;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package org.briarproject.briar.feed;
|
||||||
|
|
||||||
|
import com.rometools.rome.feed.synd.SyndFeed;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.FormatException;
|
||||||
|
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||||
|
import org.briarproject.briar.api.feed.Feed;
|
||||||
|
|
||||||
|
interface FeedFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new feed based on the feed url
|
||||||
|
* and the metadata of an existing {@link SyndFeed}.
|
||||||
|
*/
|
||||||
|
Feed createFeed(String url, SyndFeed feed);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new updated feed, based on the given existing feed,
|
||||||
|
* new metadata from the given {@link SyndFeed}
|
||||||
|
* and the time of the last feed entry.
|
||||||
|
*/
|
||||||
|
Feed createFeed(Feed feed, SyndFeed f, long lastEntryTime);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* De-serializes a {@link BdfDictionary} into a {@link Feed}.
|
||||||
|
*/
|
||||||
|
Feed createFeed(BdfDictionary d) throws FormatException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes a {@link Feed} into a {@link BdfDictionary}.
|
||||||
|
*/
|
||||||
|
BdfDictionary feedToBdfDictionary(Feed feed);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
package org.briarproject.briar.feed;
|
||||||
|
|
||||||
|
import com.rometools.rome.feed.synd.SyndFeed;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.FormatException;
|
||||||
|
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||||
|
import org.briarproject.bramble.api.crypto.KeyPair;
|
||||||
|
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||||
|
import org.briarproject.bramble.api.data.BdfEntry;
|
||||||
|
import org.briarproject.bramble.api.identity.AuthorFactory;
|
||||||
|
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||||
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
|
import org.briarproject.briar.api.blog.Blog;
|
||||||
|
import org.briarproject.briar.api.blog.BlogFactory;
|
||||||
|
import org.briarproject.briar.api.feed.Feed;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
|
||||||
|
import static org.briarproject.briar.api.feed.FeedConstants.KEY_BLOG_TITLE;
|
||||||
|
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_ADDED;
|
||||||
|
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_AUTHOR;
|
||||||
|
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_DESC;
|
||||||
|
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_LAST_ENTRY;
|
||||||
|
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_UPDATED;
|
||||||
|
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_URL;
|
||||||
|
import static org.briarproject.briar.api.feed.FeedConstants.KEY_PRIVATE_KEY;
|
||||||
|
import static org.briarproject.briar.api.feed.FeedConstants.KEY_PUBLIC_KEY;
|
||||||
|
|
||||||
|
class FeedFactoryImpl implements FeedFactory {
|
||||||
|
|
||||||
|
private final CryptoComponent cryptoComponent;
|
||||||
|
private final AuthorFactory authorFactory;
|
||||||
|
private final BlogFactory blogFactory;
|
||||||
|
private final Clock clock;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
FeedFactoryImpl(CryptoComponent cryptoComponent,
|
||||||
|
AuthorFactory authorFactory, BlogFactory blogFactory, Clock clock) {
|
||||||
|
this.cryptoComponent = cryptoComponent;
|
||||||
|
this.authorFactory = authorFactory;
|
||||||
|
this.blogFactory = blogFactory;
|
||||||
|
this.clock = clock;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Feed createFeed(String url, SyndFeed syndFeed) {
|
||||||
|
String title = syndFeed.getTitle();
|
||||||
|
if (title == null) title = "RSS";
|
||||||
|
title = StringUtils.truncateUtf8(title, MAX_AUTHOR_NAME_LENGTH);
|
||||||
|
|
||||||
|
KeyPair keyPair = cryptoComponent.generateSignatureKeyPair();
|
||||||
|
LocalAuthor localAuthor = authorFactory
|
||||||
|
.createLocalAuthor(title,
|
||||||
|
keyPair.getPublic().getEncoded(),
|
||||||
|
keyPair.getPrivate().getEncoded());
|
||||||
|
Blog blog = blogFactory.createFeedBlog(localAuthor);
|
||||||
|
long added = clock.currentTimeMillis();
|
||||||
|
|
||||||
|
return new Feed(url, blog, localAuthor, added);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Feed createFeed(Feed feed, SyndFeed f, long lastEntryTime) {
|
||||||
|
long updated = clock.currentTimeMillis();
|
||||||
|
return new Feed(feed.getUrl(), feed.getBlog(), feed.getLocalAuthor(),
|
||||||
|
f.getDescription(), f.getAuthor(), feed.getAdded(), updated,
|
||||||
|
lastEntryTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Feed createFeed(BdfDictionary d) throws FormatException {
|
||||||
|
String url = d.getString(KEY_FEED_URL);
|
||||||
|
|
||||||
|
String blogTitle = d.getString(KEY_BLOG_TITLE);
|
||||||
|
byte[] publicKey = d.getRaw(KEY_PUBLIC_KEY);
|
||||||
|
byte[] privateKey = d.getRaw(KEY_PRIVATE_KEY);
|
||||||
|
LocalAuthor localAuthor = authorFactory
|
||||||
|
.createLocalAuthor(blogTitle, publicKey, privateKey);
|
||||||
|
Blog blog = blogFactory.createFeedBlog(localAuthor);
|
||||||
|
|
||||||
|
String desc = d.getOptionalString(KEY_FEED_DESC);
|
||||||
|
String author = d.getOptionalString(KEY_FEED_AUTHOR);
|
||||||
|
long added = d.getLong(KEY_FEED_ADDED, 0L);
|
||||||
|
long updated = d.getLong(KEY_FEED_UPDATED, 0L);
|
||||||
|
long lastEntryTime = d.getLong(KEY_FEED_LAST_ENTRY, 0L);
|
||||||
|
|
||||||
|
return new Feed(url, blog, localAuthor, desc, author, added,
|
||||||
|
updated, lastEntryTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BdfDictionary feedToBdfDictionary(Feed feed) {
|
||||||
|
BdfDictionary d = BdfDictionary.of(
|
||||||
|
new BdfEntry(KEY_FEED_URL, feed.getUrl()),
|
||||||
|
new BdfEntry(KEY_BLOG_TITLE, feed.getLocalAuthor().getName()),
|
||||||
|
new BdfEntry(KEY_PUBLIC_KEY,
|
||||||
|
feed.getLocalAuthor().getPublicKey()),
|
||||||
|
new BdfEntry(KEY_PRIVATE_KEY,
|
||||||
|
feed.getLocalAuthor().getPrivateKey()),
|
||||||
|
new BdfEntry(KEY_FEED_ADDED, feed.getAdded()),
|
||||||
|
new BdfEntry(KEY_FEED_UPDATED, feed.getUpdated()),
|
||||||
|
new BdfEntry(KEY_FEED_LAST_ENTRY, feed.getLastEntryTime())
|
||||||
|
);
|
||||||
|
if (feed.getDescription() != null)
|
||||||
|
d.put(KEY_FEED_DESC, feed.getDescription());
|
||||||
|
if (feed.getAuthor() != null) d.put(KEY_FEED_AUTHOR, feed.getAuthor());
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -18,7 +18,6 @@ import org.briarproject.bramble.api.db.DbException;
|
|||||||
import org.briarproject.bramble.api.db.Transaction;
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
import org.briarproject.bramble.api.event.Event;
|
import org.briarproject.bramble.api.event.Event;
|
||||||
import org.briarproject.bramble.api.event.EventListener;
|
import org.briarproject.bramble.api.event.EventListener;
|
||||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
|
||||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
@@ -31,6 +30,7 @@ import org.briarproject.bramble.api.sync.GroupId;
|
|||||||
import org.briarproject.bramble.api.system.Clock;
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
import org.briarproject.bramble.api.system.Scheduler;
|
import org.briarproject.bramble.api.system.Scheduler;
|
||||||
import org.briarproject.bramble.util.StringUtils;
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
|
import org.briarproject.briar.api.blog.Blog;
|
||||||
import org.briarproject.briar.api.blog.BlogManager;
|
import org.briarproject.briar.api.blog.BlogManager;
|
||||||
import org.briarproject.briar.api.blog.BlogPost;
|
import org.briarproject.briar.api.blog.BlogPost;
|
||||||
import org.briarproject.briar.api.blog.BlogPostFactory;
|
import org.briarproject.briar.api.blog.BlogPostFactory;
|
||||||
@@ -39,8 +39,6 @@ import org.briarproject.briar.api.feed.FeedManager;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -75,12 +73,12 @@ import static org.briarproject.briar.util.HtmlUtils.clean;
|
|||||||
|
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class FeedManagerImpl implements FeedManager, Client, EventListener {
|
class FeedManagerImpl implements FeedManager, Client, EventListener,
|
||||||
|
BlogManager.RemoveBlogHook {
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(FeedManagerImpl.class.getName());
|
Logger.getLogger(FeedManagerImpl.class.getName());
|
||||||
|
|
||||||
private static final byte[] UNSPECIFIED_ADDRESS = new byte[4];
|
|
||||||
private static final int CONNECT_TIMEOUT = 60 * 1000; // Milliseconds
|
private static final int CONNECT_TIMEOUT = 60 * 1000; // Milliseconds
|
||||||
|
|
||||||
private final ScheduledExecutorService scheduler;
|
private final ScheduledExecutorService scheduler;
|
||||||
@@ -88,31 +86,33 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
|
|||||||
private final DatabaseComponent db;
|
private final DatabaseComponent db;
|
||||||
private final ContactGroupFactory contactGroupFactory;
|
private final ContactGroupFactory contactGroupFactory;
|
||||||
private final ClientHelper clientHelper;
|
private final ClientHelper clientHelper;
|
||||||
private final IdentityManager identityManager;
|
|
||||||
private final BlogManager blogManager;
|
private final BlogManager blogManager;
|
||||||
private final BlogPostFactory blogPostFactory;
|
private final BlogPostFactory blogPostFactory;
|
||||||
|
private final FeedFactory feedFactory;
|
||||||
private final SocketFactory torSocketFactory;
|
private final SocketFactory torSocketFactory;
|
||||||
private final Clock clock;
|
private final Clock clock;
|
||||||
|
private final Dns noDnsLookups;
|
||||||
private final AtomicBoolean fetcherStarted = new AtomicBoolean(false);
|
private final AtomicBoolean fetcherStarted = new AtomicBoolean(false);
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
FeedManagerImpl(@Scheduler ScheduledExecutorService scheduler,
|
FeedManagerImpl(@Scheduler ScheduledExecutorService scheduler,
|
||||||
@IoExecutor Executor ioExecutor, DatabaseComponent db,
|
@IoExecutor Executor ioExecutor, DatabaseComponent db,
|
||||||
ContactGroupFactory contactGroupFactory, ClientHelper clientHelper,
|
ContactGroupFactory contactGroupFactory, ClientHelper clientHelper,
|
||||||
IdentityManager identityManager, BlogManager blogManager,
|
BlogManager blogManager, BlogPostFactory blogPostFactory,
|
||||||
BlogPostFactory blogPostFactory, SocketFactory torSocketFactory,
|
FeedFactory feedFactory, SocketFactory torSocketFactory,
|
||||||
Clock clock) {
|
Clock clock, Dns noDnsLookups) {
|
||||||
|
|
||||||
this.scheduler = scheduler;
|
this.scheduler = scheduler;
|
||||||
this.ioExecutor = ioExecutor;
|
this.ioExecutor = ioExecutor;
|
||||||
this.db = db;
|
this.db = db;
|
||||||
this.contactGroupFactory = contactGroupFactory;
|
this.contactGroupFactory = contactGroupFactory;
|
||||||
this.clientHelper = clientHelper;
|
this.clientHelper = clientHelper;
|
||||||
this.identityManager = identityManager;
|
|
||||||
this.blogManager = blogManager;
|
this.blogManager = blogManager;
|
||||||
this.blogPostFactory = blogPostFactory;
|
this.blogPostFactory = blogPostFactory;
|
||||||
|
this.feedFactory = feedFactory;
|
||||||
this.torSocketFactory = torSocketFactory;
|
this.torSocketFactory = torSocketFactory;
|
||||||
this.clock = clock;
|
this.clock = clock;
|
||||||
|
this.noDnsLookups = noDnsLookups;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -158,21 +158,21 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addFeed(String url, GroupId g) throws DbException, IOException {
|
public void addFeed(String url) throws DbException, IOException {
|
||||||
LOG.info("Adding new RSS feed...");
|
// fetch syndication feed to get its metadata
|
||||||
|
SyndFeed f;
|
||||||
// TODO check for existing feed?
|
|
||||||
// fetch feed to get its metadata
|
|
||||||
Feed feed = new Feed(url, g, clock.currentTimeMillis());
|
|
||||||
try {
|
try {
|
||||||
feed = fetchFeed(feed, false);
|
f = fetchSyndFeed(url);
|
||||||
} catch (FeedException e) {
|
} catch (FeedException e) {
|
||||||
throw new IOException(e);
|
throw new IOException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// store feed
|
Feed feed = feedFactory.createFeed(url, f);
|
||||||
|
|
||||||
|
// store feed and new blog
|
||||||
Transaction txn = db.startTransaction(false);
|
Transaction txn = db.startTransaction(false);
|
||||||
try {
|
try {
|
||||||
|
blogManager.addBlog(txn, feed.getBlog());
|
||||||
List<Feed> feeds = getFeeds(txn);
|
List<Feed> feeds = getFeeds(txn);
|
||||||
feeds.add(feed);
|
feeds.add(feed);
|
||||||
storeFeeds(txn, feeds);
|
storeFeeds(txn, feeds);
|
||||||
@@ -181,10 +181,10 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
|
|||||||
db.endTransaction(txn);
|
db.endTransaction(txn);
|
||||||
}
|
}
|
||||||
|
|
||||||
// fetch feed again, post entries this time
|
// fetch feed again and post entries
|
||||||
Feed updatedFeed;
|
Feed updatedFeed;
|
||||||
try {
|
try {
|
||||||
updatedFeed = fetchFeed(feed, true);
|
updatedFeed = fetchFeed(feed);
|
||||||
} catch (FeedException e) {
|
} catch (FeedException e) {
|
||||||
throw new IOException(e);
|
throw new IOException(e);
|
||||||
}
|
}
|
||||||
@@ -203,27 +203,35 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeFeed(String url) throws DbException {
|
public void removeFeed(Feed feed) throws DbException {
|
||||||
LOG.info("Removing RSS feed...");
|
LOG.info("Removing RSS feed...");
|
||||||
Transaction txn = db.startTransaction(false);
|
Transaction txn = db.startTransaction(false);
|
||||||
try {
|
try {
|
||||||
List<Feed> feeds = getFeeds(txn);
|
// this will call removingBlog() where the feed itself gets removed
|
||||||
boolean found = false;
|
blogManager.removeBlog(txn, feed.getBlog());
|
||||||
for (Feed feed : feeds) {
|
|
||||||
if (feed.getUrl().equals(url)) {
|
|
||||||
found = true;
|
|
||||||
feeds.remove(feed);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found) throw new DbException();
|
|
||||||
storeFeeds(txn, feeds);
|
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(txn);
|
db.endTransaction(txn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removingBlog(Transaction txn, Blog b) throws DbException {
|
||||||
|
if (!b.isRssFeed()) return;
|
||||||
|
|
||||||
|
// delete blog's RSS feed if we have it
|
||||||
|
boolean found = false;
|
||||||
|
List<Feed> feeds = getFeeds(txn);
|
||||||
|
for (Feed f : feeds) {
|
||||||
|
if (f.getBlogId().equals(b.getId())) {
|
||||||
|
found = true;
|
||||||
|
feeds.remove(f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found) storeFeeds(txn, feeds);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Feed> getFeeds() throws DbException {
|
public List<Feed> getFeeds() throws DbException {
|
||||||
List<Feed> feeds;
|
List<Feed> feeds;
|
||||||
@@ -246,7 +254,7 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
|
|||||||
for (Object object : d.getList(KEY_FEEDS)) {
|
for (Object object : d.getList(KEY_FEEDS)) {
|
||||||
if (!(object instanceof BdfDictionary))
|
if (!(object instanceof BdfDictionary))
|
||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
feeds.add(Feed.from((BdfDictionary) object));
|
feeds.add(feedFactory.createFeed((BdfDictionary) object));
|
||||||
}
|
}
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
@@ -259,7 +267,7 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
|
|||||||
|
|
||||||
BdfList feedList = new BdfList();
|
BdfList feedList = new BdfList();
|
||||||
for (Feed feed : feeds) {
|
for (Feed feed : feeds) {
|
||||||
feedList.add(feed.toBdfDictionary());
|
feedList.add(feedFactory.feedToBdfDictionary(feed));
|
||||||
}
|
}
|
||||||
BdfDictionary gm = BdfDictionary.of(new BdfEntry(KEY_FEEDS, feedList));
|
BdfDictionary gm = BdfDictionary.of(new BdfEntry(KEY_FEEDS, feedList));
|
||||||
try {
|
try {
|
||||||
@@ -300,7 +308,7 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
|
|||||||
List<Feed> newFeeds = new ArrayList<Feed>(feeds.size());
|
List<Feed> newFeeds = new ArrayList<Feed>(feeds.size());
|
||||||
for (Feed feed : feeds) {
|
for (Feed feed : feeds) {
|
||||||
try {
|
try {
|
||||||
newFeeds.add(fetchFeed(feed, true));
|
newFeeds.add(fetchFeed(feed));
|
||||||
} catch (FeedException e) {
|
} catch (FeedException e) {
|
||||||
if (LOG.isLoggable(WARNING))
|
if (LOG.isLoggable(WARNING))
|
||||||
LOG.log(WARNING, e.toString(), e);
|
LOG.log(WARNING, e.toString(), e);
|
||||||
@@ -323,49 +331,52 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
|
|||||||
LOG.info("Done updating RSS feeds");
|
LOG.info("Done updating RSS feeds");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Feed fetchFeed(Feed feed, boolean post)
|
private SyndFeed fetchSyndFeed(String url)
|
||||||
throws FeedException, IOException, DbException {
|
throws FeedException, IOException {
|
||||||
String title, description, author;
|
// fetch feed
|
||||||
long updated = clock.currentTimeMillis();
|
SyndFeed f = getSyndFeed(getFeedInputStream(url));
|
||||||
long lastEntryTime = feed.getLastEntryTime();
|
|
||||||
|
|
||||||
SyndFeed f = getSyndFeed(getFeedInputStream(feed.getUrl()));
|
|
||||||
title = StringUtils.isNullOrEmpty(f.getTitle()) ? null : f.getTitle();
|
|
||||||
if (title != null) title = clean(title, STRIP_ALL);
|
|
||||||
description = StringUtils.isNullOrEmpty(f.getDescription()) ? null :
|
|
||||||
f.getDescription();
|
|
||||||
if (description != null) description = clean(description, STRIP_ALL);
|
|
||||||
author =
|
|
||||||
StringUtils.isNullOrEmpty(f.getAuthor()) ? null : f.getAuthor();
|
|
||||||
if (author != null) author = clean(author, STRIP_ALL);
|
|
||||||
|
|
||||||
if (f.getEntries().size() == 0)
|
if (f.getEntries().size() == 0)
|
||||||
throw new FeedException("Feed has no entries");
|
throw new FeedException("Feed has no entries");
|
||||||
|
|
||||||
|
// clean title
|
||||||
|
String title =
|
||||||
|
StringUtils.isNullOrEmpty(f.getTitle()) ? null : f.getTitle();
|
||||||
|
if (title != null) title = clean(title, STRIP_ALL);
|
||||||
|
f.setTitle(title);
|
||||||
|
|
||||||
|
// clean description
|
||||||
|
String description =
|
||||||
|
StringUtils.isNullOrEmpty(f.getDescription()) ? null :
|
||||||
|
f.getDescription();
|
||||||
|
if (description != null) description = clean(description, STRIP_ALL);
|
||||||
|
f.setDescription(description);
|
||||||
|
|
||||||
|
// clean author
|
||||||
|
String author =
|
||||||
|
StringUtils.isNullOrEmpty(f.getAuthor()) ? null : f.getAuthor();
|
||||||
|
if (author != null) author = clean(author, STRIP_ALL);
|
||||||
|
f.setAuthor(author);
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Feed fetchFeed(Feed feed)
|
||||||
|
throws FeedException, IOException, DbException {
|
||||||
|
// fetch and clean feed
|
||||||
|
SyndFeed f = fetchSyndFeed(feed.getUrl());
|
||||||
|
|
||||||
// sort and add new entries
|
// sort and add new entries
|
||||||
if (post) {
|
long lastEntryTime = postFeedEntries(feed, f.getEntries());
|
||||||
lastEntryTime = postFeedEntries(feed, f.getEntries());
|
|
||||||
}
|
return feedFactory.createFeed(feed, f, lastEntryTime);
|
||||||
return new Feed(feed.getUrl(), feed.getBlogId(), title, description,
|
|
||||||
author, feed.getAdded(), updated, lastEntryTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private InputStream getFeedInputStream(String url) throws IOException {
|
private InputStream getFeedInputStream(String url) throws IOException {
|
||||||
// Don't make local DNS lookups
|
|
||||||
Dns noLookups = new Dns() {
|
|
||||||
@Override
|
|
||||||
public List<InetAddress> lookup(String hostname)
|
|
||||||
throws UnknownHostException {
|
|
||||||
InetAddress unspecified =
|
|
||||||
InetAddress.getByAddress(hostname, UNSPECIFIED_ADDRESS);
|
|
||||||
return Collections.singletonList(unspecified);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Build HTTP Client
|
// Build HTTP Client
|
||||||
OkHttpClient client = new OkHttpClient.Builder()
|
OkHttpClient client = new OkHttpClient.Builder()
|
||||||
.socketFactory(torSocketFactory)
|
.socketFactory(torSocketFactory)
|
||||||
.dns(noLookups)
|
.dns(noDnsLookups) // Don't make local DNS lookups
|
||||||
.connectTimeout(CONNECT_TIMEOUT, MILLISECONDS)
|
.connectTimeout(CONNECT_TIMEOUT, MILLISECONDS)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@@ -422,9 +433,8 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
|
|||||||
|
|
||||||
// build post body
|
// build post body
|
||||||
StringBuilder b = new StringBuilder();
|
StringBuilder b = new StringBuilder();
|
||||||
if (feed.getTitle() != null) {
|
b.append("<h3>").append(feed.getTitle()).append("</h3>");
|
||||||
b.append("<h3>").append(feed.getTitle()).append("</h3>");
|
|
||||||
}
|
|
||||||
if (!StringUtils.isNullOrEmpty(entry.getTitle())) {
|
if (!StringUtils.isNullOrEmpty(entry.getTitle())) {
|
||||||
b.append("<h1>").append(entry.getTitle()).append("</h1>");
|
b.append("<h1>").append(entry.getTitle()).append("</h1>");
|
||||||
}
|
}
|
||||||
@@ -461,9 +471,9 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
|
|||||||
String body = getPostBody(b.toString());
|
String body = getPostBody(b.toString());
|
||||||
try {
|
try {
|
||||||
// create and store post
|
// create and store post
|
||||||
LocalAuthor author = identityManager.getLocalAuthor(txn);
|
LocalAuthor localAuthor = feed.getLocalAuthor();
|
||||||
BlogPost post = blogPostFactory
|
BlogPost post = blogPostFactory
|
||||||
.createBlogPost(groupId, time, null, author, body);
|
.createBlogPost(groupId, time, null, localAuthor, body);
|
||||||
blogManager.addLocalPost(txn, post);
|
blogManager.addLocalPost(txn, post);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING))
|
if (LOG.isLoggable(WARNING))
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.briarproject.briar.feed;
|
|||||||
|
|
||||||
import org.briarproject.bramble.api.event.EventBus;
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
|
import org.briarproject.briar.api.blog.BlogManager;
|
||||||
import org.briarproject.briar.api.feed.FeedManager;
|
import org.briarproject.briar.api.feed.FeedManager;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@@ -21,11 +22,18 @@ public class FeedModule {
|
|||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
FeedManager provideFeedManager(FeedManagerImpl feedManager,
|
FeedManager provideFeedManager(FeedManagerImpl feedManager,
|
||||||
LifecycleManager lifecycleManager, EventBus eventBus) {
|
LifecycleManager lifecycleManager, EventBus eventBus,
|
||||||
|
BlogManager blogManager) {
|
||||||
|
|
||||||
lifecycleManager.registerClient(feedManager);
|
lifecycleManager.registerClient(feedManager);
|
||||||
eventBus.addListener(feedManager);
|
eventBus.addListener(feedManager);
|
||||||
|
blogManager.registerRemoveBlogHook(feedManager);
|
||||||
return feedManager;
|
return feedManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
FeedFactory provideFeedFactory(FeedFactoryImpl feedFactory) {
|
||||||
|
return feedFactory;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package org.briarproject.briar.feed;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import okhttp3.Dns;
|
||||||
|
|
||||||
|
class NoDns implements Dns {
|
||||||
|
|
||||||
|
private static final byte[] UNSPECIFIED_ADDRESS = new byte[4];
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public NoDns() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<InetAddress> lookup(String hostname)
|
||||||
|
throws UnknownHostException {
|
||||||
|
InetAddress unspecified =
|
||||||
|
InetAddress.getByAddress(hostname, UNSPECIFIED_ADDRESS);
|
||||||
|
return Collections.singletonList(unspecified);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -39,14 +39,20 @@ class BlogSharingValidator extends SharingValidator {
|
|||||||
@Override
|
@Override
|
||||||
protected GroupId validateDescriptor(BdfList descriptor)
|
protected GroupId validateDescriptor(BdfList descriptor)
|
||||||
throws FormatException {
|
throws FormatException {
|
||||||
checkSize(descriptor, 2);
|
checkSize(descriptor, 3);
|
||||||
String name = descriptor.getString(0);
|
String name = descriptor.getString(0);
|
||||||
checkLength(name, 1, MAX_AUTHOR_NAME_LENGTH);
|
checkLength(name, 1, MAX_AUTHOR_NAME_LENGTH);
|
||||||
byte[] publicKey = descriptor.getRaw(1);
|
byte[] publicKey = descriptor.getRaw(1);
|
||||||
checkLength(publicKey, 1, MAX_PUBLIC_KEY_LENGTH);
|
checkLength(publicKey, 1, MAX_PUBLIC_KEY_LENGTH);
|
||||||
|
boolean rssFeed = descriptor.getBoolean(2);
|
||||||
|
|
||||||
Author author = authorFactory.createAuthor(name, publicKey);
|
Author author = authorFactory.createAuthor(name, publicKey);
|
||||||
Blog blog = blogFactory.createBlog(author);
|
Blog blog;
|
||||||
|
if (rssFeed) {
|
||||||
|
blog = blogFactory.createFeedBlog(author);
|
||||||
|
} else {
|
||||||
|
blog = blogFactory.createBlog(author);
|
||||||
|
}
|
||||||
return blog.getId();
|
return blog.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -297,7 +297,7 @@ public class BlogManagerImplTest extends BriarTestCase {
|
|||||||
final LocalAuthor localAuthor =
|
final LocalAuthor localAuthor =
|
||||||
new LocalAuthor(authorId, "Author", publicKey, privateKey,
|
new LocalAuthor(authorId, "Author", publicKey, privateKey,
|
||||||
created);
|
created);
|
||||||
return new Blog(group, localAuthor);
|
return new Blog(group, localAuthor, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BdfDictionary authorToBdfDictionary(Author a) {
|
private BdfDictionary authorToBdfDictionary(Author a) {
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package org.briarproject.briar.blog;
|
package org.briarproject.briar.blog;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
|
import org.briarproject.bramble.api.identity.Author;
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
import org.briarproject.bramble.test.TestDatabaseModule;
|
import org.briarproject.bramble.test.TestDatabaseModule;
|
||||||
import org.briarproject.briar.api.blog.Blog;
|
import org.briarproject.briar.api.blog.Blog;
|
||||||
@@ -32,7 +34,7 @@ public class BlogManagerIntegrationTest
|
|||||||
extends BriarIntegrationTest<BriarIntegrationTestComponent> {
|
extends BriarIntegrationTest<BriarIntegrationTestComponent> {
|
||||||
|
|
||||||
private BlogManager blogManager0, blogManager1;
|
private BlogManager blogManager0, blogManager1;
|
||||||
private Blog blog0, blog1;
|
private Blog blog0, blog1, rssBlog;
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
public ExpectedException thrown = ExpectedException.none();
|
public ExpectedException thrown = ExpectedException.none();
|
||||||
@@ -50,6 +52,12 @@ public class BlogManagerIntegrationTest
|
|||||||
|
|
||||||
blog0 = blogFactory.createBlog(author0);
|
blog0 = blogFactory.createBlog(author0);
|
||||||
blog1 = blogFactory.createBlog(author1);
|
blog1 = blogFactory.createBlog(author1);
|
||||||
|
|
||||||
|
rssBlog = blogFactory.createFeedBlog(author0);
|
||||||
|
Transaction txn = db0.startTransaction(false);
|
||||||
|
blogManager0.addBlog(txn, rssBlog);
|
||||||
|
db0.commitTransaction(txn);
|
||||||
|
db0.endTransaction(txn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -393,4 +401,63 @@ public class BlogManagerIntegrationTest
|
|||||||
assertEquals(2, headers0.size());
|
assertEquals(2, headers0.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFeedPost() throws Exception {
|
||||||
|
assertTrue(rssBlog.isRssFeed());
|
||||||
|
|
||||||
|
// add a feed post to rssBlog
|
||||||
|
final String body = getRandomString(42);
|
||||||
|
BlogPost p = blogPostFactory
|
||||||
|
.createBlogPost(rssBlog.getId(), clock.currentTimeMillis(),
|
||||||
|
null, author0, body);
|
||||||
|
blogManager0.addLocalPost(p);
|
||||||
|
|
||||||
|
// make sure it got saved as an RSS feed post
|
||||||
|
Collection<BlogPostHeader> headers =
|
||||||
|
blogManager0.getPostHeaders(rssBlog.getId());
|
||||||
|
assertEquals(1, headers.size());
|
||||||
|
BlogPostHeader header = headers.iterator().next();
|
||||||
|
assertEquals(POST, header.getType());
|
||||||
|
assertEquals(Author.Status.NONE, header.getAuthorStatus());
|
||||||
|
assertTrue(header.isRssFeed());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFeedReblog() throws Exception {
|
||||||
|
// add a feed post to rssBlog
|
||||||
|
final String body = getRandomString(42);
|
||||||
|
BlogPost p = blogPostFactory
|
||||||
|
.createBlogPost(rssBlog.getId(), clock.currentTimeMillis(),
|
||||||
|
null, author0, body);
|
||||||
|
blogManager0.addLocalPost(p);
|
||||||
|
|
||||||
|
// reblog feed post to own blog
|
||||||
|
Collection<BlogPostHeader> headers =
|
||||||
|
blogManager0.getPostHeaders(rssBlog.getId());
|
||||||
|
assertEquals(1, headers.size());
|
||||||
|
BlogPostHeader header = headers.iterator().next();
|
||||||
|
blogManager0.addLocalComment(author0, blog0.getId(), null, header);
|
||||||
|
|
||||||
|
// make sure it got saved as an RSS feed post
|
||||||
|
headers = blogManager0.getPostHeaders(blog0.getId());
|
||||||
|
assertEquals(1, headers.size());
|
||||||
|
BlogCommentHeader commentHeader =
|
||||||
|
(BlogCommentHeader) headers.iterator().next();
|
||||||
|
assertEquals(COMMENT, commentHeader.getType());
|
||||||
|
assertTrue(commentHeader.getParent().isRssFeed());
|
||||||
|
|
||||||
|
// reblog reblogged post again to own blog
|
||||||
|
blogManager0
|
||||||
|
.addLocalComment(author0, blog0.getId(), null, commentHeader);
|
||||||
|
|
||||||
|
// make sure it got saved as an RSS feed post
|
||||||
|
headers = blogManager0.getPostHeaders(blog0.getId());
|
||||||
|
assertEquals(2, headers.size());
|
||||||
|
for (BlogPostHeader h: headers) {
|
||||||
|
assertTrue(h instanceof BlogCommentHeader);
|
||||||
|
assertEquals(COMMENT, h.getType());
|
||||||
|
assertTrue(((BlogCommentHeader) h).getRootPost().isRssFeed());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ public class BlogPostValidatorTest extends BriarTestCase {
|
|||||||
new BdfEntry(KEY_AUTHOR_NAME, author.getName()),
|
new BdfEntry(KEY_AUTHOR_NAME, author.getName()),
|
||||||
new BdfEntry(KEY_PUBLIC_KEY, author.getPublicKey())
|
new BdfEntry(KEY_PUBLIC_KEY, author.getPublicKey())
|
||||||
);
|
);
|
||||||
blog = new Blog(group, author);
|
blog = new Blog(group, author, false);
|
||||||
|
|
||||||
MessageId messageId = new MessageId(TestUtils.getRandomId());
|
MessageId messageId = new MessageId(TestUtils.getRandomId());
|
||||||
long timestamp = System.currentTimeMillis();
|
long timestamp = System.currentTimeMillis();
|
||||||
|
|||||||
@@ -0,0 +1,127 @@
|
|||||||
|
package org.briarproject.briar.feed;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
|
import org.briarproject.bramble.contact.ContactModule;
|
||||||
|
import org.briarproject.bramble.crypto.CryptoModule;
|
||||||
|
import org.briarproject.bramble.identity.IdentityModule;
|
||||||
|
import org.briarproject.bramble.lifecycle.LifecycleModule;
|
||||||
|
import org.briarproject.bramble.sync.SyncModule;
|
||||||
|
import org.briarproject.bramble.system.SystemModule;
|
||||||
|
import org.briarproject.bramble.test.TestDatabaseModule;
|
||||||
|
import org.briarproject.bramble.test.TestUtils;
|
||||||
|
import org.briarproject.bramble.transport.TransportModule;
|
||||||
|
import org.briarproject.briar.api.blog.Blog;
|
||||||
|
import org.briarproject.briar.api.blog.BlogManager;
|
||||||
|
import org.briarproject.briar.api.blog.BlogPostHeader;
|
||||||
|
import org.briarproject.briar.api.feed.Feed;
|
||||||
|
import org.briarproject.briar.api.feed.FeedManager;
|
||||||
|
import org.briarproject.briar.blog.BlogModule;
|
||||||
|
import org.briarproject.briar.test.BriarTestCase;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
public class FeedManagerIntegrationTest extends BriarTestCase {
|
||||||
|
|
||||||
|
private LifecycleManager lifecycleManager;
|
||||||
|
private FeedManager feedManager;
|
||||||
|
private BlogManager blogManager;
|
||||||
|
private final File testDir = TestUtils.getTestDirectory();
|
||||||
|
private final File testFile = new File(testDir, "feedTest");
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
assertTrue(testDir.mkdirs());
|
||||||
|
FeedManagerIntegrationTestComponent component =
|
||||||
|
DaggerFeedManagerIntegrationTestComponent.builder()
|
||||||
|
.testDatabaseModule(new TestDatabaseModule(testFile))
|
||||||
|
.build();
|
||||||
|
component.inject(this);
|
||||||
|
injectEagerSingletons(component);
|
||||||
|
|
||||||
|
lifecycleManager = component.getLifecycleManager();
|
||||||
|
lifecycleManager.startServices("feedTest");
|
||||||
|
lifecycleManager.waitForStartup();
|
||||||
|
|
||||||
|
feedManager = component.getFeedManager();
|
||||||
|
blogManager = component.getBlogManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFeedImportAndRemoval() throws Exception {
|
||||||
|
// initially, there's only the one personal blog
|
||||||
|
Collection<Blog> blogs = blogManager.getBlogs();
|
||||||
|
assertEquals(1, blogs.size());
|
||||||
|
Blog personalBlog = blogs.iterator().next();
|
||||||
|
|
||||||
|
// add feed into a dedicated blog
|
||||||
|
String url = "https://www.schneier.com/blog/atom.xml";
|
||||||
|
feedManager.addFeed(url);
|
||||||
|
|
||||||
|
// then there's the feed's blog now
|
||||||
|
blogs = blogManager.getBlogs();
|
||||||
|
assertEquals(2, blogs.size());
|
||||||
|
Blog feedBlog = null;
|
||||||
|
for (Blog blog : blogs) {
|
||||||
|
if (!blog.equals(personalBlog)) feedBlog = blog;
|
||||||
|
}
|
||||||
|
assertNotNull(feedBlog);
|
||||||
|
|
||||||
|
// check the feed got saved as expected
|
||||||
|
Collection<Feed> feeds = feedManager.getFeeds();
|
||||||
|
assertEquals(1, feeds.size());
|
||||||
|
Feed feed = feeds.iterator().next();
|
||||||
|
assertTrue(feed.getLastEntryTime() > 0);
|
||||||
|
assertTrue(feed.getAdded() > 0);
|
||||||
|
assertTrue(feed.getUpdated() > 0);
|
||||||
|
assertEquals(url, feed.getUrl());
|
||||||
|
assertEquals(feedBlog, feed.getBlog());
|
||||||
|
assertEquals("Schneier on Security", feed.getTitle());
|
||||||
|
assertEquals("A blog covering security and security technology.",
|
||||||
|
feed.getDescription());
|
||||||
|
assertEquals(feed.getTitle(), feed.getBlog().getName());
|
||||||
|
assertEquals(feed.getTitle(), feed.getLocalAuthor().getName());
|
||||||
|
|
||||||
|
// check the feed entries have been added to the blog as expected
|
||||||
|
Collection<BlogPostHeader> headers =
|
||||||
|
blogManager.getPostHeaders(feedBlog.getId());
|
||||||
|
for (BlogPostHeader header : headers) {
|
||||||
|
assertTrue(header.isRssFeed());
|
||||||
|
}
|
||||||
|
|
||||||
|
// now let's remove the feed's blog again
|
||||||
|
blogManager.removeBlog(feedBlog);
|
||||||
|
blogs = blogManager.getBlogs();
|
||||||
|
assertEquals(1, blogs.size());
|
||||||
|
assertEquals(personalBlog, blogs.iterator().next());
|
||||||
|
assertEquals(0, feedManager.getFeeds().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
lifecycleManager.stopServices();
|
||||||
|
lifecycleManager.waitForShutdown();
|
||||||
|
TestUtils.deleteTestDirectory(testDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void injectEagerSingletons(
|
||||||
|
FeedManagerIntegrationTestComponent component) {
|
||||||
|
component.inject(new FeedModule.EagerSingletons());
|
||||||
|
component.inject(new BlogModule.EagerSingletons());
|
||||||
|
component.inject(new ContactModule.EagerSingletons());
|
||||||
|
component.inject(new CryptoModule.EagerSingletons());
|
||||||
|
component.inject(new IdentityModule.EagerSingletons());
|
||||||
|
component.inject(new LifecycleModule.EagerSingletons());
|
||||||
|
component.inject(new SyncModule.EagerSingletons());
|
||||||
|
component.inject(new SystemModule.EagerSingletons());
|
||||||
|
component.inject(new TransportModule.EagerSingletons());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
package org.briarproject.briar.feed;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
|
import org.briarproject.bramble.client.ClientModule;
|
||||||
|
import org.briarproject.bramble.contact.ContactModule;
|
||||||
|
import org.briarproject.bramble.crypto.CryptoModule;
|
||||||
|
import org.briarproject.bramble.data.DataModule;
|
||||||
|
import org.briarproject.bramble.db.DatabaseModule;
|
||||||
|
import org.briarproject.bramble.event.EventModule;
|
||||||
|
import org.briarproject.bramble.identity.IdentityModule;
|
||||||
|
import org.briarproject.bramble.lifecycle.LifecycleModule;
|
||||||
|
import org.briarproject.bramble.sync.SyncModule;
|
||||||
|
import org.briarproject.bramble.system.SystemModule;
|
||||||
|
import org.briarproject.bramble.test.TestDatabaseModule;
|
||||||
|
import org.briarproject.bramble.test.TestPluginConfigModule;
|
||||||
|
import org.briarproject.bramble.test.TestSeedProviderModule;
|
||||||
|
import org.briarproject.bramble.test.TestSocksModule;
|
||||||
|
import org.briarproject.bramble.transport.TransportModule;
|
||||||
|
import org.briarproject.briar.api.blog.BlogManager;
|
||||||
|
import org.briarproject.briar.api.feed.FeedManager;
|
||||||
|
import org.briarproject.briar.blog.BlogModule;
|
||||||
|
import org.briarproject.briar.client.BriarClientModule;
|
||||||
|
import org.briarproject.briar.test.TestDnsModule;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import dagger.Component;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Component(modules = {
|
||||||
|
TestDatabaseModule.class,
|
||||||
|
TestPluginConfigModule.class,
|
||||||
|
TestSeedProviderModule.class,
|
||||||
|
TestSocksModule.class,
|
||||||
|
TestDnsModule.class,
|
||||||
|
LifecycleModule.class,
|
||||||
|
BriarClientModule.class,
|
||||||
|
ClientModule.class,
|
||||||
|
ContactModule.class,
|
||||||
|
CryptoModule.class,
|
||||||
|
BlogModule.class,
|
||||||
|
FeedModule.class,
|
||||||
|
DataModule.class,
|
||||||
|
DatabaseModule.class,
|
||||||
|
EventModule.class,
|
||||||
|
IdentityModule.class,
|
||||||
|
SyncModule.class,
|
||||||
|
SystemModule.class,
|
||||||
|
TransportModule.class
|
||||||
|
})
|
||||||
|
interface FeedManagerIntegrationTestComponent {
|
||||||
|
|
||||||
|
void inject(FeedManagerIntegrationTest testCase);
|
||||||
|
|
||||||
|
void inject(FeedModule.EagerSingletons init);
|
||||||
|
|
||||||
|
void inject(BlogModule.EagerSingletons init);
|
||||||
|
|
||||||
|
void inject(ContactModule.EagerSingletons init);
|
||||||
|
|
||||||
|
void inject(CryptoModule.EagerSingletons init);
|
||||||
|
|
||||||
|
void inject(IdentityModule.EagerSingletons init);
|
||||||
|
|
||||||
|
void inject(LifecycleModule.EagerSingletons init);
|
||||||
|
|
||||||
|
void inject(SyncModule.EagerSingletons init);
|
||||||
|
|
||||||
|
void inject(SystemModule.EagerSingletons init);
|
||||||
|
|
||||||
|
void inject(TransportModule.EagerSingletons init);
|
||||||
|
|
||||||
|
LifecycleManager getLifecycleManager();
|
||||||
|
|
||||||
|
FeedManager getFeedManager();
|
||||||
|
|
||||||
|
BlogManager getBlogManager();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -23,8 +23,8 @@ public class BlogSharingValidatorTest extends SharingValidatorTest {
|
|||||||
private final byte[] publicKey =
|
private final byte[] publicKey =
|
||||||
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
|
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
|
||||||
private final Author author = new Author(authorId, authorName, publicKey);
|
private final Author author = new Author(authorId, authorName, publicKey);
|
||||||
private final Blog blog = new Blog(group, author);
|
private final Blog blog = new Blog(group, author, false);
|
||||||
private final BdfList descriptor = BdfList.of(authorName, publicKey);
|
private final BdfList descriptor = BdfList.of(authorName, publicKey, false);
|
||||||
private final String content =
|
private final String content =
|
||||||
TestUtils.getRandomString(MAX_INVITATION_MESSAGE_LENGTH);
|
TestUtils.getRandomString(MAX_INVITATION_MESSAGE_LENGTH);
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ public class BlogSharingValidatorTest extends SharingValidatorTest {
|
|||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testRejectsNullBlogName() throws Exception {
|
public void testRejectsNullBlogName() throws Exception {
|
||||||
BdfList invalidDescriptor = BdfList.of(null, publicKey);
|
BdfList invalidDescriptor = BdfList.of(null, publicKey, false);
|
||||||
v.validateMessage(message, group,
|
v.validateMessage(message, group,
|
||||||
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
|
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
|
||||||
null));
|
null));
|
||||||
@@ -72,7 +72,7 @@ public class BlogSharingValidatorTest extends SharingValidatorTest {
|
|||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testRejectsNonStringBlogName() throws Exception {
|
public void testRejectsNonStringBlogName() throws Exception {
|
||||||
BdfList invalidDescriptor = BdfList.of(123, publicKey);
|
BdfList invalidDescriptor = BdfList.of(123, publicKey, false);
|
||||||
v.validateMessage(message, group,
|
v.validateMessage(message, group,
|
||||||
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
|
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
|
||||||
null));
|
null));
|
||||||
@@ -80,7 +80,7 @@ public class BlogSharingValidatorTest extends SharingValidatorTest {
|
|||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testRejectsTooShortBlogName() throws Exception {
|
public void testRejectsTooShortBlogName() throws Exception {
|
||||||
BdfList invalidDescriptor = BdfList.of("", publicKey);
|
BdfList invalidDescriptor = BdfList.of("", publicKey, false);
|
||||||
v.validateMessage(message, group,
|
v.validateMessage(message, group,
|
||||||
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
|
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
|
||||||
null));
|
null));
|
||||||
@@ -89,7 +89,7 @@ public class BlogSharingValidatorTest extends SharingValidatorTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testAcceptsMinLengthBlogName() throws Exception {
|
public void testAcceptsMinLengthBlogName() throws Exception {
|
||||||
String shortBlogName = TestUtils.getRandomString(1);
|
String shortBlogName = TestUtils.getRandomString(1);
|
||||||
BdfList validDescriptor = BdfList.of(shortBlogName, publicKey);
|
BdfList validDescriptor = BdfList.of(shortBlogName, publicKey, false);
|
||||||
expectCreateBlog(shortBlogName, publicKey);
|
expectCreateBlog(shortBlogName, publicKey);
|
||||||
expectEncodeMetadata(INVITE);
|
expectEncodeMetadata(INVITE);
|
||||||
BdfMessageContext messageContext = v.validateMessage(message, group,
|
BdfMessageContext messageContext = v.validateMessage(message, group,
|
||||||
@@ -102,7 +102,8 @@ public class BlogSharingValidatorTest extends SharingValidatorTest {
|
|||||||
public void testRejectsTooLongBlogName() throws Exception {
|
public void testRejectsTooLongBlogName() throws Exception {
|
||||||
String invalidBlogName =
|
String invalidBlogName =
|
||||||
TestUtils.getRandomString(MAX_BLOG_NAME_LENGTH + 1);
|
TestUtils.getRandomString(MAX_BLOG_NAME_LENGTH + 1);
|
||||||
BdfList invalidDescriptor = BdfList.of(invalidBlogName, publicKey);
|
BdfList invalidDescriptor =
|
||||||
|
BdfList.of(invalidBlogName, publicKey, false);
|
||||||
v.validateMessage(message, group,
|
v.validateMessage(message, group,
|
||||||
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
|
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
|
||||||
null));
|
null));
|
||||||
@@ -110,7 +111,7 @@ public class BlogSharingValidatorTest extends SharingValidatorTest {
|
|||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testRejectsNullPublicKey() throws Exception {
|
public void testRejectsNullPublicKey() throws Exception {
|
||||||
BdfList invalidDescriptor = BdfList.of(authorName, null);
|
BdfList invalidDescriptor = BdfList.of(authorName, null, false);
|
||||||
v.validateMessage(message, group,
|
v.validateMessage(message, group,
|
||||||
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
|
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
|
||||||
null));
|
null));
|
||||||
@@ -118,7 +119,7 @@ public class BlogSharingValidatorTest extends SharingValidatorTest {
|
|||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testRejectsNonRawPublicKey() throws Exception {
|
public void testRejectsNonRawPublicKey() throws Exception {
|
||||||
BdfList invalidDescriptor = BdfList.of(authorName, 123);
|
BdfList invalidDescriptor = BdfList.of(authorName, 123, false);
|
||||||
v.validateMessage(message, group,
|
v.validateMessage(message, group,
|
||||||
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
|
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
|
||||||
null));
|
null));
|
||||||
@@ -127,7 +128,7 @@ public class BlogSharingValidatorTest extends SharingValidatorTest {
|
|||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testRejectsTooLongPublicKey() throws Exception {
|
public void testRejectsTooLongPublicKey() throws Exception {
|
||||||
byte[] invalidKey = TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH + 1);
|
byte[] invalidKey = TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH + 1);
|
||||||
BdfList invalidDescriptor = BdfList.of(authorName, invalidKey);
|
BdfList invalidDescriptor = BdfList.of(authorName, invalidKey, false);
|
||||||
v.validateMessage(message, group,
|
v.validateMessage(message, group,
|
||||||
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
|
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
|
||||||
null));
|
null));
|
||||||
@@ -136,7 +137,7 @@ public class BlogSharingValidatorTest extends SharingValidatorTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testAcceptsMinLengthPublicKey() throws Exception {
|
public void testAcceptsMinLengthPublicKey() throws Exception {
|
||||||
byte[] key = TestUtils.getRandomBytes(1);
|
byte[] key = TestUtils.getRandomBytes(1);
|
||||||
BdfList validDescriptor = BdfList.of(authorName, key);
|
BdfList validDescriptor = BdfList.of(authorName, key, false);
|
||||||
|
|
||||||
expectCreateBlog(authorName, key);
|
expectCreateBlog(authorName, key);
|
||||||
expectEncodeMetadata(INVITE);
|
expectEncodeMetadata(INVITE);
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package org.briarproject.briar.test;
|
||||||
|
|
||||||
|
import dagger.Module;
|
||||||
|
import dagger.Provides;
|
||||||
|
import okhttp3.Dns;
|
||||||
|
|
||||||
|
@Module
|
||||||
|
public class TestDnsModule {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
Dns provideDns() {
|
||||||
|
return Dns.SYSTEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user