From 7ee5ff76ba3468467a2b0396704e5c21962ba046 Mon Sep 17 00:00:00 2001 From: Matthew Wong Date: Sat, 21 Nov 2015 04:18:07 -0500 Subject: default to reasonable external directory --- app/build.gradle | 6 +++++- app/src/main/AndroidManifest.xml | 6 ++++-- app/src/main/java/com/zeapo/pwdstore/PasswordStore.java | 2 +- .../main/java/com/zeapo/pwdstore/UserPreference.java | 17 ++++++++++++++--- .../main/java/com/zeapo/pwdstore/git/GitActivity.java | 2 +- build.gradle | 1 + 6 files changed, 26 insertions(+), 8 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 13a92edb..db9fa9c1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -25,6 +25,8 @@ android { packagingOptions { exclude '.readme' + exclude 'META-INF/LICENSE.txt' + exclude 'META-INF/NOTICE.txt' } // @@ -67,7 +69,9 @@ dependencies { compile 'com.jcraft:jsch:0.1.53' compile 'org.apache.commons:commons-io:1.3.2' compile 'com.jayway.android.robotium:robotium-solo:5.3.1' - compile 'net.rdrei.android.dirchooser:library:2.1@aar' + compile ('net.rdrei.android.dirchooser:library:3.0@aar') { + transitive = true; + } compile group: 'com.google.guava', name: 'guava', version: '18.0' } tasks.findAll { // make all tasks whose name starts with 'assemble'... diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0789fd33..404a5138 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,7 @@ + xmlns:tools="http://schemas.android.com/tools" + package="com.zeapo.pwdstore"> @@ -8,7 +9,8 @@ + android:label="@string/app_name" android:theme="@style/AppTheme" + tools:replace="android:theme"> diff --git a/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java b/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java index 33b6bd29..83a21266 100644 --- a/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java +++ b/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java @@ -495,7 +495,7 @@ public class PasswordStore extends AppCompatActivity { PasswordRepository.closeRepository(); new AlertDialog.Builder(this) - .setTitle("Repositiory location") + .setTitle("Repository location") .setMessage("Select where to create or clone your password repository.") .setPositiveButton("External", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { diff --git a/app/src/main/java/com/zeapo/pwdstore/UserPreference.java b/app/src/main/java/com/zeapo/pwdstore/UserPreference.java index 8f8e8d66..7313ffb3 100644 --- a/app/src/main/java/com/zeapo/pwdstore/UserPreference.java +++ b/app/src/main/java/com/zeapo/pwdstore/UserPreference.java @@ -8,6 +8,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; import android.os.Bundle; +import android.os.Environment; import android.preference.CheckBoxPreference; import android.preference.Preference; import android.preference.PreferenceFragment; @@ -29,6 +30,7 @@ import com.zeapo.pwdstore.git.GitActivity; import com.zeapo.pwdstore.utils.PasswordRepository; import net.rdrei.android.dirchooser.DirectoryChooserActivity; +import net.rdrei.android.dirchooser.DirectoryChooserConfig; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; @@ -124,7 +126,8 @@ public class UserPreference extends AppCompatActivity { public boolean onPreferenceClick(Preference preference) { new AlertDialog.Builder(callingActivity). setTitle(R.string.pref_dialog_delete_title). - setMessage(R.string.pref_dialog_delete_msg). + setMessage(getResources().getString(R.string.dialog_delete_msg) + + " " + PasswordRepository.getWorkTree().toString()). setCancelable(false). setPositiveButton(R.string.dialog_delete, new DialogInterface.OnClickListener() { @Override @@ -265,8 +268,16 @@ public class UserPreference extends AppCompatActivity { public void selectExternalGitRepository() { Intent intent = new Intent(this, DirectoryChooserActivity.class); - intent.putExtra(DirectoryChooserActivity.EXTRA_NEW_DIR_NAME, - "passwordstore"); + File dir = new File(Environment.getExternalStorageDirectory() + "/PasswordStore"); + if (!dir.exists()) { + dir.mkdir(); + } + DirectoryChooserConfig config = DirectoryChooserConfig.builder() + .newDirectoryName("PasswordStore") + .allowNewDirectoryNameModification(true) + .initialDirectory(Environment.getExternalStorageDirectory() + "/PasswordStore") + .build(); + intent.putExtra(DirectoryChooserActivity.EXTRA_CONFIG, config); startActivityForResult(intent, SELECT_GIT_DIRECTORY); } diff --git a/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java b/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java index 00d5be35..d5cba03e 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java +++ b/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java @@ -481,7 +481,7 @@ public class GitActivity extends AppCompatActivity { if (localDir.exists() && localDir.listFiles().length != 0) { new AlertDialog.Builder(this). setTitle(R.string.dialog_delete_title). - setMessage(R.string.dialog_delete_msg). + setMessage(getResources().getString(R.string.dialog_delete_msg) + " " + localDir.toString()). setCancelable(false). setPositiveButton(R.string.dialog_delete, new DialogInterface.OnClickListener() { diff --git a/build.gradle b/build.gradle index 9cbebcf6..6fed505e 100644 --- a/build.gradle +++ b/build.gradle @@ -17,6 +17,7 @@ allprojects { repositories { jcenter() mavenCentral() + maven { url 'http://guardian.github.com/maven/repo-releases' } } } -- cgit v1.2.3 From 97087ba33e1deaa74e0fa4c51d527f18efa7c754 Mon Sep 17 00:00:00 2001 From: Matthew Wong Date: Sat, 21 Nov 2015 04:20:09 -0500 Subject: version bump --- app/build.gradle | 4 ++-- app/src/main/java/com/zeapo/pwdstore/UserPreference.java | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index db9fa9c1..84e716cf 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { applicationId "com.zeapo.pwdstore" minSdkVersion 15 targetSdkVersion 23 - versionCode 55 - versionName "1.2.0.35" + versionCode 56 + versionName "1.2.0.36" } compileOptions { diff --git a/app/src/main/java/com/zeapo/pwdstore/UserPreference.java b/app/src/main/java/com/zeapo/pwdstore/UserPreference.java index 7313ffb3..d1b3b360 100644 --- a/app/src/main/java/com/zeapo/pwdstore/UserPreference.java +++ b/app/src/main/java/com/zeapo/pwdstore/UserPreference.java @@ -16,7 +16,6 @@ import android.preference.PreferenceManager; import android.provider.Settings; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; -import android.text.SpannableStringBuilder; import android.view.MenuItem; import android.view.accessibility.AccessibilityManager; import android.widget.Toast; -- cgit v1.2.3 From 6e789a38f10da7c75fde3bed336dbf1d904d8efc Mon Sep 17 00:00:00 2001 From: zeapo Date: Sun, 22 Nov 2015 14:19:06 +0100 Subject: Add warnings to the user about storing the passwords on the sdcard --- app/build.gradle | 12 ++-- app/src/main/AndroidManifest.xml | 10 ++- .../java/com/zeapo/pwdstore/PasswordStore.java | 66 ++++++++++------- .../java/com/zeapo/pwdstore/UserPreference.java | 82 +++++++++++++++------- app/src/main/res/values/strings.xml | 2 +- app/src/main/res/values/styles.xml | 17 +++++ 6 files changed, 130 insertions(+), 59 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 84e716cf..df69ba77 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -58,20 +58,18 @@ android { } dependencies { - compile 'com.android.support:appcompat-v7:23.0.1' - compile 'com.android.support:recyclerview-v7:23.0.1' - compile 'com.android.support:cardview-v7:23.0.1' - compile 'com.android.support:design:23.0.1' + compile 'com.android.support:appcompat-v7:23.1.1' + compile 'com.android.support:recyclerview-v7:23.1.1' + compile 'com.android.support:cardview-v7:23.1.1' + compile 'com.android.support:design:23.1.1' compile 'org.sufficientlysecure:openpgp-api:9.0' + compile 'com.nononsenseapps:filepicker:2.4.2' compile ('org.eclipse.jgit:org.eclipse.jgit:3.7.1.201504261725-r') { exclude group: 'org.apache.httpcomponents', module: 'httpclient' } compile 'com.jcraft:jsch:0.1.53' compile 'org.apache.commons:commons-io:1.3.2' compile 'com.jayway.android.robotium:robotium-solo:5.3.1' - compile ('net.rdrei.android.dirchooser:library:3.0@aar') { - transitive = true; - } compile group: 'com.google.guava', name: 'guava', version: '18.0' } tasks.findAll { // make all tasks whose name starts with 'assemble'... diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 404a5138..7aa45ca4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -72,7 +72,15 @@ android:value="com.zeapo.pwdstore.PasswordStore" /> - + + + + + + diff --git a/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java b/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java index 83a21266..cca8493b 100644 --- a/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java +++ b/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java @@ -497,31 +497,7 @@ public class PasswordStore extends AppCompatActivity { new AlertDialog.Builder(this) .setTitle("Repository location") .setMessage("Select where to create or clone your password repository.") - .setPositiveButton("External", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - settings.edit().putBoolean("git_external", true).apply(); - - if (settings.getString("git_external_repo", null) == null) { - Intent intent = new Intent(activity, UserPreference.class); - intent.putExtra("operation", "git_external"); - startActivityForResult(intent, operation); - } else { - switch (operation) { - case NEW_REPO_BUTTON: - initializeRepositoryInfo(); - break; - case CLONE_REPO_BUTTON: - PasswordRepository.initialize(PasswordStore.this); - - Intent intent = new Intent(activity, GitActivity.class); - intent.putExtra("Operation", GitActivity.REQUEST_CLONE); - startActivityForResult(intent, GitActivity.REQUEST_CLONE); - break; - } - } - } - }) - .setNegativeButton("Internal", new DialogInterface.OnClickListener() { + .setPositiveButton("Hidden (preferred)", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { settings.edit().putBoolean("git_external", false).apply(); @@ -539,6 +515,46 @@ public class PasswordStore extends AppCompatActivity { } } }) + .setNegativeButton("SD-Card", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + settings.edit().putBoolean("git_external", true).apply(); + + if (settings.getString("git_external_repo", null) == null) { + Intent intent = new Intent(activity, UserPreference.class); + intent.putExtra("operation", "git_external"); + startActivityForResult(intent, operation); + } else { + new AlertDialog.Builder(activity). + setTitle("Directory already selected"). + setMessage("Do you want to use \"" + settings.getString("git_external_repo", null) + "\"?"). + setPositiveButton("Use", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + switch (operation) { + case NEW_REPO_BUTTON: + initializeRepositoryInfo(); + break; + case CLONE_REPO_BUTTON: + PasswordRepository.initialize(PasswordStore.this); + + Intent intent = new Intent(activity, GitActivity.class); + intent.putExtra("Operation", GitActivity.REQUEST_CLONE); + startActivityForResult(intent, GitActivity.REQUEST_CLONE); + break; + } + } + }). + setNegativeButton("Change", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Intent intent = new Intent(activity, UserPreference.class); + intent.putExtra("operation", "git_external"); + startActivityForResult(intent, operation); + } + }).show(); + } + } + }) .show(); } diff --git a/app/src/main/java/com/zeapo/pwdstore/UserPreference.java b/app/src/main/java/com/zeapo/pwdstore/UserPreference.java index d1b3b360..6ffc7abc 100644 --- a/app/src/main/java/com/zeapo/pwdstore/UserPreference.java +++ b/app/src/main/java/com/zeapo/pwdstore/UserPreference.java @@ -1,6 +1,7 @@ package com.zeapo.pwdstore; import android.accessibilityservice.AccessibilityServiceInfo; +import android.app.Activity; import android.app.DialogFragment; import android.content.Context; import android.content.DialogInterface; @@ -23,14 +24,12 @@ import android.widget.Toast; import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.collect.Iterables; +import com.nononsenseapps.filepicker.FilePickerActivity; import com.zeapo.pwdstore.autofill.AutofillPreferenceActivity; import com.zeapo.pwdstore.crypto.PgpHandler; import com.zeapo.pwdstore.git.GitActivity; import com.zeapo.pwdstore.utils.PasswordRepository; -import net.rdrei.android.dirchooser.DirectoryChooserActivity; -import net.rdrei.android.dirchooser.DirectoryChooserConfig; - import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.openintents.openpgp.util.OpenPgpKeyPreference; @@ -126,7 +125,7 @@ public class UserPreference extends AppCompatActivity { new AlertDialog.Builder(callingActivity). setTitle(R.string.pref_dialog_delete_title). setMessage(getResources().getString(R.string.dialog_delete_msg) - + " " + PasswordRepository.getWorkTree().toString()). + + " \n" + PasswordRepository.getWorkTree().toString()). setCancelable(false). setPositiveButton(R.string.dialog_delete, new DialogInterface.OnClickListener() { @Override @@ -266,19 +265,32 @@ public class UserPreference extends AppCompatActivity { } public void selectExternalGitRepository() { - Intent intent = new Intent(this, DirectoryChooserActivity.class); - File dir = new File(Environment.getExternalStorageDirectory() + "/PasswordStore"); - if (!dir.exists()) { - dir.mkdir(); - } - DirectoryChooserConfig config = DirectoryChooserConfig.builder() - .newDirectoryName("PasswordStore") - .allowNewDirectoryNameModification(true) - .initialDirectory(Environment.getExternalStorageDirectory() + "/PasswordStore") - .build(); - intent.putExtra(DirectoryChooserActivity.EXTRA_CONFIG, config); - - startActivityForResult(intent, SELECT_GIT_DIRECTORY); + final Activity activity = this; + new AlertDialog.Builder(this). + setTitle("Choose where to store the passwords"). + setMessage("You must select a directory where to store your passwords. If you want " + + "to store your passwords within the hidden storage of the application, " + + "cancel this dialog and disable the \"External Repository\" option."). + setPositiveButton(R.string.dialog_ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + // This always works + Intent i = new Intent(activity.getApplicationContext(), FilePickerActivity.class); + // This works if you defined the intent filter + // Intent i = new Intent(Intent.ACTION_GET_CONTENT); + + // Set these depending on your use case. These are the defaults. + i.putExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, false); + i.putExtra(FilePickerActivity.EXTRA_ALLOW_CREATE_DIR, true); + i.putExtra(FilePickerActivity.EXTRA_MODE, FilePickerActivity.MODE_DIR); + + i.putExtra(FilePickerActivity.EXTRA_START_PATH, Environment.getExternalStorageDirectory().getPath()); + + startActivityForResult(i, SELECT_GIT_DIRECTORY); + } + }). + setNegativeButton(R.string.dialog_cancel, null).show(); + } @Override @@ -381,17 +393,37 @@ public class UserPreference extends AppCompatActivity { } } break; + case SELECT_GIT_DIRECTORY: { + final Uri uri = data.getData(); + + if (uri.getPath().equals(Environment.getExternalStorageDirectory().getPath())) { + // the user wants to use the root of the sdcard as a store... + new AlertDialog.Builder(this). + setTitle("SD-Card root selected"). + setMessage("You have selected the root of your sdcard for the store. " + + "This is extremly dangerous and you will lose your data " + + "as its content will be deleted"). + setPositiveButton("Remove everything", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + PreferenceManager.getDefaultSharedPreferences(getApplicationContext()) + .edit() + .putString("git_external_repo", uri.getPath()) + .apply(); + } + }). + setNegativeButton(R.string.dialog_cancel, null).show(); + } else { + PreferenceManager.getDefaultSharedPreferences(getApplicationContext()) + .edit() + .putString("git_external_repo", uri.getPath()) + .apply(); + } + } + break; default: break; } } - - // why do they have to use a different resultCode than OK :/ - if (requestCode == SELECT_GIT_DIRECTORY && resultCode == DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED) { - PreferenceManager.getDefaultSharedPreferences(getApplicationContext()) - .edit() - .putString("git_external_repo", data.getStringExtra(DirectoryChooserActivity.RESULT_SELECTED_DIR)) - .apply(); - } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4047691f..9cb6ac1b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -9,7 +9,7 @@ Settings Hello world! Directory already exist - Target directory already exist. Current version support only a single store. Do you want to delete the current password store directory? + Target directory already exist. Current version support only a single store. Do you want to delete the current password store directory: Delete directory Cancel Repository information diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 3fffef42..fc592058 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -13,4 +13,21 @@ + + + + + -- cgit v1.2.3 From 5d6d349e6242f49aa5bf71aef96da8dfe92a65db Mon Sep 17 00:00:00 2001 From: zeapo Date: Sun, 22 Nov 2015 14:30:37 +0100 Subject: warn if the directory is not empty --- .../main/java/com/zeapo/pwdstore/UserPreference.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/zeapo/pwdstore/UserPreference.java b/app/src/main/java/com/zeapo/pwdstore/UserPreference.java index 6ffc7abc..dd743b64 100644 --- a/app/src/main/java/com/zeapo/pwdstore/UserPreference.java +++ b/app/src/main/java/com/zeapo/pwdstore/UserPreference.java @@ -401,7 +401,23 @@ public class UserPreference extends AppCompatActivity { new AlertDialog.Builder(this). setTitle("SD-Card root selected"). setMessage("You have selected the root of your sdcard for the store. " + - "This is extremly dangerous and you will lose your data " + + "This is extremely dangerous and you will lose your data " + + "as its content will be deleted"). + setPositiveButton("Remove everything", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + PreferenceManager.getDefaultSharedPreferences(getApplicationContext()) + .edit() + .putString("git_external_repo", uri.getPath()) + .apply(); + } + }). + setNegativeButton(R.string.dialog_cancel, null).show(); + } else if (new File(uri.getPath()).listFiles().length != 0) { + new AlertDialog.Builder(this). + setTitle("Directory not empty"). + setMessage("You have selected a non-empty directory for the store. " + + "This is extremely dangerous and you will lose your data " + "as its content will be deleted"). setPositiveButton("Remove everything", new DialogInterface.OnClickListener() { @Override -- cgit v1.2.3 From e2245271258062b0ca5110fa74d630c22ee1c355 Mon Sep 17 00:00:00 2001 From: Jaroslav Lichtblau Date: Mon, 23 Nov 2015 19:49:57 +0100 Subject: updated Czech translation --- app/src/main/res/values-cs/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 926e051e..99af0e3f 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -9,7 +9,7 @@ Nastavení Hello world! Adresář již existuje - Cílový adresář již existuje. Aktuální verze podporuje pouze jedno úložiště. Opravdu smazat aktuální adresář úložiště hesel? + Cílový adresář již existuje. Aktuální verze podporuje pouze jedno úložiště. Opravdu smazat aktuální adresář úložiště hesel: Smazat adresář Zrušit Informace repozitáře -- cgit v1.2.3 From 6f9f50db290c79ed434fb1fde3b1b0483826e852 Mon Sep 17 00:00:00 2001 From: Matthew Wong Date: Sun, 6 Dec 2015 21:56:39 -0500 Subject: Version bump --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index df69ba77..62ce2c36 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { applicationId "com.zeapo.pwdstore" minSdkVersion 15 targetSdkVersion 23 - versionCode 56 - versionName "1.2.0.36" + versionCode 57 + versionName "1.2.0.37" } compileOptions { -- cgit v1.2.3 From 60f65818f97e99384e8b59733943508ddc926ae3 Mon Sep 17 00:00:00 2001 From: Matthew Wong Date: Tue, 22 Dec 2015 21:13:59 -0500 Subject: Update hostname variable with needed protocol prefix when hitting SAVE not just CLONE (addresses #94, maybe some of the oddities observed in #137) --- .../java/com/zeapo/pwdstore/git/GitActivity.java | 82 +++++++++++++--------- 1 file changed, 49 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java b/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java index d5cba03e..132083d1 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java +++ b/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java @@ -45,7 +45,6 @@ public class GitActivity extends AppCompatActivity { private File localDir; private String hostname; - private String username; private String port; private SharedPreferences settings; @@ -401,6 +400,45 @@ public class GitActivity extends AppCompatActivity { return super.onOptionsItemSelected(item); } + /** + * Prepends the proper protocol to the hostname expected by jGit addRemote(). + */ + private void prependProtocol() { + hostname = ((EditText) findViewById(R.id.clone_uri)).getText().toString(); + port = ((EditText) findViewById(R.id.server_port)).getText().toString(); + // don't ask the user, take off the protocol that he puts in + hostname = hostname.replaceFirst("^.+://", ""); + ((TextView) findViewById(R.id.clone_uri)).setText(hostname); + + // now cheat a little and prepend the real protocol + // jGit does not accept a ssh:// but requires https:// + if (!protocol.equals("ssh://")) { + hostname = protocol + hostname; + } else { + // if the port is explicitly given, jgit requires the ssh:// + if (!port.isEmpty()) + hostname = protocol + hostname; + } + } + + private boolean forgotUsername() { + if (protocol.equals("ssh://")) { + // did he forget the username? + if (!hostname.matches("^.+@.+")) { + new AlertDialog.Builder(this). + setMessage(activity.getResources().getString(R.string.forget_username_dialog_text)). + setPositiveButton(activity.getResources().getString(R.string.dialog_oops), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + + } + }). + show(); + return true; + } + } + return false; + } /** * Saves the configuration found in the form */ @@ -416,8 +454,14 @@ public class GitActivity extends AppCompatActivity { editor.putString("git_remote_port", ((EditText) findViewById(R.id.server_port)).getText().toString()); editor.putString("git_remote_uri", ((EditText) findViewById(R.id.clone_uri)).getText().toString()); + // update hostname variable for use by addRemote() either here or later + // in syncRepository() + prependProtocol(); if (PasswordRepository.isInitialized()) { - PasswordRepository.addRemote("origin", ((EditText) findViewById(R.id.clone_uri)).getText().toString(), true); + // don't just use the clone_uri text, need to use hostname which has + // had the proper protocol prepended + Log.d("hostname", hostname); + PasswordRepository.addRemote("origin", hostname, true); } editor.apply(); @@ -429,6 +473,8 @@ public class GitActivity extends AppCompatActivity { * @param view */ public void saveConfiguration(View view) { + if (forgotUsername()) return; + saveConfiguration(); finish(); } @@ -443,38 +489,8 @@ public class GitActivity extends AppCompatActivity { PasswordRepository.initialize(this); } localDir = PasswordRepository.getWorkTree(); - hostname = ((EditText) findViewById(R.id.clone_uri)).getText().toString(); - port = ((EditText) findViewById(R.id.server_port)).getText().toString(); - // don't ask the user, take off the protocol that he puts in - hostname = hostname.replaceFirst("^.+://", ""); - ((TextView) findViewById(R.id.clone_uri)).setText(hostname); - - // now cheat a little and prepend the real protocol - // jGit does not accept a ssh:// but requires https:// - if (!protocol.equals("ssh://")) { - hostname = protocol + hostname; - } else { - - // if the port is explicitly given, jgit requires the ssh:// - if (!port.isEmpty()) - hostname = protocol + hostname; - - // did he forget the username? - if (!hostname.matches("^.+@.+")) { - new AlertDialog.Builder(this). - setMessage(activity.getResources().getString(R.string.forget_username_dialog_text)). - setPositiveButton(activity.getResources().getString(R.string.dialog_oops), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - - } - }). - show(); - return; - } - username = hostname.split("@")[0]; - } + if (forgotUsername()) return; saveConfiguration(); -- cgit v1.2.3 From 24b89992903ccc52dbe3191ff501028f4839762c Mon Sep 17 00:00:00 2001 From: Matthew Wong Date: Wed, 23 Dec 2015 00:20:09 -0500 Subject: Don't crash if no storage permission and it's needed --- .../java/com/zeapo/pwdstore/PasswordStore.java | 70 +++++++++++++++++++++- .../java/com/zeapo/pwdstore/UserPreference.java | 1 + .../java/com/zeapo/pwdstore/crypto/PgpHandler.java | 1 + .../java/com/zeapo/pwdstore/git/GitActivity.java | 1 - 4 files changed, 69 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java b/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java index cca8493b..96e58d89 100644 --- a/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java +++ b/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java @@ -1,13 +1,19 @@ package com.zeapo.pwdstore; +import android.Manifest; import android.app.Activity; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.graphics.Color; import android.os.Bundle; import android.preference.PreferenceManager; +import android.support.design.widget.Snackbar; +import android.support.v4.app.ActivityCompat; +import android.support.v4.content.ContextCompat; import android.support.v4.view.MenuItemCompat; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; @@ -16,6 +22,7 @@ import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; +import android.widget.TextView; import com.zeapo.pwdstore.crypto.PgpHandler; import com.zeapo.pwdstore.git.GitActivity; @@ -47,19 +54,76 @@ public class PasswordStore extends AppCompatActivity { private final static int NEW_REPO_BUTTON = 402; private final static int HOME = 403; + private final static int REQUEST_EXTERNAL_STORAGE = 50; @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_pwdstore); settings = PreferenceManager.getDefaultSharedPreferences(this.getApplicationContext()); activity = this; PRNGFixes.apply(); + + // If user opens app with permission granted then revokes and returns, + // prevent attempt to create password list fragment + if (savedInstanceState != null && (!settings.getBoolean("git_external", false) + || ContextCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)) { + savedInstanceState = null; + } + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_pwdstore); } @Override public void onResume(){ super.onResume(); - checkLocalRepository(); + // do not attempt to checkLocalRepository() if no storage permission: immediate crash + if (settings.getBoolean("git_external", false)) { + if (ContextCompat.checkSelfPermission(activity, + Manifest.permission.READ_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED) { + + if (ActivityCompat.shouldShowRequestPermissionRationale(activity, + Manifest.permission.READ_EXTERNAL_STORAGE)) { + Snackbar snack = Snackbar.make(findViewById(R.id.main_layout), "The store is on the sdcard but the app does not have permission to access it. Please give permission.", + Snackbar.LENGTH_INDEFINITE) + .setAction(R.string.dialog_ok, new View.OnClickListener() { + @Override + public void onClick(View view) { + ActivityCompat.requestPermissions(activity, + new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, + REQUEST_EXTERNAL_STORAGE); + } + }); + snack.show(); + View view = snack.getView(); + TextView tv = (TextView) view.findViewById(android.support.design.R.id.snackbar_text); + tv.setTextColor(Color.WHITE); + tv.setMaxLines(10); + } else { + // No explanation needed, we can request the permission. + ActivityCompat.requestPermissions(activity, + new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, + REQUEST_EXTERNAL_STORAGE); + } + } else { + checkLocalRepository(); + } + + } else { + checkLocalRepository(); + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, + String permissions[], int[] grantResults) { + switch (requestCode) { + case REQUEST_EXTERNAL_STORAGE: { + // If request is cancelled, the result arrays are empty. + if (grantResults.length > 0 + && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + checkLocalRepository(); + } + } + } } @Override diff --git a/app/src/main/java/com/zeapo/pwdstore/UserPreference.java b/app/src/main/java/com/zeapo/pwdstore/UserPreference.java index dd743b64..6311a7ac 100644 --- a/app/src/main/java/com/zeapo/pwdstore/UserPreference.java +++ b/app/src/main/java/com/zeapo/pwdstore/UserPreference.java @@ -231,6 +231,7 @@ public class UserPreference extends AppCompatActivity { public void onStart() { super.onStart(); final SharedPreferences sharedPreferences = getPreferenceManager().getSharedPreferences(); + findPreference("pref_select_external").setSummary(getPreferenceManager().getSharedPreferences().getString("git_external_repo", "No external repository selected")); findPreference("ssh_see_key").setEnabled(sharedPreferences.getBoolean("use_generated_key", false)); // see if the autofill service is enabled and check the preference accordingly 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 a620bd33..fd92a1f7 100644 --- a/app/src/main/java/com/zeapo/pwdstore/crypto/PgpHandler.java +++ b/app/src/main/java/com/zeapo/pwdstore/crypto/PgpHandler.java @@ -560,6 +560,7 @@ public class PgpHandler extends AppCompatActivity implements OpenPgpServiceConne } + // TODO (low priority but still...) android M potential permissions crashes @Override public void onBound(IOpenPgpService2 service) { Log.i("PGP", "ISBOUND!!"); diff --git a/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java b/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java index 132083d1..94589ed1 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java +++ b/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java @@ -460,7 +460,6 @@ public class GitActivity extends AppCompatActivity { if (PasswordRepository.isInitialized()) { // don't just use the clone_uri text, need to use hostname which has // had the proper protocol prepended - Log.d("hostname", hostname); PasswordRepository.addRemote("origin", hostname, true); } -- cgit v1.2.3 From 23c5603b7f583687c9943276ae544701111ed90b Mon Sep 17 00:00:00 2001 From: Matthew Wong Date: Wed, 23 Dec 2015 00:51:36 -0500 Subject: new gradle plugin and build tools --- app/build.gradle | 2 +- app/src/main/AndroidManifest.xml | 4 +--- build.gradle | 5 ++--- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 62ce2c36..cda1ac19 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,7 +4,7 @@ apply plugin: 'eclipse' android { compileSdkVersion 23 - buildToolsVersion "23.0.1" + buildToolsVersion '23.0.2' defaultConfig { applicationId "com.zeapo.pwdstore" minSdkVersion 15 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7aa45ca4..bd4c3704 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,5 @@ @@ -9,8 +8,7 @@ + android:label="@string/app_name" android:theme="@style/AppTheme"> diff --git a/build.gradle b/build.gradle index 6fed505e..68dfe62b 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:1.3.0' + classpath 'com.android.tools.build:gradle:1.5.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files @@ -17,13 +17,12 @@ allprojects { repositories { jcenter() mavenCentral() - maven { url 'http://guardian.github.com/maven/repo-releases' } } } ext { compileSdkVersion = 23 - buildToolsVersion = "23.0.1" + buildToolsVersion = "23.0.2" } subprojects { subproject -> afterEvaluate{ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 68e02ebb..1a704461 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu Dec 04 19:46:18 CET 2014 +#Wed Dec 23 00:45:56 EST 2015 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip -- cgit v1.2.3 From 406d6c04255bbd76915f6beb71a237f101737045 Mon Sep 17 00:00:00 2001 From: Matthew Wong Date: Wed, 23 Dec 2015 18:19:25 -0500 Subject: check for blank username & update 'hostname' all in saveConfiguration() --- .../java/com/zeapo/pwdstore/git/GitActivity.java | 64 ++++++++-------------- 1 file changed, 23 insertions(+), 41 deletions(-) diff --git a/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java b/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java index 94589ed1..a1ca9519 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java +++ b/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.java @@ -401,62 +401,45 @@ public class GitActivity extends AppCompatActivity { } /** - * Prepends the proper protocol to the hostname expected by jGit addRemote(). + * Saves the configuration found in the form */ - private void prependProtocol() { + private boolean saveConfiguration() { + // remember the settings + SharedPreferences.Editor editor = settings.edit(); + + editor.putString("git_remote_server", ((EditText) findViewById(R.id.server_url)).getText().toString()); + editor.putString("git_remote_location", ((EditText) findViewById(R.id.server_path)).getText().toString()); + editor.putString("git_remote_username", ((EditText) findViewById(R.id.server_user)).getText().toString()); + editor.putString("git_remote_protocol", protocol); + editor.putString("git_remote_auth", connectionMode); + editor.putString("git_remote_port", ((EditText) findViewById(R.id.server_port)).getText().toString()); + editor.putString("git_remote_uri", ((EditText) findViewById(R.id.clone_uri)).getText().toString()); + + // 'save' hostname variable for use by addRemote() either here or later + // in syncRepository() hostname = ((EditText) findViewById(R.id.clone_uri)).getText().toString(); port = ((EditText) findViewById(R.id.server_port)).getText().toString(); // don't ask the user, take off the protocol that he puts in hostname = hostname.replaceFirst("^.+://", ""); ((TextView) findViewById(R.id.clone_uri)).setText(hostname); - // now cheat a little and prepend the real protocol - // jGit does not accept a ssh:// but requires https:// if (!protocol.equals("ssh://")) { hostname = protocol + hostname; } else { + // if the port is explicitly given, jgit requires the ssh:// if (!port.isEmpty()) hostname = protocol + hostname; - } - } - private boolean forgotUsername() { - if (protocol.equals("ssh://")) { // did he forget the username? if (!hostname.matches("^.+@.+")) { new AlertDialog.Builder(this). setMessage(activity.getResources().getString(R.string.forget_username_dialog_text)). - setPositiveButton(activity.getResources().getString(R.string.dialog_oops), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - - } - }). + setPositiveButton(activity.getResources().getString(R.string.dialog_oops), null). show(); - return true; + return false; } } - return false; - } - /** - * Saves the configuration found in the form - */ - private void saveConfiguration() { - // remember the settings - SharedPreferences.Editor editor = settings.edit(); - - editor.putString("git_remote_server", ((EditText) findViewById(R.id.server_url)).getText().toString()); - editor.putString("git_remote_location", ((EditText) findViewById(R.id.server_path)).getText().toString()); - editor.putString("git_remote_username", ((EditText) findViewById(R.id.server_user)).getText().toString()); - editor.putString("git_remote_protocol", protocol); - editor.putString("git_remote_auth", connectionMode); - editor.putString("git_remote_port", ((EditText) findViewById(R.id.server_port)).getText().toString()); - editor.putString("git_remote_uri", ((EditText) findViewById(R.id.clone_uri)).getText().toString()); - - // update hostname variable for use by addRemote() either here or later - // in syncRepository() - prependProtocol(); if (PasswordRepository.isInitialized()) { // don't just use the clone_uri text, need to use hostname which has // had the proper protocol prepended @@ -464,6 +447,7 @@ public class GitActivity extends AppCompatActivity { } editor.apply(); + return true; } /** @@ -472,9 +456,8 @@ public class GitActivity extends AppCompatActivity { * @param view */ public void saveConfiguration(View view) { - if (forgotUsername()) return; - - saveConfiguration(); + if (!saveConfiguration()) + return; finish(); } @@ -489,9 +472,8 @@ public class GitActivity extends AppCompatActivity { } localDir = PasswordRepository.getWorkTree(); - if (forgotUsername()) return; - - saveConfiguration(); + if (!saveConfiguration()) + return; if (localDir.exists() && localDir.listFiles().length != 0) { new AlertDialog.Builder(this). -- cgit v1.2.3 From 9684c6c8a15809d8526ac8d9c0738b7edb7972d2 Mon Sep 17 00:00:00 2001 From: Matthew Wong Date: Sat, 26 Dec 2015 02:19:12 -0500 Subject: Delete unused gen. public key --- app/src/main/java/com/zeapo/pwdstore/UserPreference.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/src/main/java/com/zeapo/pwdstore/UserPreference.java b/app/src/main/java/com/zeapo/pwdstore/UserPreference.java index 6311a7ac..5fb710cf 100644 --- a/app/src/main/java/com/zeapo/pwdstore/UserPreference.java +++ b/app/src/main/java/com/zeapo/pwdstore/UserPreference.java @@ -367,6 +367,11 @@ public class UserPreference extends AppCompatActivity { SharedPreferences.Editor editor = prefs.edit(); editor.putBoolean("use_generated_key", false); editor.apply(); + + //delete the public key from generation + File file = new File(getFilesDir() + "/.ssh_key.pub"); + file.delete(); + setResult(RESULT_OK); finish(); } catch (IOException e) { -- cgit v1.2.3 From 893e0ce89daaa39f1157298c6a8dd10b7e98eceb Mon Sep 17 00:00:00 2001 From: Matthew Wong Date: Sat, 26 Dec 2015 02:26:59 -0500 Subject: Version bump 58 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index cda1ac19..38455ad3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { applicationId "com.zeapo.pwdstore" minSdkVersion 15 targetSdkVersion 23 - versionCode 57 - versionName "1.2.0.37" + versionCode 58 + versionName "1.2.0.38" } compileOptions { -- cgit v1.2.3