From a9e7cbd05c2fbb57d56f5e2a5bb47f8a209867aa Mon Sep 17 00:00:00 2001
From: akwizgran <akwizgran@users.sourceforge.net>
Date: Tue, 19 Jul 2011 14:21:07 +0100
Subject: [PATCH] Every encoded object should include its identifying tag.

---
 .../net/sf/briar/protocol/BundleReaderImpl.java      |  1 -
 .../net/sf/briar/protocol/BundleWriterImpl.java      |  7 ++-----
 .../net/sf/briar/protocol/CopyingConsumer.java       |  3 ++-
 .../net/sf/briar/protocol/MessageEncoderImpl.java    |  2 ++
 .../net/sf/briar/protocol/MessageReaderImpl.java     |  6 ++++--
 test/net/sf/briar/protocol/ConsumersTest.java        | 12 ++++++++++++
 6 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/components/net/sf/briar/protocol/BundleReaderImpl.java b/components/net/sf/briar/protocol/BundleReaderImpl.java
index 2474a5e085..2c80d9b1b2 100644
--- a/components/net/sf/briar/protocol/BundleReaderImpl.java
+++ b/components/net/sf/briar/protocol/BundleReaderImpl.java
@@ -123,7 +123,6 @@ class BundleReaderImpl implements BundleReader {
 		List<Message> messages = new ArrayList<Message>();
 		reader.readListStart();
 		while(!reader.hasListEnd()) {
-			reader.readUserDefinedTag(Tags.MESSAGE);
 			messages.add(messageReader.readMessage(reader));
 		}
 		reader.readListEnd();
diff --git a/components/net/sf/briar/protocol/BundleWriterImpl.java b/components/net/sf/briar/protocol/BundleWriterImpl.java
index 5640faae10..6f4802e7a1 100644
--- a/components/net/sf/briar/protocol/BundleWriterImpl.java
+++ b/components/net/sf/briar/protocol/BundleWriterImpl.java
@@ -90,11 +90,8 @@ class BundleWriterImpl implements BundleWriter {
 		out.setSigning(true);
 		writer.writeUserDefinedTag(Tags.BATCH);
 		writer.writeListStart();
-		for(Raw message : messages) {
-			writer.writeUserDefinedTag(Tags.MESSAGE);
-			// Bypass the writer and write the raw message directly
-			out.write(message.getBytes());
-		}
+		// Bypass the writer and write the raw messages directly
+		for(Raw message : messages) out.write(message.getBytes());
 		writer.writeListEnd();
 		out.setSigning(false);
 		// Create and write the signature
diff --git a/components/net/sf/briar/protocol/CopyingConsumer.java b/components/net/sf/briar/protocol/CopyingConsumer.java
index f84f5a746b..6e84d5929a 100644
--- a/components/net/sf/briar/protocol/CopyingConsumer.java
+++ b/components/net/sf/briar/protocol/CopyingConsumer.java
@@ -5,7 +5,8 @@ import java.io.IOException;
 
 import net.sf.briar.api.serial.Consumer;
 
-public class CopyingConsumer implements Consumer {
+/** A consumer that makes a copy of the bytes consumed. */
+class CopyingConsumer implements Consumer {
 
 	private final ByteArrayOutputStream out = new ByteArrayOutputStream();
 
diff --git a/components/net/sf/briar/protocol/MessageEncoderImpl.java b/components/net/sf/briar/protocol/MessageEncoderImpl.java
index 58d52b1be4..f59ba57eee 100644
--- a/components/net/sf/briar/protocol/MessageEncoderImpl.java
+++ b/components/net/sf/briar/protocol/MessageEncoderImpl.java
@@ -36,6 +36,7 @@ class MessageEncoderImpl implements MessageEncoder {
 		byte[] encodedKey = keyPair.getPublic().getEncoded();
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
 		Writer w = writerFactory.createWriter(out);
+		w.writeUserDefinedTag(Tags.MESSAGE);
 		parent.writeTo(w);
 		group.writeTo(w);
 		w.writeUserDefinedTag(Tags.TIMESTAMP);
@@ -60,6 +61,7 @@ class MessageEncoderImpl implements MessageEncoder {
 		// The author ID is the hash of the author's nick and public key
 		out.reset();
 		w = writerFactory.createWriter(out);
+		w.writeUserDefinedTag(Tags.AUTHOR);
 		w.writeString(nick);
 		w.writeRaw(encodedKey);
 		w.close();
diff --git a/components/net/sf/briar/protocol/MessageReaderImpl.java b/components/net/sf/briar/protocol/MessageReaderImpl.java
index cbc4a19e8e..f865fc021a 100644
--- a/components/net/sf/briar/protocol/MessageReaderImpl.java
+++ b/components/net/sf/briar/protocol/MessageReaderImpl.java
@@ -39,7 +39,9 @@ class MessageReaderImpl implements MessageReader {
 		messageDigest.reset();
 		reader.addConsumer(copying);
 		reader.addConsumer(counting);
-		// Read the parent message ID
+		// Read the initial tag
+		reader.readUserDefinedTag(Tags.MESSAGE);
+		// Read the parent's message ID
 		reader.readUserDefinedTag(Tags.MESSAGE_ID);
 		byte[] b = reader.readRaw();
 		if(b.length != UniqueId.LENGTH) throw new FormatException();
@@ -54,8 +56,8 @@ class MessageReaderImpl implements MessageReader {
 		long timestamp = reader.readInt64();
 		if(timestamp < 0L) throw new FormatException();
 		// Hash the author's nick and public key to get the author ID
-		reader.readUserDefinedTag(Tags.AUTHOR);
 		reader.addConsumer(digesting);
+		reader.readUserDefinedTag(Tags.AUTHOR);
 		reader.readString();
 		byte[] encodedKey = reader.readRaw();
 		reader.removeConsumer(digesting);
diff --git a/test/net/sf/briar/protocol/ConsumersTest.java b/test/net/sf/briar/protocol/ConsumersTest.java
index 38c49599c1..fdfba1c5fa 100644
--- a/test/net/sf/briar/protocol/ConsumersTest.java
+++ b/test/net/sf/briar/protocol/ConsumersTest.java
@@ -70,4 +70,16 @@ public class ConsumersTest extends TestCase {
 			assertTrue(false);
 		} catch(FormatException expected) {}
 	}
+
+	@Test
+	public void testCopyingConsumer() throws Exception {
+		byte[] data = new byte[1234];
+		new Random().nextBytes(data);
+		// Check that a CopyingConsumer creates a faithful copy
+		CopyingConsumer cc = new CopyingConsumer();
+		cc.write(data[0]);
+		cc.write(data, 1, data.length - 2);
+		cc.write(data[data.length - 1]);
+		assertTrue(Arrays.equals(data, cc.getCopy()));
+	}
 }
-- 
GitLab