diff --git a/src/org/fdroid/fdroid/ManageRepo.java b/src/org/fdroid/fdroid/ManageRepo.java index 733f0e063..64b025597 100644 --- a/src/org/fdroid/fdroid/ManageRepo.java +++ b/src/org/fdroid/fdroid/ManageRepo.java @@ -27,11 +27,11 @@ import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Bundle; import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentManager; import android.support.v4.app.NavUtils; import android.text.TextUtils; import android.util.Log; import android.view.MenuItem; - import android.widget.LinearLayout; import android.widget.Toast; @@ -57,8 +57,8 @@ public class ManageRepo extends FragmentActivity { ((FDroidApp) getApplication()).applyTheme(this); - if (savedInstanceState == null) { - + FragmentManager fm = getSupportFragmentManager(); + if (fm.findFragmentById(android.R.id.content) == null) { // Need to set a dummy view (which will get overridden by the fragment manager // below) so that we can call setContentView(). This is a work around for // a (bug?) thing in 3.0, 3.1 which requires setContentView to be invoked before @@ -67,10 +67,9 @@ public class ManageRepo extends FragmentActivity { setContentView( new LinearLayout(this) ); listFragment = new RepoListFragment(); - getSupportFragmentManager() - .beginTransaction() - .add(android.R.id.content, listFragment) - .commit(); + fm.beginTransaction() + .add(android.R.id.content, listFragment) + .commit(); } ActionBarCompat.create(this).setDisplayHomeAsUpEnabled(true); diff --git a/src/org/fdroid/fdroid/UpdateService.java b/src/org/fdroid/fdroid/UpdateService.java index 6817936f8..471b120f2 100644 --- a/src/org/fdroid/fdroid/UpdateService.java +++ b/src/org/fdroid/fdroid/UpdateService.java @@ -120,7 +120,13 @@ public class UpdateService extends IntentService implements ProgressListener { } if (finished && dialog.isShowing()) - dialog.dismiss(); + try { + dialog.dismiss(); + } catch (IllegalArgumentException e) { + // sometimes dialog.isShowing() doesn't work :( + // https://stackoverflow.com/questions/19538282/view-not-attached-to-window-manager-dialog-dismiss + e.printStackTrace(); + } } } diff --git a/src/org/fdroid/fdroid/updater/SignedRepoUpdater.java b/src/org/fdroid/fdroid/updater/SignedRepoUpdater.java index f7ac7e805..57fdeb373 100644 --- a/src/org/fdroid/fdroid/updater/SignedRepoUpdater.java +++ b/src/org/fdroid/fdroid/updater/SignedRepoUpdater.java @@ -52,6 +52,13 @@ public class SignedRepoUpdater extends RepoUpdater { InputStream input = null; OutputStream output = null; try { + /* + * JarFile.getInputStream() provides the signature check, even + * though the Android docs do not mention this, the Java docs do + * and Android seems to implement it the same: + * http://docs.oracle.com/javase/6/docs/api/java/util/jar/JarFile.html#getInputStream(java.util.zip.ZipEntry) + * https://developer.android.com/reference/java/util/jar/JarFile.html#getInputStream(java.util.zip.ZipEntry) + */ input = jarFile.getInputStream(indexEntry); output = new FileOutputStream(indexFile); Utils.copy(input, output); diff --git a/test/assets/simpleIndex.jar b/test/assets/simpleIndex.jar new file mode 100644 index 000000000..1c173ceb3 Binary files /dev/null and b/test/assets/simpleIndex.jar differ diff --git a/test/assets/simpleIndex.xml b/test/assets/simpleIndex.xml new file mode 100644 index 000000000..a806ef68a --- /dev/null +++ b/test/assets/simpleIndex.xml @@ -0,0 +1,6 @@ + +The official repository of the F-Droid client. Applications in this repository +are either official binaries built by the original application developers, or +are binaries built from source by the admin of f-droid.org using the tools on +https://gitorious.org/f-droid. + \ No newline at end of file diff --git a/test/assets/simpleIndexWithCorruptedCertificate.jar b/test/assets/simpleIndexWithCorruptedCertificate.jar new file mode 100644 index 000000000..ba16c3306 Binary files /dev/null and b/test/assets/simpleIndexWithCorruptedCertificate.jar differ diff --git a/test/assets/simpleIndexWithCorruptedEverything.jar b/test/assets/simpleIndexWithCorruptedEverything.jar new file mode 100644 index 000000000..cca7b96bc Binary files /dev/null and b/test/assets/simpleIndexWithCorruptedEverything.jar differ diff --git a/test/assets/simpleIndexWithCorruptedManifest.jar b/test/assets/simpleIndexWithCorruptedManifest.jar new file mode 100644 index 000000000..d8b7b70b7 Binary files /dev/null and b/test/assets/simpleIndexWithCorruptedManifest.jar differ diff --git a/test/assets/simpleIndexWithCorruptedSignature.jar b/test/assets/simpleIndexWithCorruptedSignature.jar new file mode 100644 index 000000000..b198ab60f Binary files /dev/null and b/test/assets/simpleIndexWithCorruptedSignature.jar differ diff --git a/test/assets/simpleIndexWithoutSignature.jar b/test/assets/simpleIndexWithoutSignature.jar new file mode 100644 index 000000000..4d22353a5 Binary files /dev/null and b/test/assets/simpleIndexWithoutSignature.jar differ diff --git a/test/libs/commons-io-2.2.jar b/test/libs/commons-io-2.2.jar new file mode 100644 index 000000000..84ca56585 Binary files /dev/null and b/test/libs/commons-io-2.2.jar differ diff --git a/test/libs/commons-io-2.2.jar.README b/test/libs/commons-io-2.2.jar.README new file mode 100644 index 000000000..a330a9794 --- /dev/null +++ b/test/libs/commons-io-2.2.jar.README @@ -0,0 +1,5 @@ + +Downloaded from: +https://archive.apache.org/dist/commons/io/binaries/commons-io-2.2-bin.zip +https://archive.apache.org/dist/commons/io/binaries/commons-io-2.2-bin.zip.asc +https://archive.apache.org/dist/commons/io/binaries/commons-io-2.2-bin.zip.sha1 diff --git a/test/src/org/fdroid/fdroid/updater/SignedRepoUpdaterTest.java b/test/src/org/fdroid/fdroid/updater/SignedRepoUpdaterTest.java new file mode 100644 index 000000000..3f198a6e4 --- /dev/null +++ b/test/src/org/fdroid/fdroid/updater/SignedRepoUpdaterTest.java @@ -0,0 +1,142 @@ + +package org.fdroid.fdroid.updater; + +import android.content.Context; +import android.test.InstrumentationTestCase; + +import org.apache.commons.io.FileUtils; +import org.fdroid.fdroid.Utils; +import org.fdroid.fdroid.data.Repo; +import org.fdroid.fdroid.updater.RepoUpdater.UpdateException; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public class SignedRepoUpdaterTest extends InstrumentationTestCase { + + private Context context; + private RepoUpdater repoUpdater; + + String simpleIndexPubkey = "308201ee30820157a0030201020204300d845b300d06092a864886f70d01010b0500302a3110300e060355040b1307462d44726f6964311630140603550403130d70616c6174736368696e6b656e301e170d3134303432373030303633315a170d3431303931323030303633315a302a3110300e060355040b1307462d44726f6964311630140603550403130d70616c6174736368696e6b656e30819f300d06092a864886f70d010101050003818d0030818902818100a439472e4b6d01141bfc94ecfe131c7c728fdda670bb14c57ca60bd1c38a8b8bc0879d22a0a2d0bc0d6fdd4cb98d1d607c2caefbe250a0bd0322aedeb365caf9b236992fac13e6675d3184a6c7c6f07f73410209e399a9da8d5d7512bbd870508eebacff8b57c3852457419434d34701ccbf692267cbc3f42f1c5d1e23762d790203010001a321301f301d0603551d0e041604140b1840691dab909746fde4bfe28207d1cae15786300d06092a864886f70d01010b05000381810062424c928ffd1b6fd419b44daafef01ca982e09341f7077fb865905087aeac882534b3bd679b51fdfb98892cef38b63131c567ed26c9d5d9163afc775ac98ad88c405d211d6187bde0b0d236381cc574ba06ef9080721a92ae5a103a7301b2c397eecc141cc850dd3e123813ebc41c59d31ddbcb6e984168280c53272f6a442b"; + + @Override + protected void setUp() { + context = getInstrumentation().getContext(); + Repo repo = new Repo(); + repo.pubkey = this.simpleIndexPubkey; + repoUpdater = RepoUpdater.createUpdaterFor(context, repo); + } + + private InputStream getInputStreamFromAssets(String fileName) { + try { + return context.getResources().getAssets().open(fileName); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + private File getTestFile(String fileName) { + File indexFile; + InputStream input = null; + OutputStream output = null; + try { + indexFile = File.createTempFile("index-", ".xml", context.getFilesDir()); + input = getInputStreamFromAssets(fileName); + output = new FileOutputStream(indexFile); + Utils.copy(input, output); + } catch (IOException e) { + e.printStackTrace(); + return null; + } finally { + Utils.closeQuietly(output); + Utils.closeQuietly(input); + } + return indexFile; + } + + public void testExtractIndexFromJar() { + File simpleIndexXml = getTestFile("simpleIndex.xml"); + File simpleIndexJar = getTestFile("simpleIndex.jar"); + File testFile = null; + + // these are supposed to succeed + try { + testFile = repoUpdater.getIndexFromFile(simpleIndexJar); + assertTrue(testFile.length() == simpleIndexXml.length()); + assertEquals(FileUtils.readFileToString(testFile), + FileUtils.readFileToString(simpleIndexXml)); + } catch (IOException e) { + e.printStackTrace(); + fail(); + } catch (UpdateException e) { + e.printStackTrace(); + fail(); + } + } + + public void testExtractIndexFromJarWithoutSignatureJar() { + // this is supposed to fail + try { + repoUpdater.getIndexFromFile(getTestFile("simpleIndexWithoutSignature.jar")); + fail(); + } catch (UpdateException e) { + // success! + } + } + + public void testExtractIndexFromJarWithCorruptedManifestJar() { + // this is supposed to fail + try { + repoUpdater.getIndexFromFile(getTestFile("simpleIndexWithCorruptedManifest.jar")); + fail(); + } catch (UpdateException e) { + e.printStackTrace(); + fail(); + } catch (SecurityException e) { + // success! + } + } + + public void testExtractIndexFromJarWithCorruptedSignature() { + // this is supposed to fail + try { + repoUpdater.getIndexFromFile(getTestFile("simpleIndexWithCorruptedSignature.jar")); + fail(); + } catch (UpdateException e) { + e.printStackTrace(); + fail(); + } catch (SecurityException e) { + // success! + } + } + + public void testExtractIndexFromJarWithCorruptedCertificate() { + // this is supposed to fail + try { + repoUpdater.getIndexFromFile(getTestFile("simpleIndexWithCorruptedCertificate.jar")); + fail(); + } catch (UpdateException e) { + e.printStackTrace(); + fail(); + } catch (SecurityException e) { + // success! + } + } + + public void testExtractIndexFromJarWithCorruptedEverything() { + // this is supposed to fail + try { + repoUpdater.getIndexFromFile(getTestFile("simpleIndexWithCorruptedEverything.jar")); + fail(); + } catch (UpdateException e) { + e.printStackTrace(); + fail(); + } catch (SecurityException e) { + // success! + } + } +}