diff --git a/components/net/sf/briar/plugins/file/FilePlugin.java b/components/net/sf/briar/plugins/file/FilePlugin.java index 81c1a6a1284041efb5419b14fd156cb4fc5a4f73..56e3d5bb054caf5a434f73b0899f91271a61a2bb 100644 --- a/components/net/sf/briar/plugins/file/FilePlugin.java +++ b/components/net/sf/briar/plugins/file/FilePlugin.java @@ -28,7 +28,8 @@ abstract class FilePlugin implements BatchTransportPlugin { protected Map<ContactId, Map<String, String>> remoteProperties = null; protected Map<String, String> config = null; protected BatchTransportCallback callback = null; - private boolean started = false; + + private volatile boolean started = false; protected abstract File chooseOutputDirectory(); protected abstract void writerFinished(File f); @@ -117,6 +118,7 @@ abstract class FilePlugin implements BatchTransportPlugin { } protected void createReaderFromFile(File f) { + if(!started) throw new IllegalStateException(); if(!isPossibleConnectionFilename(f.getName())) return; if(f.length() < TransportConstants.MIN_CONNECTION_LENGTH) return; try { @@ -128,6 +130,11 @@ abstract class FilePlugin implements BatchTransportPlugin { if(read == -1) break; offset += read; } + if(offset < iv.length) { + // The file was truncated + in.close(); + return; + } ContactId c = recogniser.acceptConnection(iv); if(c == null) { // Nobody there diff --git a/components/net/sf/briar/plugins/file/RemovableDriveMonitor.java b/components/net/sf/briar/plugins/file/RemovableDriveMonitor.java index ce9aeeca1633018dd2922295e297712c6529a941..caa223fc7a7f5a8c4962c323950089894449ff28 100644 --- a/components/net/sf/briar/plugins/file/RemovableDriveMonitor.java +++ b/components/net/sf/briar/plugins/file/RemovableDriveMonitor.java @@ -11,6 +11,6 @@ interface RemovableDriveMonitor { interface Callback { - void driveInserted(File f); + void driveInserted(File root); } } diff --git a/test/net/sf/briar/plugins/file/RemovableDrivePluginTest.java b/test/net/sf/briar/plugins/file/RemovableDrivePluginTest.java index 54a49c30d69094a1f9148ce28d515becb20d8973..625a7de03354634a9ad391d59985d1eda119e3a3 100644 --- a/test/net/sf/briar/plugins/file/RemovableDrivePluginTest.java +++ b/test/net/sf/briar/plugins/file/RemovableDrivePluginTest.java @@ -1,6 +1,7 @@ package net.sf.briar.plugins.file; import java.io.File; +import java.io.FileOutputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Collections; @@ -10,7 +11,9 @@ import junit.framework.TestCase; import net.sf.briar.TestUtils; import net.sf.briar.api.ContactId; import net.sf.briar.api.transport.ConnectionRecogniser; +import net.sf.briar.api.transport.TransportConstants; import net.sf.briar.api.transport.batch.BatchTransportCallback; +import net.sf.briar.api.transport.batch.BatchTransportReader; import net.sf.briar.api.transport.batch.BatchTransportWriter; import net.sf.briar.plugins.file.RemovableDriveMonitor.Callback; @@ -39,6 +42,7 @@ public class RemovableDrivePluginTest extends TestCase { context.mock(RemovableDriveFinder.class); final RemovableDriveMonitor monitor = context.mock(RemovableDriveMonitor.class); + RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser, finder, monitor); @@ -292,6 +296,154 @@ public class RemovableDrivePluginTest extends TestCase { context.assertIsSatisfied(); } + @Test + public void testEmptyDriveIsIgnored() throws Exception { + Mockery context = new Mockery(); + final ConnectionRecogniser recogniser = + context.mock(ConnectionRecogniser.class); + final RemovableDriveFinder finder = + context.mock(RemovableDriveFinder.class); + final RemovableDriveMonitor monitor = + context.mock(RemovableDriveMonitor.class); + final BatchTransportCallback callback = + context.mock(BatchTransportCallback.class); + + context.checking(new Expectations() {{ + oneOf(monitor).start(with(any(Callback.class))); + }}); + + RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser, + finder, monitor); + plugin.start(null, null, null, callback); + + plugin.driveInserted(testDir); + + context.assertIsSatisfied(); + } + + @Test + public void testFilenames() { + Mockery context = new Mockery(); + final ConnectionRecogniser recogniser = + context.mock(ConnectionRecogniser.class); + final RemovableDriveFinder finder = + context.mock(RemovableDriveFinder.class); + final RemovableDriveMonitor monitor = + context.mock(RemovableDriveMonitor.class); + + RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser, + finder, monitor); + + assertFalse(plugin.isPossibleConnectionFilename("abcdefg.dat")); + assertFalse(plugin.isPossibleConnectionFilename("abcdefghi.dat")); + assertFalse(plugin.isPossibleConnectionFilename("abcdefgh_dat")); + assertFalse(plugin.isPossibleConnectionFilename("abcdefgh.rat")); + assertTrue(plugin.isPossibleConnectionFilename("abcdefgh.dat")); + assertTrue(plugin.isPossibleConnectionFilename("ABCDEFGH.DAT")); + + context.assertIsSatisfied(); + } + + @Test + public void testSmallFileIsIgnored() throws Exception { + Mockery context = new Mockery(); + final ConnectionRecogniser recogniser = + context.mock(ConnectionRecogniser.class); + final RemovableDriveFinder finder = + context.mock(RemovableDriveFinder.class); + final RemovableDriveMonitor monitor = + context.mock(RemovableDriveMonitor.class); + final BatchTransportCallback callback = + context.mock(BatchTransportCallback.class); + + context.checking(new Expectations() {{ + oneOf(monitor).start(with(any(Callback.class))); + }}); + + RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser, + finder, monitor); + plugin.start(null, null, null, callback); + + File f = new File(testDir, "abcdefgh.dat"); + OutputStream out = new FileOutputStream(f); + out.write(new byte[TransportConstants.MIN_CONNECTION_LENGTH - 1]); + out.flush(); + out.close(); + assertEquals(TransportConstants.MIN_CONNECTION_LENGTH - 1, f.length()); + plugin.driveInserted(testDir); + + context.assertIsSatisfied(); + } + + @Test + public void testIvIsChecked() throws Exception { + Mockery context = new Mockery(); + final ConnectionRecogniser recogniser = + context.mock(ConnectionRecogniser.class); + final RemovableDriveFinder finder = + context.mock(RemovableDriveFinder.class); + final RemovableDriveMonitor monitor = + context.mock(RemovableDriveMonitor.class); + final BatchTransportCallback callback = + context.mock(BatchTransportCallback.class); + + context.checking(new Expectations() {{ + oneOf(monitor).start(with(any(Callback.class))); + oneOf(recogniser).acceptConnection(with(any(byte[].class))); + will(returnValue(null)); + }}); + + RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser, + finder, monitor); + plugin.start(null, null, null, callback); + + File f = new File(testDir, "abcdefgh.dat"); + OutputStream out = new FileOutputStream(f); + out.write(new byte[TransportConstants.MIN_CONNECTION_LENGTH]); + out.flush(); + out.close(); + assertEquals(TransportConstants.MIN_CONNECTION_LENGTH, f.length()); + plugin.driveInserted(testDir); + + context.assertIsSatisfied(); + } + + @Test + public void testReaderIsCreated() throws Exception { + Mockery context = new Mockery(); + final ConnectionRecogniser recogniser = + context.mock(ConnectionRecogniser.class); + final RemovableDriveFinder finder = + context.mock(RemovableDriveFinder.class); + final RemovableDriveMonitor monitor = + context.mock(RemovableDriveMonitor.class); + final BatchTransportCallback callback = + context.mock(BatchTransportCallback.class); + + context.checking(new Expectations() {{ + oneOf(monitor).start(with(any(Callback.class))); + oneOf(recogniser).acceptConnection(with(any(byte[].class))); + will(returnValue(contactId)); + oneOf(callback).readerCreated(with(contactId), + with(any(byte[].class)), + with(any(BatchTransportReader.class))); + }}); + + RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser, + finder, monitor); + plugin.start(null, null, null, callback); + + File f = new File(testDir, "abcdefgh.dat"); + OutputStream out = new FileOutputStream(f); + out.write(new byte[TransportConstants.MIN_CONNECTION_LENGTH]); + out.flush(); + out.close(); + assertEquals(TransportConstants.MIN_CONNECTION_LENGTH, f.length()); + plugin.driveInserted(testDir); + + context.assertIsSatisfied(); + } + @After public void tearDown() { TestUtils.deleteTestDirectory(testDir);