diff --git a/app/app-release.apk b/app/app-release.apk index 8a01c3ef..3a2497e4 100644 Binary files a/app/app-release.apk and b/app/app-release.apk differ diff --git a/app/build.gradle b/app/build.gradle index 622aa1dc..74753bb2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -14,8 +14,8 @@ android { } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 } // avoid Travis failures @@ -33,9 +33,13 @@ dependencies { compile 'org.apache.commons:commons-io:1.3.2' compile 'com.jayway.android.robotium:robotium-solo:5.3.1' compile 'com.melnykov:floatingactionbutton:1.2.0' + compile group: 'com.google.guava', name: 'guava', version: '18.0' } tasks.findAll { // make all tasks whose name starts with 'assemble'... it.name.startsWith 'assemble' }.each { // ... depending on 'copyDependenciesIntoLibs' task from 'copyLibs.gradle' script plugin it.dependsOn copyDependenciesIntoLibs -} \ No newline at end of file +} + +apply plugin: 'com.android.application' //or apply plugin: 'java' +apply plugin: 'me.tatarka.retrolambda' \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 45dc58a5..1c62bd01 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -15,3 +15,4 @@ #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} +-dontwarn java.lang.invoke.* diff --git a/app/src/main/java/com/zeapo/pwdstore/UserPreference.java b/app/src/main/java/com/zeapo/pwdstore/UserPreference.java index 82c278df..0b7f3640 100644 --- a/app/src/main/java/com/zeapo/pwdstore/UserPreference.java +++ b/app/src/main/java/com/zeapo/pwdstore/UserPreference.java @@ -1,8 +1,8 @@ package com.zeapo.pwdstore; import android.app.AlertDialog; -import android.content.DialogInterface; import android.content.Intent; +import android.content.SharedPreferences; import android.net.Uri; import android.os.Bundle; import android.preference.Preference; @@ -12,6 +12,9 @@ import android.support.v7.app.AppCompatActivity; import android.view.MenuItem; import android.widget.Toast; +import com.google.common.base.Joiner; +import com.google.common.base.Strings; +import com.google.common.collect.Iterables; import com.zeapo.pwdstore.crypto.PgpHandler; import com.zeapo.pwdstore.git.GitActivity; import com.zeapo.pwdstore.utils.PasswordRepository; @@ -19,12 +22,14 @@ import com.zeapo.pwdstore.utils.PasswordRepository; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.openintents.openpgp.util.OpenPgpKeyPreference; +import org.openintents.openpgp.util.OpenPgpUtils; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.util.Arrays; -public class UserPreference extends AppCompatActivity implements Preference.OnPreferenceClickListener { +public class UserPreference extends AppCompatActivity { private final static int IMPORT_SSH_KEY = 1; private final static int IMPORT_PGP_KEY = 2; private final static int EDIT_GIT_INFO = 3; @@ -34,26 +39,75 @@ public class UserPreference extends AppCompatActivity implements Preference.OnPr @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - // Load the preferences from an XML resource + final UserPreference callingActivity = (UserPreference) getActivity(); + final SharedPreferences sharedPreferences = getPreferenceManager().getSharedPreferences(); + addPreferencesFromResource(R.xml.preference); -// Preference keyPref = findPreference("openpgp_key_id"); -// keyPref.setSummary(getPreferenceManager().getSharedPreferences().getString("openpgp_key_ids", "No key selected")); -// keyPref.setOnPreferenceClickListener((UserPreference) getActivity()); - findPreference("ssh_key").setOnPreferenceClickListener((UserPreference) getActivity()); - findPreference("git_server_info").setOnPreferenceClickListener((UserPreference) getActivity()); - findPreference("git_delete_repo").setOnPreferenceClickListener((UserPreference) getActivity()); -// ((UserPreference) getActivity()).mKey = (OpenPgpKeyPreference) findPreference("openpgp_key"); -// if (getPreferenceManager().getSharedPreferences().getString("openpgp_provider_list", null) != null) -// ((UserPreference) getActivity()).mKey.setOpenPgpProvider(getPreferenceManager().getSharedPreferences().getString("openpgp_provider_list", "")); + Preference keyPref = findPreference("openpgp_key_id_pref"); + String selectedKeys = sharedPreferences.getString("openpgp_key_ids", ""); + if (Strings.isNullOrEmpty(selectedKeys)) { + keyPref.setSummary("No key selected"); + } else { + keyPref.setSummary( + Joiner.on(',') + .join(Iterables.transform(Arrays.asList(selectedKeys.split(",")), input -> OpenPgpUtils.convertKeyIdToHex(Long.valueOf(input)))) + ); + } + keyPref.setOnPreferenceClickListener((Preference pref) -> { + Intent intent = new Intent(callingActivity, PgpHandler.class); + intent.putExtra("Operation", "GET_KEY_ID"); + startActivityForResult(intent, IMPORT_PGP_KEY); + return true; + }); -// findPreference("openpgp_provider_list").setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { -// @Override -// public boolean onPreferenceChange(Preference preference, Object o) { -// ((UserPreference) getActivity()).mKey.setOpenPgpProvider((String) o); -// return false; -// } -// }); + findPreference("ssh_key").setOnPreferenceClickListener((Preference pref) -> { + callingActivity.getSshKey(); + return true; + }); + + findPreference("git_server_info").setOnPreferenceClickListener((Preference pref) -> { + Intent intent = new Intent(callingActivity, GitActivity.class); + intent.putExtra("Operation", GitActivity.EDIT_SERVER); + startActivityForResult(intent, EDIT_GIT_INFO); + return true; + }); + + findPreference("git_delete_repo").setOnPreferenceClickListener((Preference pref) -> { + new AlertDialog.Builder(callingActivity). + setTitle(R.string.pref_dialog_delete_title). + setMessage(R.string.pref_dialog_delete_msg). + setCancelable(false). + setPositiveButton(R.string.dialog_delete, + (dialog, id) -> { + try { + FileUtils.deleteDirectory(PasswordRepository.getWorkTree()); + } catch (Exception e) { + //TODO Handle the diffent cases of exceptions + } + + sharedPreferences.edit().putBoolean("repository_initialized", false).commit(); + dialog.cancel(); + callingActivity.finish(); + } + ). + setNegativeButton(R.string.dialog_do_not_delete, + (dialog, id) -> { + dialog.cancel(); + } + ). + show(); + return true; + }); + + callingActivity.mKey = (OpenPgpKeyPreference) findPreference("openpgp_key"); + if (sharedPreferences.getString("openpgp_provider_list", null) != null) + ((UserPreference) getActivity()).mKey.setOpenPgpProvider(sharedPreferences.getString("openpgp_provider_list", "")); + + findPreference("openpgp_provider_list").setOnPreferenceChangeListener((preference, o) -> { + callingActivity.mKey.setOpenPgpProvider((String) o); + return false; + }); } } @@ -104,63 +158,6 @@ public class UserPreference extends AppCompatActivity implements Preference.OnPr sshKey.close(); } - @Override - public boolean onPreferenceClick(Preference pref) { - switch (pref.getKey()) - { - case "openpgp_key_id": - { - Intent intent = new Intent(this, PgpHandler.class); - intent.putExtra("Operation", "GET_KEY_ID"); - startActivityForResult(intent, IMPORT_PGP_KEY); - } - break; - case "ssh_key": - { - getSshKey(); - } - break; - case "git_server_info": - { - Intent intent = new Intent(this, GitActivity.class); - intent.putExtra("Operation", GitActivity.EDIT_SERVER); - startActivityForResult(intent, EDIT_GIT_INFO); - } - break; - case "git_delete_repo": - { - new AlertDialog.Builder(this). - setTitle(R.string.pref_dialog_delete_title). - setMessage(R.string.pref_dialog_delete_msg). - setCancelable(false). - setPositiveButton(R.string.dialog_delete, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - try { - FileUtils.deleteDirectory(PasswordRepository.getWorkTree()); - } catch (Exception e) { - //TODO Handle the diffent cases of exceptions - } - - PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).edit().putBoolean("repository_initialized", false).commit(); - dialog.cancel(); - finish(); - } - } - ). - setNegativeButton(R.string.dialog_do_not_delete, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - dialog.cancel(); - } - } - ). - show(); - } - } - return true; - } - protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == RESULT_OK) { @@ -181,11 +178,8 @@ public class UserPreference extends AppCompatActivity implements Preference.OnPr new AlertDialog.Builder(this). setTitle(this.getResources().getString(R.string.ssh_key_error_dialog_title)). setMessage(this.getResources().getString(R.string.ssh_key_error_dialog_text) + e.getMessage()). - setPositiveButton(this.getResources().getString(R.string.dialog_ok), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - //pass - } + setPositiveButton(this.getResources().getString(R.string.dialog_ok), (dialogInterface, i) -> { + //pass }).show(); } } @@ -199,6 +193,7 @@ public class UserPreference extends AppCompatActivity implements Preference.OnPr { if (mKey.handleOnActivityResult(requestCode, resultCode, data)) { // handled by OpenPgpKeyPreference + PreferenceManager.getDefaultSharedPreferences(this.getApplicationContext()).edit().putLong("openpgp_sign_key", mKey.getValue()).apply(); return; } } diff --git a/app/src/main/java/com/zeapo/pwdstore/crypto/PgpHandler.java b/app/src/main/java/com/zeapo/pwdstore/crypto/PgpHandler.java index 3e94344d..baa25c16 100644 --- a/app/src/main/java/com/zeapo/pwdstore/crypto/PgpHandler.java +++ b/app/src/main/java/com/zeapo/pwdstore/crypto/PgpHandler.java @@ -25,17 +25,16 @@ import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; +import com.google.common.primitives.Longs; import com.zeapo.pwdstore.R; import com.zeapo.pwdstore.UserPreference; import com.zeapo.pwdstore.utils.PasswordRepository; import org.apache.commons.io.FileUtils; -import org.eclipse.jgit.util.StringUtils; import org.openintents.openpgp.IOpenPgpService; import org.openintents.openpgp.OpenPgpError; import org.openintents.openpgp.util.OpenPgpApi; import org.openintents.openpgp.util.OpenPgpServiceConnection; -import org.openintents.openpgp.util.OpenPgpUtils; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -44,12 +43,14 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; public class PgpHandler extends AppCompatActivity implements OpenPgpServiceConnection.OnBound{ private OpenPgpServiceConnection mServiceConnection; - private String keyIDs = ""; + private Set keyIDs = new HashSet<>(); SharedPreferences settings; private Activity activity; ClipboardManager clipboard; @@ -82,7 +83,7 @@ public class PgpHandler extends AppCompatActivity implements OpenPgpServiceConne // some persistance settings = PreferenceManager.getDefaultSharedPreferences(this); String providerPackageName = settings.getString("openpgp_provider_list", ""); - keyIDs = settings.getString("openpgp_key_ids", ""); + keyIDs = settings.getStringSet("openpgp_key_ids_set", new HashSet<>()); registered = false; @@ -355,6 +356,7 @@ public class PgpHandler extends AppCompatActivity implements OpenPgpServiceConne + ".gpg"; OutputStream outputStream = FileUtils.openOutputStream(new File(path)); outputStream.write(os.toByteArray()); + outputStream.close(); Intent data = new Intent(); data.putExtra("CREATED_FILE", path); data.putExtra("NAME", ((EditText) findViewById(R.id.crypto_password_file_edit)).getText().toString()); @@ -368,18 +370,10 @@ public class PgpHandler extends AppCompatActivity implements OpenPgpServiceConne // get key ids if (result.hasExtra(OpenPgpApi.RESULT_KEY_IDS)) { long[] ids = result.getLongArrayExtra(OpenPgpApi.RESULT_KEY_IDS); - ArrayList keys = new ArrayList(); + Set keys = new HashSet(); - for (int i = 0; i < ids.length; i++) { - keys.add(OpenPgpUtils.convertKeyIdToHex(ids[i])); - } - keyIDs = StringUtils.join(keys, ", "); - - if (!keyIDs.isEmpty()) { - String mKeys = keyIDs.split(",").length > 1 ? keyIDs : keyIDs.split(",")[0]; -// ((TextView) findViewById(R.id.crypto_key_ids)).setText(mKeys); - settings.edit().putString("openpgp_key_ids", keyIDs).apply(); - } + for (long id : ids) keys.add(String.valueOf(id)); // use Long + settings.edit().putStringSet("openpgp_key_ids_set", keys).apply(); showToast("PGP key selected"); setResult(RESULT_OK); @@ -438,9 +432,17 @@ public class PgpHandler extends AppCompatActivity implements OpenPgpServiceConne } } - + /** + * Encrypts a password file + * @param data + */ public void encrypt(Intent data) { data.setAction(OpenPgpApi.ACTION_ENCRYPT); + + ArrayList longKeys = new ArrayList<>(); + for (String keyId : keyIDs) longKeys.add(Long.valueOf(keyId)); + data.putExtra(OpenPgpApi.EXTRA_KEY_IDS, Longs.toArray(longKeys)); + data.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); String name = ((EditText) findViewById(R.id.crypto_password_file_edit)).getText().toString(); diff --git a/app/src/main/res/xml/preference.xml b/app/src/main/res/xml/preference.xml index c27f36f2..1d81f987 100644 --- a/app/src/main/res/xml/preference.xml +++ b/app/src/main/res/xml/preference.xml @@ -9,6 +9,10 @@ + + diff --git a/build.gradle b/build.gradle index f787acce..f062d72f 100644 --- a/build.gradle +++ b/build.gradle @@ -3,9 +3,11 @@ buildscript { repositories { jcenter() + mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:1.2.2' + classpath 'com.android.tools.build:gradle:1.2.3' + classpath 'me.tatarka:gradle-retrolambda:3.1.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files