From 3008bcc209638809ee2c4949d5776463e00eb11f Mon Sep 17 00:00:00 2001 From: akwizgran <akwizgran@users.sourceforge.net> Date: Tue, 1 Apr 2014 19:35:56 +0100 Subject: [PATCH] Sort forum messages correctly even if clocks are wrong. Bug #57. --- .../android/contact/ConversationActivity.java | 19 +++++++++++++------ .../contact/ReadPrivateMessageActivity.java | 6 ++++-- .../contact/WritePrivateMessageActivity.java | 13 +++++++------ .../android/groups/GroupActivity.java | 13 +++++++++++++ .../android/groups/ReadGroupPostActivity.java | 6 ++++-- .../groups/WriteGroupPostActivity.java | 15 ++++++++------- 6 files changed, 49 insertions(+), 23 deletions(-) diff --git a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java index ccca7563e6..7cde33e7db 100644 --- a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java +++ b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java @@ -387,13 +387,8 @@ implements EventListener, OnClickListener, OnItemClickListener { public void onClick(View view) { String message = content.getText().toString(); if(message.equals("")) return; - // Don't use an earlier timestamp than the newest message long timestamp = System.currentTimeMillis(); - int count = adapter.getCount(); - for(int i = 0; i < count; i++) { - long time = adapter.getItem(i).getHeader().getTimestamp() + 1; - if(time > timestamp) timestamp = time; - } + timestamp = Math.max(timestamp, getMinTimestampForNewMessage()); createMessage(StringUtils.toUtf8(message), timestamp); Toast.makeText(this, R.string.message_sent_toast, LENGTH_SHORT).show(); content.setText(""); @@ -402,6 +397,17 @@ implements EventListener, OnClickListener, OnItemClickListener { ((InputMethodManager) o).toggleSoftInput(HIDE_IMPLICIT_ONLY, 0); } + private long getMinTimestampForNewMessage() { + // Don't use an earlier timestamp than the newest message + long timestamp = 0; + int count = adapter.getCount(); + for(int i = 0; i < count; i++) { + long t = adapter.getItem(i).getHeader().getTimestamp(); + if(t > timestamp) timestamp = t; + } + return timestamp + 1; + } + private void createMessage(final byte[] body, final long timestamp) { cryptoExecutor.execute(new Runnable() { public void run() { @@ -452,6 +458,7 @@ implements EventListener, OnClickListener, OnItemClickListener { i.putExtra("briar.MESSAGE_ID", header.getId().getBytes()); i.putExtra("briar.CONTENT_TYPE", header.getContentType()); i.putExtra("briar.TIMESTAMP", header.getTimestamp()); + i.putExtra("briar.MIN_TIMESTAMP", getMinTimestampForNewMessage()); i.putExtra("briar.POSITION", position); startActivityForResult(i, REQUEST_READ); } diff --git a/briar-android/src/org/briarproject/android/contact/ReadPrivateMessageActivity.java b/briar-android/src/org/briarproject/android/contact/ReadPrivateMessageActivity.java index 19eeba26e4..2dfafbef4e 100644 --- a/briar-android/src/org/briarproject/android/contact/ReadPrivateMessageActivity.java +++ b/briar-android/src/org/briarproject/android/contact/ReadPrivateMessageActivity.java @@ -51,6 +51,7 @@ implements OnClickListener { private String contactName = null; private AuthorId localAuthorId = null; + private long timestamp = -1, minTimestamp = -1; private ImageButton prevButton = null, nextButton = null; private ImageButton replyButton = null; private TextView content = null; @@ -60,7 +61,6 @@ implements OnClickListener { @Inject private volatile DatabaseComponent db; private volatile MessageId messageId = null; private volatile GroupId groupId = null; - private volatile long timestamp = -1; @Override public void onCreate(Bundle state) { @@ -85,6 +85,8 @@ implements OnClickListener { if(contentType == null) throw new IllegalStateException(); timestamp = i.getLongExtra("briar.TIMESTAMP", -1); if(timestamp == -1) throw new IllegalStateException(); + minTimestamp = i.getLongExtra("briar.MIN_TIMESTAMP", -1); + if(minTimestamp == -1) throw new IllegalStateException(); position = i.getIntExtra("briar.POSITION", -1); if(position == -1) throw new IllegalStateException(); @@ -228,7 +230,7 @@ implements OnClickListener { i.putExtra("briar.LOCAL_AUTHOR_ID", localAuthorId.getBytes()); i.putExtra("briar.PARENT_ID", messageId.getBytes()); - i.putExtra("briar.TIMESTAMP", timestamp); + i.putExtra("briar.MIN_TIMESTAMP", minTimestamp); startActivity(i); setResult(RESULT_REPLY); finish(); diff --git a/briar-android/src/org/briarproject/android/contact/WritePrivateMessageActivity.java b/briar-android/src/org/briarproject/android/contact/WritePrivateMessageActivity.java index 9abb58bda8..3c2d6ed33c 100644 --- a/briar-android/src/org/briarproject/android/contact/WritePrivateMessageActivity.java +++ b/briar-android/src/org/briarproject/android/contact/WritePrivateMessageActivity.java @@ -69,7 +69,7 @@ implements OnClickListener { private volatile GroupId groupId = null; private volatile AuthorId localAuthorId = null; private volatile MessageId parentId = null; - private volatile long timestamp = -1; + private volatile long minTimestamp = -1; private volatile LocalAuthor localAuthor = null; private volatile Group group = null; @@ -86,10 +86,11 @@ implements OnClickListener { groupId = new GroupId(b); b = i.getByteArrayExtra("briar.LOCAL_AUTHOR_ID"); if(b == null) throw new IllegalStateException(); + minTimestamp = i.getLongExtra("briar.MIN_TIMESTAMP", -1); + if(minTimestamp == -1) throw new IllegalStateException(); localAuthorId = new AuthorId(b); b = i.getByteArrayExtra("briar.PARENT_ID"); if(b != null) parentId = new MessageId(b); - timestamp = i.getLongExtra("briar.TIMESTAMP", -1); LinearLayout layout = new LinearLayout(this); layout.setLayoutParams(MATCH_WRAP); @@ -187,12 +188,12 @@ implements OnClickListener { private void createMessage(final byte[] body) { cryptoExecutor.execute(new Runnable() { public void run() { - // Don't use an earlier timestamp than the parent - long time = System.currentTimeMillis(); - time = Math.max(time, timestamp + 1); + // Don't use an earlier timestamp than the newest message + long timestamp = System.currentTimeMillis(); + timestamp = Math.max(timestamp, minTimestamp); try { Message m = messageFactory.createAnonymousMessage(parentId, - group, "text/plain", time, body); + group, "text/plain", timestamp, body); storeMessage(m); } catch(GeneralSecurityException e) { throw new RuntimeException(e); diff --git a/briar-android/src/org/briarproject/android/groups/GroupActivity.java b/briar-android/src/org/briarproject/android/groups/GroupActivity.java index 89b5199689..b82e5e4dbb 100644 --- a/briar-android/src/org/briarproject/android/groups/GroupActivity.java +++ b/briar-android/src/org/briarproject/android/groups/GroupActivity.java @@ -318,9 +318,21 @@ OnClickListener, OnItemClickListener { Intent i = new Intent(this, WriteGroupPostActivity.class); i.putExtra("briar.GROUP_ID", groupId.getBytes()); i.putExtra("briar.GROUP_NAME", groupName); + i.putExtra("briar.MIN_TIMESTAMP", getMinTimestampForNewMessage()); startActivity(i); } + private long getMinTimestampForNewMessage() { + // Don't use an earlier timestamp than the newest message + long timestamp = 0; + int count = adapter.getCount(); + for(int i = 0; i < count; i++) { + long t = adapter.getItem(i).getHeader().getTimestamp(); + if(t > timestamp) timestamp = t; + } + return timestamp + 1; + } + public void onItemClick(AdapterView<?> parent, View view, int position, long id) { displayMessage(position); @@ -337,6 +349,7 @@ OnClickListener, OnItemClickListener { i.putExtra("briar.AUTHOR_STATUS", item.getAuthorStatus().name()); i.putExtra("briar.CONTENT_TYPE", item.getContentType()); i.putExtra("briar.TIMESTAMP", item.getTimestamp()); + i.putExtra("briar.MIN_TIMESTAMP", getMinTimestampForNewMessage()); i.putExtra("briar.POSITION", position); startActivityForResult(i, REQUEST_READ); } diff --git a/briar-android/src/org/briarproject/android/groups/ReadGroupPostActivity.java b/briar-android/src/org/briarproject/android/groups/ReadGroupPostActivity.java index 5ebfb1aa50..25a0a3d05d 100644 --- a/briar-android/src/org/briarproject/android/groups/ReadGroupPostActivity.java +++ b/briar-android/src/org/briarproject/android/groups/ReadGroupPostActivity.java @@ -50,6 +50,7 @@ implements OnClickListener { private GroupId groupId = null; private String groupName = null; + private long timestamp = -1, minTimestamp = -1; private ImageButton prevButton = null, nextButton = null; private ImageButton replyButton = null; private TextView content = null; @@ -58,7 +59,6 @@ implements OnClickListener { // Fields that are accessed from background threads must be volatile @Inject private volatile DatabaseComponent db; private volatile MessageId messageId = null; - private volatile long timestamp = -1; @Override public void onCreate(Bundle state) { @@ -78,6 +78,8 @@ implements OnClickListener { if(contentType == null) throw new IllegalStateException(); timestamp = i.getLongExtra("briar.TIMESTAMP", -1); if(timestamp == -1) throw new IllegalStateException(); + minTimestamp = i.getLongExtra("briar.MIN_TIMESTAMP", -1); + if(minTimestamp == -1) throw new IllegalStateException(); position = i.getIntExtra("briar.POSITION", -1); if(position == -1) throw new IllegalStateException(); String authorName = i.getStringExtra("briar.AUTHOR_NAME"); @@ -223,7 +225,7 @@ implements OnClickListener { i.putExtra("briar.GROUP_ID", groupId.getBytes()); i.putExtra("briar.GROUP_NAME", groupName); i.putExtra("briar.PARENT_ID", messageId.getBytes()); - i.putExtra("briar.TIMESTAMP", timestamp); + i.putExtra("briar.MIN_TIMESTAMP", minTimestamp); startActivity(i); setResult(RESULT_REPLY); finish(); diff --git a/briar-android/src/org/briarproject/android/groups/WriteGroupPostActivity.java b/briar-android/src/org/briarproject/android/groups/WriteGroupPostActivity.java index 76bc207bc9..27d8f92852 100644 --- a/briar-android/src/org/briarproject/android/groups/WriteGroupPostActivity.java +++ b/briar-android/src/org/briarproject/android/groups/WriteGroupPostActivity.java @@ -79,7 +79,7 @@ implements OnItemSelectedListener, OnClickListener { @Inject private volatile CryptoComponent crypto; @Inject private volatile MessageFactory messageFactory; private volatile MessageId parentId = null; - private volatile long timestamp = -1; + private volatile long minTimestamp = -1; private volatile LocalAuthor localAuthor = null; private volatile Group group = null; @@ -94,9 +94,10 @@ implements OnItemSelectedListener, OnClickListener { String groupName = i.getStringExtra("briar.GROUP_NAME"); if(groupName == null) throw new IllegalStateException(); setTitle(groupName); + minTimestamp = i.getLongExtra("briar.MIN_TIMESTAMP", -1); + if(minTimestamp == -1) throw new IllegalStateException(); b = i.getByteArrayExtra("briar.PARENT_ID"); if(b != null) parentId = new MessageId(b); - timestamp = i.getLongExtra("briar.TIMESTAMP", -1); if(state != null) { b = state.getByteArray("briar.LOCAL_AUTHOR_ID"); @@ -260,21 +261,21 @@ implements OnItemSelectedListener, OnClickListener { private void createMessage(final byte[] body) { cryptoExecutor.execute(new Runnable() { public void run() { - // Don't use an earlier timestamp than the parent - long time = System.currentTimeMillis(); - time = Math.max(time, timestamp + 1); + // Don't use an earlier timestamp than the newest post + long timestamp = System.currentTimeMillis(); + timestamp = Math.max(timestamp, minTimestamp); Message m; try { if(localAuthor == null) { m = messageFactory.createAnonymousMessage(parentId, - group, "text/plain", time, body); + group, "text/plain", timestamp, body); } else { KeyParser keyParser = crypto.getSignatureKeyParser(); byte[] b = localAuthor.getPrivateKey(); PrivateKey authorKey = keyParser.parsePrivateKey(b); m = messageFactory.createPseudonymousMessage(parentId, group, localAuthor, authorKey, "text/plain", - time, body); + timestamp, body); } } catch(GeneralSecurityException e) { throw new RuntimeException(e); -- GitLab