diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 8fed257a..cb6a55cd 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -8,4 +8,4 @@ jobs: - name: setup-android uses: msfjarvis/setup-android@0.2 with: - gradleTasks: build test lintDebug -Dpre-dex=false + gradleTasks: spotlessCheck build test lintDebug -Dpre-dex=false diff --git a/app/src/main/java/com/zeapo/pwdstore/LaunchActivity.kt b/app/src/main/java/com/zeapo/pwdstore/LaunchActivity.kt index 8f607ee0..69366a21 100644 --- a/app/src/main/java/com/zeapo/pwdstore/LaunchActivity.kt +++ b/app/src/main/java/com/zeapo/pwdstore/LaunchActivity.kt @@ -40,7 +40,7 @@ class LaunchActivity : AppCompatActivity() { decryptIntent.putExtra("LAST_CHANGED_TIMESTAMP", intent.getLongExtra("LAST_CHANGED_TIMESTAMP", 0L)) decryptIntent.putExtra("OPERATION", "DECRYPT") startActivity(decryptIntent) - }else { + } else { startActivity(Intent(this, PasswordStore::class.java)) } overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out) diff --git a/app/src/main/java/com/zeapo/pwdstore/PasswordFragment.java b/app/src/main/java/com/zeapo/pwdstore/PasswordFragment.java index 33424353..98803f29 100644 --- a/app/src/main/java/com/zeapo/pwdstore/PasswordFragment.java +++ b/app/src/main/java/com/zeapo/pwdstore/PasswordFragment.java @@ -6,7 +6,6 @@ import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; - import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.Fragment; @@ -14,22 +13,21 @@ import androidx.preference.PreferenceManager; import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; - import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.zeapo.pwdstore.utils.PasswordItem; import com.zeapo.pwdstore.utils.PasswordRecyclerAdapter; import com.zeapo.pwdstore.utils.PasswordRepository; - import java.io.File; import java.util.ArrayList; import java.util.Stack; /** * A fragment representing a list of Items. - *

- * Large screen devices (such as tablets) are supported by replacing the ListView - * with a GridView. - *

+ * + *

Large screen devices (such as tablets) are supported by replacing the ListView with a + * GridView. + * + *

*/ public class PasswordFragment extends Fragment { @@ -43,11 +41,10 @@ public class PasswordFragment extends Fragment { private SharedPreferences settings; /** - * Mandatory empty constructor for the fragment manager to instantiate the - * fragment (e.g. upon screen orientation changes). + * Mandatory empty constructor for the fragment manager to instantiate the fragment (e.g. upon + * screen orientation changes). */ - public PasswordFragment() { - } + public PasswordFragment() {} @Override public void onCreate(Bundle savedInstanceState) { @@ -58,13 +55,19 @@ public class PasswordFragment extends Fragment { passListStack = new Stack<>(); scrollPosition = new Stack<>(); pathStack = new Stack<>(); - recyclerAdapter = new PasswordRecyclerAdapter((PasswordStore) requireActivity(), mListener, - PasswordRepository.getPasswords(new File(path), PasswordRepository.getRepositoryDirectory(requireContext()), getSortOrder())); + recyclerAdapter = + new PasswordRecyclerAdapter( + (PasswordStore) requireActivity(), + mListener, + PasswordRepository.getPasswords( + new File(path), + PasswordRepository.getRepositoryDirectory(requireContext()), + getSortOrder())); } @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + public View onCreateView( + @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.password_recycler_view, container, false); // use a linear layout manager @@ -74,7 +77,8 @@ public class PasswordFragment extends Fragment { recyclerView.setLayoutManager(mLayoutManager); // use divider - recyclerView.addItemDecoration(new DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL)); + recyclerView.addItemDecoration( + new DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL)); // Set the adapter recyclerView.setAdapter(recyclerAdapter); @@ -90,55 +94,77 @@ public class PasswordFragment extends Fragment { public void onAttach(final Context context) { super.onAttach(context); try { - mListener = item -> { - if (item.getType() == PasswordItem.TYPE_CATEGORY) { - // push the current password list (non filtered plz!) - passListStack.push(pathStack.isEmpty() ? - PasswordRepository.getPasswords(PasswordRepository.getRepositoryDirectory(context), getSortOrder()) : - PasswordRepository.getPasswords(pathStack.peek(), PasswordRepository.getRepositoryDirectory(context), getSortOrder())); - //push the category were we're going - pathStack.push(item.getFile()); - scrollPosition.push(recyclerView.getVerticalScrollbarPosition()); + mListener = + item -> { + if (item.getType() == PasswordItem.TYPE_CATEGORY) { + // push the current password list (non filtered plz!) + passListStack.push( + pathStack.isEmpty() + ? PasswordRepository.getPasswords( + PasswordRepository.getRepositoryDirectory( + context), + getSortOrder()) + : PasswordRepository.getPasswords( + pathStack.peek(), + PasswordRepository.getRepositoryDirectory( + context), + getSortOrder())); + // push the category were we're going + pathStack.push(item.getFile()); + scrollPosition.push(recyclerView.getVerticalScrollbarPosition()); - recyclerView.scrollToPosition(0); - recyclerAdapter.clear(); - recyclerAdapter.addAll(PasswordRepository.getPasswords(item.getFile(), PasswordRepository.getRepositoryDirectory(context), getSortOrder())); + recyclerView.scrollToPosition(0); + recyclerAdapter.clear(); + recyclerAdapter.addAll( + PasswordRepository.getPasswords( + item.getFile(), + PasswordRepository.getRepositoryDirectory(context), + getSortOrder())); - ((AppCompatActivity) requireActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true); - } else { - if (getArguments().getBoolean("matchWith", false)) { - ((PasswordStore) requireActivity()).matchPasswordWithApp(item); - } else { - ((PasswordStore) requireActivity()).decryptPassword(item); - } - } - }; + ((AppCompatActivity) requireActivity()) + .getSupportActionBar() + .setDisplayHomeAsUpEnabled(true); + } else { + if (getArguments().getBoolean("matchWith", false)) { + ((PasswordStore) requireActivity()).matchPasswordWithApp(item); + } else { + ((PasswordStore) requireActivity()).decryptPassword(item); + } + } + }; } catch (ClassCastException e) { throw new ClassCastException(context + " must implement OnFragmentInteractionListener"); } } - /** - * clears the adapter content and sets it back to the root view - */ + /** clears the adapter content and sets it back to the root view */ public void updateAdapter() { passListStack.clear(); pathStack.clear(); scrollPosition.clear(); recyclerAdapter.clear(); - recyclerAdapter.addAll(PasswordRepository.getPasswords(PasswordRepository.getRepositoryDirectory(requireContext()), getSortOrder())); + recyclerAdapter.addAll( + PasswordRepository.getPasswords( + PasswordRepository.getRepositoryDirectory(requireContext()), + getSortOrder())); - ((AppCompatActivity) requireActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(false); + ((AppCompatActivity) requireActivity()) + .getSupportActionBar() + .setDisplayHomeAsUpEnabled(false); } - /** - * refreshes the adapter with the latest opened category - */ + /** refreshes the adapter with the latest opened category */ public void refreshAdapter() { recyclerAdapter.clear(); - recyclerAdapter.addAll(pathStack.isEmpty() ? - PasswordRepository.getPasswords(PasswordRepository.getRepositoryDirectory(requireContext()), getSortOrder()) : - PasswordRepository.getPasswords(pathStack.peek(), PasswordRepository.getRepositoryDirectory(requireContext()), getSortOrder())); + recyclerAdapter.addAll( + pathStack.isEmpty() + ? PasswordRepository.getPasswords( + PasswordRepository.getRepositoryDirectory(requireContext()), + getSortOrder()) + : PasswordRepository.getPasswords( + pathStack.peek(), + PasswordRepository.getRepositoryDirectory(requireContext()), + getSortOrder())); } /** @@ -158,13 +184,19 @@ public class PasswordFragment extends Fragment { * recursively filters a directory and extract all the matching items * * @param filter the filter to apply - * @param dir the directory to filter + * @param dir the directory to filter */ private void recursiveFilter(String filter, File dir) { // on the root the pathStack is empty - ArrayList passwordItems = dir == null ? - PasswordRepository.getPasswords(PasswordRepository.getRepositoryDirectory(requireContext()), getSortOrder()) : - PasswordRepository.getPasswords(dir, PasswordRepository.getRepositoryDirectory(requireContext()), getSortOrder()); + ArrayList passwordItems = + dir == null + ? PasswordRepository.getPasswords( + PasswordRepository.getRepositoryDirectory(requireContext()), + getSortOrder()) + : PasswordRepository.getPasswords( + dir, + PasswordRepository.getRepositoryDirectory(requireContext()), + getSortOrder()); boolean rec = settings.getBoolean("filter_recursively", true); for (PasswordItem item : passwordItems) { @@ -181,12 +213,9 @@ public class PasswordFragment extends Fragment { } } - /** - * Goes back one level back in the path - */ + /** Goes back one level back in the path */ public void popBack() { - if (passListStack.isEmpty()) - return; + if (passListStack.isEmpty()) return; recyclerView.scrollToPosition(scrollPosition.pop()); recyclerAdapter.clear(); @@ -200,10 +229,8 @@ public class PasswordFragment extends Fragment { * @return the current directory */ public File getCurrentDir() { - if (pathStack.isEmpty()) - return PasswordRepository.getRepositoryDirectory(requireContext()); - else - return pathStack.peek(); + if (pathStack.isEmpty()) return PasswordRepository.getRepositoryDirectory(requireContext()); + else return pathStack.peek(); } public boolean isNotEmpty() { diff --git a/app/src/main/java/com/zeapo/pwdstore/PasswordGeneratorDialogFragment.java b/app/src/main/java/com/zeapo/pwdstore/PasswordGeneratorDialogFragment.java index 6ec0529e..2f72352b 100644 --- a/app/src/main/java/com/zeapo/pwdstore/PasswordGeneratorDialogFragment.java +++ b/app/src/main/java/com/zeapo/pwdstore/PasswordGeneratorDialogFragment.java @@ -13,27 +13,19 @@ import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.Toast; - import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.AppCompatEditText; import androidx.appcompat.widget.AppCompatTextView; import androidx.fragment.app.DialogFragment; - import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.zeapo.pwdstore.pwgen.PasswordGenerator; - +import java.util.ArrayList; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; - - -/** - * A placeholder fragment containing a simple view. - */ +/** A placeholder fragment containing a simple view. */ public class PasswordGeneratorDialogFragment extends DialogFragment { - public PasswordGeneratorDialogFragment() { - } + public PasswordGeneratorDialogFragment() {} @NotNull @SuppressLint("SetTextI18n") @@ -42,13 +34,17 @@ public class PasswordGeneratorDialogFragment extends DialogFragment { final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireContext()); final Activity callingActivity = requireActivity(); LayoutInflater inflater = callingActivity.getLayoutInflater(); - @SuppressLint("InflateParams") final View view = inflater.inflate(R.layout.fragment_pwgen, null); - Typeface monoTypeface = Typeface.createFromAsset(callingActivity.getAssets(), "fonts/sourcecodepro.ttf"); + @SuppressLint("InflateParams") + final View view = inflater.inflate(R.layout.fragment_pwgen, null); + Typeface monoTypeface = + Typeface.createFromAsset(callingActivity.getAssets(), "fonts/sourcecodepro.ttf"); builder.setView(view); - SharedPreferences prefs - = requireActivity().getApplicationContext().getSharedPreferences("PasswordGenerator", Context.MODE_PRIVATE); + SharedPreferences prefs = + requireActivity() + .getApplicationContext() + .getSharedPreferences("PasswordGenerator", Context.MODE_PRIVATE); CheckBox checkBox = view.findViewById(R.id.numerals); checkBox.setChecked(!prefs.getBoolean("0", false)); @@ -74,38 +70,53 @@ public class PasswordGeneratorDialogFragment extends DialogFragment { AppCompatTextView passwordText = view.findViewById(R.id.passwordText); passwordText.setTypeface(monoTypeface); - builder.setPositiveButton(getResources().getString(R.string.dialog_ok), (dialog, which) -> { - EditText edit = callingActivity.findViewById(R.id.crypto_password_edit); - edit.setText(passwordText.getText()); - }); + builder.setPositiveButton( + getResources().getString(R.string.dialog_ok), + (dialog, which) -> { + EditText edit = callingActivity.findViewById(R.id.crypto_password_edit); + edit.setText(passwordText.getText()); + }); - builder.setNegativeButton(getResources().getString(R.string.dialog_cancel), (dialog, which) -> { - - }); + builder.setNegativeButton( + getResources().getString(R.string.dialog_cancel), (dialog, which) -> {}); builder.setNeutralButton(getResources().getString(R.string.pwgen_generate), null); - final AlertDialog ad = builder.setTitle(this.getResources().getString(R.string.pwgen_title)).create(); - ad.setOnShowListener(dialog -> { - setPreferences(); - try { - passwordText.setText(PasswordGenerator.generate(requireActivity().getApplicationContext()).get(0)); - } catch (PasswordGenerator.PasswordGeneratorExeption e) { - Toast.makeText(requireActivity(), e.getMessage(), Toast.LENGTH_SHORT).show(); - passwordText.setText(""); - } + final AlertDialog ad = + builder.setTitle(this.getResources().getString(R.string.pwgen_title)).create(); + ad.setOnShowListener( + dialog -> { + setPreferences(); + try { + passwordText.setText( + PasswordGenerator.generate( + requireActivity().getApplicationContext()) + .get(0)); + } catch (PasswordGenerator.PasswordGeneratorExeption e) { + Toast.makeText(requireActivity(), e.getMessage(), Toast.LENGTH_SHORT) + .show(); + passwordText.setText(""); + } - Button b = ad.getButton(AlertDialog.BUTTON_NEUTRAL); - b.setOnClickListener(v -> { - setPreferences(); - try { - passwordText.setText(PasswordGenerator.generate(callingActivity.getApplicationContext()).get(0)); - } catch (PasswordGenerator.PasswordGeneratorExeption e) { - Toast.makeText(requireActivity(), e.getMessage(), Toast.LENGTH_SHORT).show(); - passwordText.setText(""); - } - }); - }); + Button b = ad.getButton(AlertDialog.BUTTON_NEUTRAL); + b.setOnClickListener( + v -> { + setPreferences(); + try { + passwordText.setText( + PasswordGenerator.generate( + callingActivity.getApplicationContext()) + .get(0)); + } catch (PasswordGenerator.PasswordGeneratorExeption e) { + Toast.makeText( + requireActivity(), + e.getMessage(), + Toast.LENGTH_SHORT) + .show(); + passwordText.setText(""); + } + }); + }); return ad; } @@ -133,10 +144,10 @@ public class PasswordGeneratorDialogFragment extends DialogFragment { EditText editText = getDialog().findViewById(R.id.lengthNumber); try { int length = Integer.valueOf(editText.getText().toString()); - PasswordGenerator.setPrefs(requireActivity().getApplicationContext(), preferences, length); + PasswordGenerator.setPrefs( + requireActivity().getApplicationContext(), preferences, length); } catch (NumberFormatException e) { PasswordGenerator.setPrefs(requireActivity().getApplicationContext(), preferences); } } } - diff --git a/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java b/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java index a0003bb9..3c0d0d6c 100644 --- a/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java +++ b/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java @@ -18,7 +18,6 @@ import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.View; - import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.AppCompatTextView; @@ -28,7 +27,6 @@ import androidx.core.content.ContextCompat; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; import androidx.preference.PreferenceManager; - import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.snackbar.Snackbar; import com.zeapo.pwdstore.crypto.PgpActivity; @@ -38,14 +36,6 @@ import com.zeapo.pwdstore.git.GitOperation; import com.zeapo.pwdstore.utils.PasswordItem; import com.zeapo.pwdstore.utils.PasswordRecyclerAdapter; import com.zeapo.pwdstore.utils.PasswordRepository; - -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.FilenameUtils; -import org.eclipse.jgit.api.Git; -import org.eclipse.jgit.api.errors.GitAPIException; -import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.revwalk.RevCommit; - import java.io.File; import java.util.ArrayList; import java.util.Collections; @@ -53,6 +43,12 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.FilenameUtils; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; public class PasswordStore extends AppCompatActivity { @@ -65,10 +61,10 @@ public class PasswordStore extends AppCompatActivity { public static final int REQUEST_CODE_EDIT = 9916; public static final int REQUEST_CODE_SELECT_FOLDER = 9917; private static final String TAG = PasswordStore.class.getName(); - private final static int CLONE_REPO_BUTTON = 401; - private final static int NEW_REPO_BUTTON = 402; - private final static int HOME = 403; - private final static int REQUEST_EXTERNAL_STORAGE = 50; + private static final int CLONE_REPO_BUTTON = 401; + private static final int NEW_REPO_BUTTON = 402; + private static final int HOME = 403; + private static final int REQUEST_EXTERNAL_STORAGE = 50; private SharedPreferences settings; private Activity activity; private PasswordFragment plist; @@ -78,16 +74,16 @@ public class PasswordStore extends AppCompatActivity { private static boolean isPrintable(char c) { Character.UnicodeBlock block = Character.UnicodeBlock.of(c); - return (!Character.isISOControl(c)) && - block != null && - block != Character.UnicodeBlock.SPECIALS; + return (!Character.isISOControl(c)) + && block != null + && block != Character.UnicodeBlock.SPECIALS; } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { // open search view on search key, or Ctr+F - if ((keyCode == KeyEvent.KEYCODE_SEARCH || - keyCode == KeyEvent.KEYCODE_F && event.isCtrlPressed()) + if ((keyCode == KeyEvent.KEYCODE_SEARCH + || keyCode == KeyEvent.KEYCODE_F && event.isCtrlPressed()) && !searchItem.isActionViewExpanded()) { searchItem.expandActionView(); return true; @@ -116,8 +112,11 @@ public class PasswordStore extends AppCompatActivity { // 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)) { + if (savedInstanceState != null + && (!settings.getBoolean("git_external", false) + || ContextCompat.checkSelfPermission( + activity, Manifest.permission.READ_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED)) { savedInstanceState = null; } super.onCreate(savedInstanceState); @@ -129,27 +128,39 @@ public class PasswordStore extends AppCompatActivity { super.onResume(); // 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) + if (ContextCompat.checkSelfPermission( + activity, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { - if (ActivityCompat.shouldShowRequestPermissionRationale(activity, - Manifest.permission.READ_EXTERNAL_STORAGE)) { + if (ActivityCompat.shouldShowRequestPermissionRationale( + activity, Manifest.permission.READ_EXTERNAL_STORAGE)) { // TODO: strings.xml - 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, view -> ActivityCompat.requestPermissions(activity, - new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, - REQUEST_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, + view -> + ActivityCompat.requestPermissions( + activity, + new String[] { + Manifest.permission + .READ_EXTERNAL_STORAGE + }, + REQUEST_EXTERNAL_STORAGE)); snack.show(); View view = snack.getView(); - AppCompatTextView tv = view.findViewById(com.google.android.material.R.id.snackbar_text); + AppCompatTextView tv = + view.findViewById(com.google.android.material.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}, + ActivityCompat.requestPermissions( + activity, + new String[] {Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_EXTERNAL_STORAGE); } } else { @@ -162,11 +173,11 @@ public class PasswordStore extends AppCompatActivity { } @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + public void onRequestPermissionsResult( + int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { // If request is cancelled, the result arrays are empty. if (requestCode == REQUEST_EXTERNAL_STORAGE) { - if (grantResults.length > 0 - && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { checkLocalRepository(); } } @@ -179,33 +190,35 @@ public class PasswordStore extends AppCompatActivity { searchItem = menu.findItem(R.id.action_search); searchView = (SearchView) searchItem.getActionView(); - searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { - @Override - public boolean onQueryTextSubmit(String s) { - return true; - } + searchView.setOnQueryTextListener( + new SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(String s) { + return true; + } - @Override - public boolean onQueryTextChange(String s) { - filterListAdapter(s); - return true; - } - }); + @Override + public boolean onQueryTextChange(String s) { + filterListAdapter(s); + return true; + } + }); // When using the support library, the setOnActionExpandListener() method is // static and accepts the MenuItem object as an argument - searchItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() { - @Override - public boolean onMenuItemActionCollapse(MenuItem item) { - refreshListAdapter(); - return true; - } + searchItem.setOnActionExpandListener( + new MenuItem.OnActionExpandListener() { + @Override + public boolean onMenuItemActionCollapse(MenuItem item) { + refreshListAdapter(); + return true; + } - @Override - public boolean onMenuItemActionExpand(MenuItem item) { - return true; - } - }); + @Override + public boolean onMenuItemActionExpand(MenuItem item) { + return true; + } + }); return super.onCreateOptionsMenu(menu); } @@ -217,9 +230,10 @@ public class PasswordStore extends AppCompatActivity { int id = item.getItemId(); Intent intent; - final MaterialAlertDialogBuilder initBefore = new MaterialAlertDialogBuilder(this) - .setMessage(this.getResources().getString(R.string.creation_dialog_text)) - .setPositiveButton(this.getResources().getString(R.string.dialog_ok), null); + final MaterialAlertDialogBuilder initBefore = + new MaterialAlertDialogBuilder(this) + .setMessage(this.getResources().getString(R.string.creation_dialog_text)) + .setPositiveButton(this.getResources().getString(R.string.dialog_ok), null); switch (id) { case R.id.user_pref: @@ -306,8 +320,7 @@ public class PasswordStore extends AppCompatActivity { final File localDir = PasswordRepository.getRepositoryDirectory(getApplicationContext()); try { - if (!localDir.mkdir()) - throw new IllegalStateException("Failed to create directory!"); + if (!localDir.mkdir()) throw new IllegalStateException("Failed to create directory!"); PasswordRepository.createRepository(localDir); if (new File(localDir.getAbsolutePath() + "/.gpg-id").createNewFile()) { settings.edit().putBoolean("repository_initialized", true).apply(); @@ -329,9 +342,13 @@ public class PasswordStore extends AppCompatActivity { if (settings.getBoolean("git_external", false) && externalRepoPath != null) { File dir = new File(externalRepoPath); - if (dir.exists() && - dir.isDirectory() && - !PasswordRepository.getPasswords(dir, PasswordRepository.getRepositoryDirectory(this), getSortOrder()).isEmpty()) { + if (dir.exists() + && dir.isDirectory() + && !PasswordRepository.getPasswords( + dir, + PasswordRepository.getRepositoryDirectory(this), + getSortOrder()) + .isEmpty()) { PasswordRepository.closeRepository(); checkLocalRepository(); @@ -344,11 +361,14 @@ public class PasswordStore extends AppCompatActivity { if (keyIds.isEmpty()) new MaterialAlertDialogBuilder(this) .setMessage(this.getResources().getString(R.string.key_dialog_text)) - .setPositiveButton(this.getResources().getString(R.string.dialog_positive), (dialogInterface, i) -> { - Intent intent = new Intent(activity, UserPreference.class); - startActivityForResult(intent, GitActivity.REQUEST_INIT); - }) - .setNegativeButton(this.getResources().getString(R.string.dialog_negative), null) + .setPositiveButton( + this.getResources().getString(R.string.dialog_positive), + (dialogInterface, i) -> { + Intent intent = new Intent(activity, UserPreference.class); + startActivityForResult(intent, GitActivity.REQUEST_INIT); + }) + .setNegativeButton( + this.getResources().getString(R.string.dialog_negative), null) .show(); createRepository(); @@ -361,7 +381,8 @@ public class PasswordStore extends AppCompatActivity { intent.putExtra("operation", "git_external"); startActivityForResult(intent, HOME); } else { - checkLocalRepository(PasswordRepository.getRepositoryDirectory(getApplicationContext())); + checkLocalRepository( + PasswordRepository.getRepositoryDirectory(getApplicationContext())); } } @@ -371,12 +392,16 @@ public class PasswordStore extends AppCompatActivity { if (localDir != null && settings.getBoolean("repository_initialized", false)) { Log.d(TAG, "Check, dir: " + localDir.getAbsolutePath()); // do not push the fragment if we already have it - if (fragmentManager.findFragmentByTag("PasswordsList") == null || settings.getBoolean("repo_changed", false)) { + if (fragmentManager.findFragmentByTag("PasswordsList") == null + || settings.getBoolean("repo_changed", false)) { settings.edit().putBoolean("repo_changed", false).apply(); plist = new PasswordFragment(); Bundle args = new Bundle(); - args.putString("Path", PasswordRepository.getRepositoryDirectory(getApplicationContext()).getAbsolutePath()); + args.putString( + "Path", + PasswordRepository.getRepositoryDirectory(getApplicationContext()) + .getAbsolutePath()); // if the activity was started from the autofill settings, the // intent is to match a clicked pwd with app. pass this to fragment @@ -405,7 +430,6 @@ public class PasswordStore extends AppCompatActivity { } } - @Override public void onBackPressed() { if ((null != plist) && plist.isNotEmpty()) { @@ -433,16 +457,13 @@ public class PasswordStore extends AppCompatActivity { } Git git = new Git(repository); - String relativePath = getRelativePath(fullPath, repoPath.getAbsolutePath()) - .substring(1); // Removes leading '/' + String relativePath = + getRelativePath(fullPath, repoPath.getAbsolutePath()) + .substring(1); // Removes leading '/' Iterator iterator; try { - iterator = git - .log() - .addPath(relativePath) - .call() - .iterator(); + iterator = git.log().addPath(relativePath).call().iterator(); } catch (GitAPIException e) { Log.e(TAG, "getLastChangedTimestamp: GITAPIException", e); return -1; @@ -462,23 +483,29 @@ public class PasswordStore extends AppCompatActivity { for (Intent intent : new Intent[] {decryptIntent, authDecryptIntent}) { intent.putExtra("NAME", item.toString()); intent.putExtra("FILE_PATH", item.getFile().getAbsolutePath()); - intent.putExtra("REPO_PATH", PasswordRepository.getRepositoryDirectory(getApplicationContext()).getAbsolutePath()); - intent.putExtra("LAST_CHANGED_TIMESTAMP", getLastChangedTimestamp(item.getFile().getAbsolutePath())); + intent.putExtra( + "REPO_PATH", + PasswordRepository.getRepositoryDirectory(getApplicationContext()) + .getAbsolutePath()); + intent.putExtra( + "LAST_CHANGED_TIMESTAMP", + getLastChangedTimestamp(item.getFile().getAbsolutePath())); intent.putExtra("OPERATION", "DECRYPT"); } // Adds shortcut if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { - ShortcutInfo shortcut = new ShortcutInfo.Builder(this, item.getFullPathToParent()) - .setShortLabel(item.toString()) - .setLongLabel(item.getFullPathToParent() + item.toString()) - .setIcon(Icon.createWithResource(this, R.mipmap.ic_launcher)) - .setIntent(authDecryptIntent.setAction("DECRYPT_PASS")) // Needs action - .build(); + ShortcutInfo shortcut = + new ShortcutInfo.Builder(this, item.getFullPathToParent()) + .setShortLabel(item.toString()) + .setLongLabel(item.getFullPathToParent() + item.toString()) + .setIcon(Icon.createWithResource(this, R.mipmap.ic_launcher)) + .setIntent(authDecryptIntent.setAction("DECRYPT_PASS")) // Needs action + .build(); List shortcuts = shortcutManager.getDynamicShortcuts(); - if (shortcuts.size() >= shortcutManager.getMaxShortcutCountPerActivity() && - shortcuts.size() > 0) { + if (shortcuts.size() >= shortcutManager.getMaxShortcutCountPerActivity() + && shortcuts.size() > 0) { shortcuts.remove(shortcuts.size() - 1); shortcuts.add(0, shortcut); shortcutManager.setDynamicShortcuts(shortcuts); @@ -494,7 +521,10 @@ public class PasswordStore extends AppCompatActivity { intent.putExtra("NAME", item.toString()); intent.putExtra("FILE_PATH", item.getFile().getAbsolutePath()); intent.putExtra("PARENT_PATH", getCurrentDir().getAbsolutePath()); - intent.putExtra("REPO_PATH", PasswordRepository.getRepositoryDirectory(getApplicationContext()).getAbsolutePath()); + intent.putExtra( + "REPO_PATH", + PasswordRepository.getRepositoryDirectory(getApplicationContext()) + .getAbsolutePath()); intent.putExtra("OPERATION", "EDIT"); startActivityForResult(intent, REQUEST_CODE_EDIT); } @@ -503,8 +533,10 @@ public class PasswordStore extends AppCompatActivity { if (!PasswordRepository.isInitialized()) { new MaterialAlertDialogBuilder(this) .setMessage(this.getResources().getString(R.string.creation_dialog_text)) - .setPositiveButton(this.getResources().getString(R.string.dialog_ok), (dialogInterface, i) -> { - }).show(); + .setPositiveButton( + this.getResources().getString(R.string.dialog_ok), + (dialogInterface, i) -> {}) + .show(); return; } @@ -512,10 +544,13 @@ public class PasswordStore extends AppCompatActivity { new MaterialAlertDialogBuilder(this) .setTitle(this.getResources().getString(R.string.no_key_selected_dialog_title)) .setMessage(this.getResources().getString(R.string.no_key_selected_dialog_text)) - .setPositiveButton(this.getResources().getString(R.string.dialog_ok), (dialogInterface, i) -> { - Intent intent = new Intent(activity, UserPreference.class); - startActivity(intent); - }).show(); + .setPositiveButton( + this.getResources().getString(R.string.dialog_ok), + (dialogInterface, i) -> { + Intent intent = new Intent(activity, UserPreference.class); + startActivity(intent); + }) + .show(); return; } @@ -524,13 +559,17 @@ public class PasswordStore extends AppCompatActivity { Intent intent = new Intent(this, PgpActivity.class); intent.putExtra("FILE_PATH", getCurrentDir().getAbsolutePath()); - intent.putExtra("REPO_PATH", PasswordRepository.getRepositoryDirectory(getApplicationContext()).getAbsolutePath()); + intent.putExtra( + "REPO_PATH", + PasswordRepository.getRepositoryDirectory(getApplicationContext()) + .getAbsolutePath()); intent.putExtra("OPERATION", "ENCRYPT"); startActivityForResult(intent, REQUEST_CODE_ENCRYPT); } // deletes passwords in order from top to bottom - public void deletePasswords(final PasswordRecyclerAdapter adapter, final Set selectedItems) { + public void deletePasswords( + final PasswordRecyclerAdapter adapter, final Set selectedItems) { final Iterator it = selectedItems.iterator(); if (!it.hasNext()) { return; @@ -538,21 +577,29 @@ public class PasswordStore extends AppCompatActivity { final int position = (int) it.next(); final PasswordItem item = adapter.getValues().get(position); new MaterialAlertDialogBuilder(this) - .setMessage(getResources().getString(R.string.delete_dialog_text, item.getLongName())) - .setPositiveButton(getResources().getString(R.string.dialog_yes), (dialogInterface, i) -> { - item.getFile().delete(); - adapter.remove(position); - it.remove(); - adapter.updateSelectedItems(position, selectedItems); + .setMessage( + getResources().getString(R.string.delete_dialog_text, item.getLongName())) + .setPositiveButton( + getResources().getString(R.string.dialog_yes), + (dialogInterface, i) -> { + item.getFile().delete(); + adapter.remove(position); + it.remove(); + adapter.updateSelectedItems(position, selectedItems); - commitChange(getResources().getString(R.string.git_commit_remove_text, - item.getLongName())); - deletePasswords(adapter, selectedItems); - }) - .setNegativeButton(this.getResources().getString(R.string.dialog_no), (dialogInterface, i) -> { - it.remove(); - deletePasswords(adapter, selectedItems); - }) + commitChange( + getResources() + .getString( + R.string.git_commit_remove_text, + item.getLongName())); + deletePasswords(adapter, selectedItems); + }) + .setNegativeButton( + this.getResources().getString(R.string.dialog_no), + (dialogInterface, i) -> { + it.remove(); + deletePasswords(adapter, selectedItems); + }) .show(); } @@ -567,18 +614,14 @@ public class PasswordStore extends AppCompatActivity { startActivityForResult(intent, REQUEST_CODE_SELECT_FOLDER); } - /** - * clears adapter's content and updates it with a fresh list of passwords from the root - */ + /** clears adapter's content and updates it with a fresh list of passwords from the root */ public void updateListAdapter() { if ((null != plist)) { plist.updateAdapter(); } } - /** - * Updates the adapter with the current view of passwords - */ + /** Updates the adapter with the current view of passwords */ private void refreshListAdapter() { if ((null != plist)) { plist.refreshAdapter(); @@ -607,14 +650,12 @@ public class PasswordStore extends AppCompatActivity { GitAsyncTask tasks = new GitAsyncTask(activity, false, true, this); tasks.execute( git.add().addFilepattern("."), - git.commit().setAll(true).setMessage(message) - ); + git.commit().setAll(true).setMessage(message)); } }.execute(); } - protected void onActivityResult(int requestCode, int resultCode, - Intent data) { + protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == RESULT_OK) { switch (requestCode) { case GitActivity.REQUEST_CLONE: @@ -622,26 +663,39 @@ public class PasswordStore extends AppCompatActivity { settings.edit().putBoolean("repository_initialized", true).apply(); break; case REQUEST_CODE_DECRYPT_AND_VERIFY: - // if went from decrypt->edit and user saved changes or HOTP counter was incremented, we need to commitChange + // if went from decrypt->edit and user saved changes or HOTP counter was + // incremented, we need to commitChange if (data != null && data.getBooleanExtra("needCommit", false)) { if (data.getStringExtra("OPERATION").equals("EDIT")) { - commitChange(this.getResources().getString(R.string.git_commit_edit_text, - data.getExtras().getString("LONG_NAME"))); + commitChange( + this.getResources() + .getString( + R.string.git_commit_edit_text, + data.getExtras().getString("LONG_NAME"))); } else { - commitChange(this.getResources().getString(R.string.git_commit_increment_text, - data.getExtras().getString("LONG_NAME"))); + commitChange( + this.getResources() + .getString( + R.string.git_commit_increment_text, + data.getExtras().getString("LONG_NAME"))); } } refreshListAdapter(); break; case REQUEST_CODE_ENCRYPT: - commitChange(this.getResources().getString(R.string.git_commit_add_text, - data.getExtras().getString("LONG_NAME"))); + commitChange( + this.getResources() + .getString( + R.string.git_commit_add_text, + data.getExtras().getString("LONG_NAME"))); refreshListAdapter(); break; case REQUEST_CODE_EDIT: - commitChange(this.getResources().getString(R.string.git_commit_edit_text, - data.getExtras().getString("LONG_NAME"))); + commitChange( + this.getResources() + .getString( + R.string.git_commit_edit_text, + data.getExtras().getString("LONG_NAME"))); refreshListAdapter(); break; case GitActivity.REQUEST_INIT: @@ -657,15 +711,20 @@ public class PasswordStore extends AppCompatActivity { break; case CLONE_REPO_BUTTON: // duplicate code - if (settings.getBoolean("git_external", false) && settings.getString("git_external_repo", null) != null) { + if (settings.getBoolean("git_external", false) + && settings.getString("git_external_repo", null) != null) { String externalRepoPath = settings.getString("git_external_repo", null); File dir = externalRepoPath != null ? new File(externalRepoPath) : null; - if (dir != null && - dir.exists() && - dir.isDirectory() && - !FileUtils.listFiles(dir, null, true).isEmpty() && - !PasswordRepository.getPasswords(dir, PasswordRepository.getRepositoryDirectory(this), getSortOrder()).isEmpty()) { + if (dir != null + && dir.exists() + && dir.isDirectory() + && !FileUtils.listFiles(dir, null, true).isEmpty() + && !PasswordRepository.getPasswords( + dir, + PasswordRepository.getRepositoryDirectory(this), + getSortOrder()) + .isEmpty()) { PasswordRepository.closeRepository(); checkLocalRepository(); return; // if not empty, just show me the passwords! @@ -676,7 +735,9 @@ public class PasswordStore extends AppCompatActivity { startActivityForResult(intent, GitActivity.REQUEST_CLONE); break; case REQUEST_CODE_SELECT_FOLDER: - Log.d(TAG, "Moving passwords to " + data.getStringExtra("SELECTED_FOLDER_PATH")); + Log.d( + TAG, + "Moving passwords to " + data.getStringExtra("SELECTED_FOLDER_PATH")); Log.d(TAG, TextUtils.join(", ", data.getStringArrayListExtra("Files"))); File target = new File(data.getStringExtra("SELECTED_FOLDER_PATH")); if (!target.isDirectory()) { @@ -684,9 +745,9 @@ public class PasswordStore extends AppCompatActivity { break; } - String repositoryPath = PasswordRepository - .getRepositoryDirectory(getApplicationContext()) - .getAbsolutePath(); + String repositoryPath = + PasswordRepository.getRepositoryDirectory(getApplicationContext()) + .getAbsolutePath(); // TODO move this to an async task for (String fileString : data.getStringArrayListExtra("Files")) { @@ -696,23 +757,33 @@ public class PasswordStore extends AppCompatActivity { continue; } - File destinationFile = new File(target.getAbsolutePath() + "/" + source.getName()); + File destinationFile = + new File(target.getAbsolutePath() + "/" + source.getName()); String basename = FilenameUtils.getBaseName(source.getAbsolutePath()); - String sourceLongName = PgpActivity.getLongName(source.getParent(), - repositoryPath, basename); + String sourceLongName = + PgpActivity.getLongName( + source.getParent(), repositoryPath, basename); - String destinationLongName = PgpActivity.getLongName(target.getAbsolutePath(), - repositoryPath, basename); + String destinationLongName = + PgpActivity.getLongName( + target.getAbsolutePath(), repositoryPath, basename); if (destinationFile.exists()) { Log.e(TAG, "Trying to move a file that already exists."); - // TODO: Add option to cancel overwrite. Will be easier once this is an async task. + // TODO: Add option to cancel overwrite. Will be easier once this is an + // async task. new MaterialAlertDialogBuilder(this) - .setTitle(getResources().getString(R.string.password_exists_title)) - .setMessage(getResources().getString(R.string.password_exists_message, - destinationLongName, sourceLongName)) + .setTitle( + getResources() + .getString(R.string.password_exists_title)) + .setMessage( + getResources() + .getString( + R.string.password_exists_message, + destinationLongName, + sourceLongName)) .setPositiveButton("Okay", null) .show(); } @@ -721,10 +792,12 @@ public class PasswordStore extends AppCompatActivity { // TODO this should show a warning to the user Log.e(TAG, "Something went wrong while moving."); } else { - commitChange(this.getResources() - .getString(R.string.git_commit_move_text, - sourceLongName, - destinationLongName)); + commitChange( + this.getResources() + .getString( + R.string.git_commit_move_text, + sourceLongName, + destinationLongName)); } } updateListAdapter(); @@ -743,63 +816,94 @@ public class PasswordStore extends AppCompatActivity { new MaterialAlertDialogBuilder(this) .setTitle(this.getResources().getString(R.string.location_dialog_title)) .setMessage(this.getResources().getString(R.string.location_dialog_text)) - .setPositiveButton(this.getResources().getString(R.string.location_hidden), (dialog, whichButton) -> { - settings.edit().putBoolean("git_external", false).apply(); + .setPositiveButton( + this.getResources().getString(R.string.location_hidden), + (dialog, whichButton) -> { + settings.edit().putBoolean("git_external", false).apply(); - switch (operation) { - case NEW_REPO_BUTTON: - initializeRepositoryInfo(); - break; - case CLONE_REPO_BUTTON: - PasswordRepository.initialize(PasswordStore.this); + 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(this.getResources().getString(R.string.location_sdcard), (dialog, whichButton) -> { - settings.edit().putBoolean("git_external", true).apply(); + Intent intent = new Intent(activity, GitActivity.class); + intent.putExtra("Operation", GitActivity.REQUEST_CLONE); + startActivityForResult(intent, GitActivity.REQUEST_CLONE); + break; + } + }) + .setNegativeButton( + this.getResources().getString(R.string.location_sdcard), + (dialog, whichButton) -> { + settings.edit().putBoolean("git_external", true).apply(); - String externalRepo = settings.getString("git_external_repo", null); + String externalRepo = settings.getString("git_external_repo", null); - if (externalRepo == null) { - Intent intent = new Intent(activity, UserPreference.class); - intent.putExtra("operation", "git_external"); - startActivityForResult(intent, operation); - } else { - new MaterialAlertDialogBuilder(activity) - .setTitle(getResources().getString(R.string.directory_selected_title)) - .setMessage(getResources().getString(R.string.directory_selected_message, externalRepo)) - .setPositiveButton(getResources().getString(R.string.use), (dialog1, which) -> { - switch (operation) { - case NEW_REPO_BUTTON: - initializeRepositoryInfo(); - break; - case CLONE_REPO_BUTTON: - PasswordRepository.initialize(PasswordStore.this); + if (externalRepo == null) { + Intent intent = new Intent(activity, UserPreference.class); + intent.putExtra("operation", "git_external"); + startActivityForResult(intent, operation); + } else { + new MaterialAlertDialogBuilder(activity) + .setTitle( + getResources() + .getString( + R.string.directory_selected_title)) + .setMessage( + getResources() + .getString( + R.string.directory_selected_message, + externalRepo)) + .setPositiveButton( + getResources().getString(R.string.use), + (dialog1, 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(getResources().getString(R.string.change), (dialog12, which) -> { - Intent intent = new Intent(activity, UserPreference.class); - intent.putExtra("operation", "git_external"); - startActivityForResult(intent, operation); - }).show(); - } - }) + Intent intent = + new Intent( + activity, + GitActivity.class); + intent.putExtra( + "Operation", + GitActivity.REQUEST_CLONE); + startActivityForResult( + intent, + GitActivity.REQUEST_CLONE); + break; + } + }) + .setNegativeButton( + getResources().getString(R.string.change), + (dialog12, which) -> { + Intent intent = + new Intent( + activity, UserPreference.class); + intent.putExtra("operation", "git_external"); + startActivityForResult(intent, operation); + }) + .show(); + } + }) .show(); } public void matchPasswordWithApp(PasswordItem item) { - String path = item.getFile().getAbsolutePath() - .replace(PasswordRepository.getRepositoryDirectory(getApplicationContext()) + "/", "") - .replace(".gpg", ""); + String path = + item.getFile() + .getAbsolutePath() + .replace( + PasswordRepository.getRepositoryDirectory(getApplicationContext()) + + "/", + "") + .replace(".gpg", ""); Intent data = new Intent(); data.putExtra("path", path); setResult(RESULT_OK, data); diff --git a/app/src/main/java/com/zeapo/pwdstore/SelectFolderActivity.kt b/app/src/main/java/com/zeapo/pwdstore/SelectFolderActivity.kt index 2eda0f73..7a55f09f 100644 --- a/app/src/main/java/com/zeapo/pwdstore/SelectFolderActivity.kt +++ b/app/src/main/java/com/zeapo/pwdstore/SelectFolderActivity.kt @@ -21,7 +21,6 @@ class SelectFolderActivity : AppCompatActivity() { val fragmentManager = supportFragmentManager val fragmentTransaction = fragmentManager.beginTransaction() - passwordList = SelectFolderFragment() val args = Bundle() args.putString("Path", PasswordRepository.getRepositoryDirectory(applicationContext)?.absolutePath) @@ -59,4 +58,4 @@ class SelectFolderActivity : AppCompatActivity() { setResult(Activity.RESULT_OK, intent) finish() } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/zeapo/pwdstore/SelectFolderFragment.java b/app/src/main/java/com/zeapo/pwdstore/SelectFolderFragment.java index b17ed746..b31a5d6f 100644 --- a/app/src/main/java/com/zeapo/pwdstore/SelectFolderFragment.java +++ b/app/src/main/java/com/zeapo/pwdstore/SelectFolderFragment.java @@ -5,7 +5,6 @@ import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; - import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.Fragment; @@ -13,21 +12,20 @@ import androidx.preference.PreferenceManager; import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; - import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.zeapo.pwdstore.utils.FolderRecyclerAdapter; import com.zeapo.pwdstore.utils.PasswordItem; import com.zeapo.pwdstore.utils.PasswordRepository; - import java.io.File; import java.util.Stack; /** * A fragment representing a list of Items. - *

- * Large screen devices (such as tablets) are supported by replacing the ListView - * with a GridView. - *

+ * + *

Large screen devices (such as tablets) are supported by replacing the ListView with a + * GridView. + * + *

*/ public class SelectFolderFragment extends Fragment { @@ -38,11 +36,10 @@ public class SelectFolderFragment extends Fragment { private OnFragmentInteractionListener mListener; /** - * Mandatory empty constructor for the fragment manager to instantiate the - * fragment (e.g. upon screen orientation changes). + * Mandatory empty constructor for the fragment manager to instantiate the fragment (e.g. upon + * screen orientation changes). */ - public SelectFolderFragment() { - } + public SelectFolderFragment() {} @Override public void onCreate(Bundle savedInstanceState) { @@ -50,17 +47,18 @@ public class SelectFolderFragment extends Fragment { String path = getArguments().getString("Path"); pathStack = new Stack<>(); - recyclerAdapter = new FolderRecyclerAdapter(mListener, - PasswordRepository.getPasswords( - new File(path), - PasswordRepository.getRepositoryDirectory(requireActivity()), getSortOrder() - ) - ); + recyclerAdapter = + new FolderRecyclerAdapter( + mListener, + PasswordRepository.getPasswords( + new File(path), + PasswordRepository.getRepositoryDirectory(requireActivity()), + getSortOrder())); } @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + public View onCreateView( + @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.password_recycler_view, container, false); // use a linear layout manager @@ -68,7 +66,8 @@ public class SelectFolderFragment extends Fragment { recyclerView.setLayoutManager(new LinearLayoutManager(requireContext())); // use divider - recyclerView.addItemDecoration(new DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL)); + recyclerView.addItemDecoration( + new DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL)); // Set the adapter recyclerView.setAdapter(recyclerAdapter); @@ -83,21 +82,28 @@ public class SelectFolderFragment extends Fragment { public void onAttach(final Context context) { super.onAttach(context); try { - mListener = item -> { - if (item.getType() == PasswordItem.TYPE_CATEGORY) { - //push the category were we're going - pathStack.push(item.getFile()); + mListener = + item -> { + if (item.getType() == PasswordItem.TYPE_CATEGORY) { + // push the category were we're going + pathStack.push(item.getFile()); - recyclerView.scrollToPosition(0); - recyclerAdapter.clear(); - recyclerAdapter.addAll(PasswordRepository.getPasswords(item.getFile(), PasswordRepository.getRepositoryDirectory(context), getSortOrder())); + recyclerView.scrollToPosition(0); + recyclerAdapter.clear(); + recyclerAdapter.addAll( + PasswordRepository.getPasswords( + item.getFile(), + PasswordRepository.getRepositoryDirectory(context), + getSortOrder())); - ((AppCompatActivity) requireActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true); - } - }; + ((AppCompatActivity) requireActivity()) + .getSupportActionBar() + .setDisplayHomeAsUpEnabled(true); + } + }; } catch (ClassCastException e) { - throw new ClassCastException(context.toString() - + " must implement OnFragmentInteractionListener"); + throw new ClassCastException( + context.toString() + " must implement OnFragmentInteractionListener"); } } @@ -107,14 +113,13 @@ public class SelectFolderFragment extends Fragment { * @return the current directory */ public File getCurrentDir() { - if (pathStack.isEmpty()) - return PasswordRepository.getRepositoryDirectory(requireContext()); - else - return pathStack.peek(); + if (pathStack.isEmpty()) return PasswordRepository.getRepositoryDirectory(requireContext()); + else return pathStack.peek(); } private PasswordRepository.PasswordSortOrder getSortOrder() { - return PasswordRepository.PasswordSortOrder.getSortOrder(PreferenceManager.getDefaultSharedPreferences(requireContext())); + return PasswordRepository.PasswordSortOrder.getSortOrder( + PreferenceManager.getDefaultSharedPreferences(requireContext())); } public interface OnFragmentInteractionListener { diff --git a/app/src/main/java/com/zeapo/pwdstore/SshKeyGen.java b/app/src/main/java/com/zeapo/pwdstore/SshKeyGen.java index 77fbcf27..3055d41f 100644 --- a/app/src/main/java/com/zeapo/pwdstore/SshKeyGen.java +++ b/app/src/main/java/com/zeapo/pwdstore/SshKeyGen.java @@ -21,7 +21,6 @@ import android.widget.CheckBox; import android.widget.EditText; import android.widget.Spinner; import android.widget.Toast; - import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; @@ -30,18 +29,15 @@ import androidx.fragment.app.DialogFragment; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; import androidx.preference.PreferenceManager; - import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.textfield.TextInputEditText; import com.jcraft.jsch.JSch; import com.jcraft.jsch.KeyPair; - -import org.apache.commons.io.FileUtils; - import java.io.File; import java.io.FileOutputStream; import java.lang.ref.WeakReference; import java.nio.charset.StandardCharsets; +import org.apache.commons.io.FileUtils; public class SshKeyGen extends AppCompatActivity { @@ -49,14 +45,15 @@ public class SshKeyGen extends AppCompatActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - if (getSupportActionBar() != null) - getSupportActionBar().setDisplayHomeAsUpEnabled(true); + if (getSupportActionBar() != null) getSupportActionBar().setDisplayHomeAsUpEnabled(true); setTitle("Generate SSH Key"); if (savedInstanceState == null) { - getSupportFragmentManager().beginTransaction() - .replace(android.R.id.content, new SshKeyGenFragment()).commit(); + getSupportFragmentManager() + .beginTransaction() + .replace(android.R.id.content, new SshKeyGenFragment()) + .commit(); } } @@ -64,45 +61,56 @@ public class SshKeyGen extends AppCompatActivity { // private and public key, then replaces the SshKeyGenFragment with a // ShowSshKeyFragment which displays the public key. public void generate(View view) { - String length = Integer.toString((Integer) ((Spinner) findViewById(R.id.length)).getSelectedItem()); + String length = + Integer.toString((Integer) ((Spinner) findViewById(R.id.length)).getSelectedItem()); String passphrase = ((EditText) findViewById(R.id.passphrase)).getText().toString(); String comment = ((EditText) findViewById(R.id.comment)).getText().toString(); new KeyGenerateTask(this).execute(length, passphrase, comment); - InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + InputMethodManager imm = + (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(view.getWindowToken(), 0); } // SSH key generation UI public static class SshKeyGenFragment extends Fragment { - public SshKeyGenFragment() { - } + public SshKeyGenFragment() {} @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final View v = inflater.inflate(R.layout.fragment_ssh_keygen, container, false); - Typeface monoTypeface = Typeface.createFromAsset(requireContext().getAssets(), "fonts/sourcecodepro.ttf"); + Typeface monoTypeface = + Typeface.createFromAsset( + requireContext().getAssets(), "fonts/sourcecodepro.ttf"); Spinner spinner = v.findViewById(R.id.length); - Integer[] lengths = new Integer[]{2048, 4096}; - ArrayAdapter adapter = new ArrayAdapter<>(requireContext(), - android.R.layout.simple_spinner_dropdown_item, lengths); + Integer[] lengths = new Integer[] {2048, 4096}; + ArrayAdapter adapter = + new ArrayAdapter<>( + requireContext(), + android.R.layout.simple_spinner_dropdown_item, + lengths); spinner.setAdapter(adapter); ((TextInputEditText) v.findViewById(R.id.passphrase)).setTypeface(monoTypeface); final CheckBox checkbox = v.findViewById(R.id.show_passphrase); - checkbox.setOnCheckedChangeListener((buttonView, isChecked) -> { - final TextInputEditText editText = v.findViewById(R.id.passphrase); - final int selection = editText.getSelectionEnd(); - if (isChecked) { - editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD); - } else { - editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); - } - editText.setSelection(selection); - }); + checkbox.setOnCheckedChangeListener( + (buttonView, isChecked) -> { + final TextInputEditText editText = v.findViewById(R.id.passphrase); + final int selection = editText.getSelectionEnd(); + if (isChecked) { + editText.setInputType( + InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD); + } else { + editText.setInputType( + InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_VARIATION_PASSWORD); + } + editText.setSelection(selection); + }); return v; } @@ -110,16 +118,17 @@ public class SshKeyGen extends AppCompatActivity { // Displays the generated public key .ssh_key.pub public static class ShowSshKeyFragment extends DialogFragment { - public ShowSshKeyFragment() { - } + public ShowSshKeyFragment() {} @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final FragmentActivity activity = requireActivity(); - final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireContext()); + final MaterialAlertDialogBuilder builder = + new MaterialAlertDialogBuilder(requireContext()); LayoutInflater inflater = activity.getLayoutInflater(); - @SuppressLint("InflateParams") final View v = inflater.inflate(R.layout.fragment_show_ssh_key, null); + @SuppressLint("InflateParams") + final View v = inflater.inflate(R.layout.fragment_show_ssh_key, null); builder.setView(v); AppCompatTextView textView = v.findViewById(R.id.public_key); @@ -131,27 +140,35 @@ public class SshKeyGen extends AppCompatActivity { e.printStackTrace(); } - builder.setPositiveButton(getResources().getString(R.string.dialog_ok), (dialog, which) -> { - if (activity instanceof SshKeyGen) - activity.finish(); - }); + builder.setPositiveButton( + getResources().getString(R.string.dialog_ok), + (dialog, which) -> { + if (activity instanceof SshKeyGen) activity.finish(); + }); - builder.setNegativeButton(getResources().getString(R.string.dialog_cancel), (dialog, which) -> { - - }); + builder.setNegativeButton( + getResources().getString(R.string.dialog_cancel), (dialog, which) -> {}); builder.setNeutralButton(getResources().getString(R.string.ssh_keygen_copy), null); final AlertDialog ad = builder.setTitle("Your public key").create(); - ad.setOnShowListener(dialog -> { - Button b = ad.getButton(AlertDialog.BUTTON_NEUTRAL); - b.setOnClickListener(v1 -> { - AppCompatTextView textView1 = getDialog().findViewById(R.id.public_key); - ClipboardManager clipboard = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE); - ClipData clip = ClipData.newPlainText("public key", textView1.getText().toString()); - clipboard.setPrimaryClip(clip); - }); - }); + ad.setOnShowListener( + dialog -> { + Button b = ad.getButton(AlertDialog.BUTTON_NEUTRAL); + b.setOnClickListener( + v1 -> { + AppCompatTextView textView1 = + getDialog().findViewById(R.id.public_key); + ClipboardManager clipboard = + (ClipboardManager) + activity.getSystemService( + Context.CLIPBOARD_SERVICE); + ClipData clip = + ClipData.newPlainText( + "public key", textView1.getText().toString()); + clipboard.setPrimaryClip(clip); + }); + }); return ad; } } @@ -206,17 +223,26 @@ public class SshKeyGen extends AppCompatActivity { Toast.makeText(weakReference.get(), "SSH-key generated", Toast.LENGTH_LONG).show(); DialogFragment df = new ShowSshKeyFragment(); df.show(weakReference.get().getSupportFragmentManager(), "public_key"); - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(weakReference.get()); + SharedPreferences prefs = + PreferenceManager.getDefaultSharedPreferences(weakReference.get()); SharedPreferences.Editor editor = prefs.edit(); editor.putBoolean("use_generated_key", true); editor.apply(); } else { new MaterialAlertDialogBuilder(weakReference.get()) .setTitle("Error while trying to generate the ssh-key") - .setMessage(weakReference.get().getResources().getString(R.string.ssh_key_error_dialog_text) + e.getMessage()) - .setPositiveButton(weakReference.get().getResources().getString(R.string.dialog_ok), (dialogInterface, i) -> { - // pass - }).show(); + .setMessage( + weakReference + .get() + .getResources() + .getString(R.string.ssh_key_error_dialog_text) + + e.getMessage()) + .setPositiveButton( + weakReference.get().getResources().getString(R.string.dialog_ok), + (dialogInterface, i) -> { + // pass + }) + .show(); } } } diff --git a/app/src/main/java/com/zeapo/pwdstore/ToCloneOrNot.kt b/app/src/main/java/com/zeapo/pwdstore/ToCloneOrNot.kt index 4b1fdf55..c84a01c0 100644 --- a/app/src/main/java/com/zeapo/pwdstore/ToCloneOrNot.kt +++ b/app/src/main/java/com/zeapo/pwdstore/ToCloneOrNot.kt @@ -9,8 +9,9 @@ import androidx.fragment.app.Fragment class ToCloneOrNot : Fragment() { override fun onCreateView( - inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? ): View? { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_to_clone_or_not, container, false) diff --git a/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt b/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt index 48edf141..c2021575 100644 --- a/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt +++ b/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt @@ -72,7 +72,6 @@ class UserPreference : AppCompatActivity() { val externalGitRepositoryPreference = findPreference("git_external") val selectExternalGitRepositoryPreference = findPreference("pref_select_external") - // Crypto preferences val keyPreference = findPreference("openpgp_key_id_pref") @@ -393,8 +392,6 @@ class UserPreference : AppCompatActivity() { sshKeyInputStream.close() sshKeyOutputSteam.close() - - } else { Toast.makeText(this, getString(R.string.ssh_key_does_not_exist), Toast.LENGTH_LONG).show() } @@ -413,8 +410,9 @@ class UserPreference : AppCompatActivity() { } override fun onActivityResult( - requestCode: Int, resultCode: Int, - data: Intent? + requestCode: Int, + resultCode: Int, + data: Intent? ) { if (resultCode == Activity.RESULT_OK) { if (data == null) { @@ -452,7 +450,6 @@ class UserPreference : AppCompatActivity() { } } EDIT_GIT_INFO -> { - } SELECT_GIT_DIRECTORY -> { val uri = data.data @@ -527,7 +524,6 @@ class UserPreference : AppCompatActivity() { if (passDir != null) { copyDirToDir(sourcePassDir, passDir) } - } /** diff --git a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillActivity.kt b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillActivity.kt index 48b72c38..c37e253a 100644 --- a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillActivity.kt +++ b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillActivity.kt @@ -28,7 +28,6 @@ class AutofillActivity : AppCompatActivity() { } catch (e: IntentSender.SendIntentException) { Log.e(AutofillService.Constants.TAG, "SendIntentException", e) } - } else if (extras != null && extras.containsKey("pick")) { val intent = Intent(applicationContext, PasswordStore::class.java) intent.putExtra("matchWith", true) @@ -41,10 +40,10 @@ class AutofillActivity : AppCompatActivity() { } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - finish() // go back to the password field app + finish() // go back to the password field app when (requestCode) { REQUEST_CODE_DECRYPT_AND_VERIFY -> if (resultCode == RESULT_OK) { - AutofillService.instance?.setResultData(data!!) // report the result to service + AutofillService.instance?.setResultData(data!!) // report the result to service } REQUEST_CODE_PICK -> if (resultCode == RESULT_OK) { AutofillService.instance?.setPickedPassword(data!!.getStringExtra("path")) diff --git a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillFragment.kt b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillFragment.kt index 04b8d7ef..55a84d19 100644 --- a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillFragment.kt +++ b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillFragment.kt @@ -26,7 +26,6 @@ import com.zeapo.pwdstore.R import com.zeapo.pwdstore.utils.resolveAttribute import com.zeapo.pwdstore.utils.splitLines - class AutofillFragment : DialogFragment() { private var adapter: ArrayAdapter? = null private var isWeb: Boolean = false @@ -116,8 +115,8 @@ class AutofillFragment : DialogFragment() { val editor = prefs.edit() if (isWeb) { builder.setNeutralButton(R.string.autofill_apps_delete) { _, _ -> - if (callingActivity.recyclerAdapter != null - && packageName != null && packageName != "") { + if (callingActivity.recyclerAdapter != null && + packageName != null && packageName != "") { editor.remove(packageName) callingActivity.recyclerAdapter?.removeWebsite(packageName) editor.apply() diff --git a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillPreferenceActivity.kt b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillPreferenceActivity.kt index 43f2f33f..cb647c04 100644 --- a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillPreferenceActivity.kt +++ b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillPreferenceActivity.kt @@ -136,7 +136,6 @@ class AutofillPreferenceActivity : AppCompatActivity() { } catch (e: PackageManager.NameNotFoundException) { allApps.add(AutofillRecyclerAdapter.AppInfo(key, key, true, null)) } - } weakReference.get()?.recyclerAdapter = AutofillRecyclerAdapter(allApps, weakReference.get()!!) return null diff --git a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillRecyclerAdapter.kt b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillRecyclerAdapter.kt index 7cd7fcb7..6ebd0977 100644 --- a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillRecyclerAdapter.kt +++ b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillRecyclerAdapter.kt @@ -18,8 +18,8 @@ import java.util.ArrayList import java.util.Locale internal class AutofillRecyclerAdapter( - allApps: List, - private val activity: AutofillPreferenceActivity + allApps: List, + private val activity: AutofillPreferenceActivity ) : RecyclerView.Adapter() { private val apps: SortedList @@ -86,8 +86,8 @@ internal class AutofillRecyclerAdapter( holder.secondary.setText(R.string.autofill_apps_match) holder.secondary.append(" " + preference!!.splitLines()[0]) if (preference.trim { it <= ' ' }.splitLines().size - 1 > 0) { - holder.secondary.append(" and " - + (preference.trim { it <= ' ' }.splitLines().size - 1) + " more") + holder.secondary.append(" and " + + (preference.trim { it <= ' ' }.splitLines().size - 1) + " more") } } } @@ -164,6 +164,5 @@ internal class AutofillRecyclerAdapter( override fun onClick(v: View) { activity.showDialog(packageName, appName, isWeb) } - } } diff --git a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillService.kt b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillService.kt index d9f42b00..796b4518 100644 --- a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillService.kt +++ b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillService.kt @@ -85,17 +85,17 @@ class AutofillService : AccessibilityService() { } // if returning to the source app from a successful AutofillActivity - if (event.eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED - && event.packageName != null && event.packageName == packageName - && resultData != null) { + if (event.eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED && + event.packageName != null && event.packageName == packageName && + resultData != null) { bindDecryptAndVerify() } // look for webView and trigger accessibility events if window changes // or if page changes in chrome - if (event.eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED || (event.eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED - && event.packageName != null - && (event.packageName == "com.android.chrome" || event.packageName == "com.android.browser"))) { + if (event.eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED || (event.eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED && + event.packageName != null && + (event.packageName == "com.android.chrome" || event.packageName == "com.android.browser"))) { // there is a chance for getRootInActiveWindow() to return null at any time. save it. try { val root = rootInActiveWindow @@ -116,23 +116,20 @@ class AutofillService : AccessibilityService() { webViewURL = URL("http://" + node.text.toString()).host } catch (ignored: MalformedURLException) { } - } } - } } } catch (e: Exception) { // sadly we were unable to access the data we wanted return } - } // nothing to do if field is keychain app or system ui - if (event.eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED - || event.packageName != null && event.packageName == "org.sufficientlysecure.keychain" - || event.packageName != null && event.packageName == "com.android.systemui") { + if (event.eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED || + event.packageName != null && event.packageName == "org.sufficientlysecure.keychain" || + event.packageName != null && event.packageName == "com.android.systemui") { dismissDialog(event) return } @@ -281,8 +278,8 @@ class AutofillService : AccessibilityService() { // means use default, so ignore it. val value = prefs.getString(key, null) val keyLowerCase = key.toLowerCase(Locale.ROOT) - if (value != null && value != "" - && (webViewUrlLowerCase.contains(keyLowerCase) || keyLowerCase.contains(webViewUrlLowerCase))) { + if (value != null && value != "" && + (webViewUrlLowerCase.contains(keyLowerCase) || keyLowerCase.contains(webViewUrlLowerCase))) { preference = value settingsURL = key } @@ -397,7 +394,7 @@ class AutofillService : AccessibilityService() { dialog = null } builder.setNeutralButton("Settings") { _, _ -> - //TODO make icon? gear? + // TODO make icon? gear? // the user will have to return to the app themselves. val intent = Intent(this@AutofillService, AutofillPreferenceActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) @@ -426,7 +423,7 @@ class AutofillService : AccessibilityService() { startActivity(intent) } else -> { - lastWhichItem-- // will add one element to items, so lastWhichItem=items.size()+1 + lastWhichItem-- // will add one element to items, so lastWhichItem=items.size()+1 val intent = Intent(this@AutofillService, AutofillActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) intent.putExtra("pickMatchWith", true) @@ -512,7 +509,6 @@ class AutofillService : AccessibilityService() { } catch (e: UnsupportedEncodingException) { Log.e(Constants.TAG, "UnsupportedEncodingException", e) } - } OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED -> { Log.i("PgpHandler", "RESULT_CODE_USER_INTERACTION_REQUIRED") diff --git a/app/src/main/java/com/zeapo/pwdstore/crypto/PgpActivity.kt b/app/src/main/java/com/zeapo/pwdstore/crypto/PgpActivity.kt index 81fef413..523fc6a6 100644 --- a/app/src/main/java/com/zeapo/pwdstore/crypto/PgpActivity.kt +++ b/app/src/main/java/com/zeapo/pwdstore/crypto/PgpActivity.kt @@ -404,7 +404,6 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound { RESULT_CODE_USER_INTERACTION_REQUIRED -> handleUserInteractionRequest(result, REQUEST_DECRYPT) RESULT_CODE_ERROR -> handleError(result) } - } } @@ -474,7 +473,6 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound { } RESULT_CODE_ERROR -> handleError(result) } - } } @@ -669,7 +667,6 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound { } else { showToast(this.resources.getString(R.string.clipboard_password_no_clear_toast_text)) } - } private fun copyUsernameToClipBoard(username: String) { @@ -697,7 +694,7 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound { sendIntent, resources.getText(R.string.send_plaintext_password_to) ) - )//Always show a picker to give the user a chance to cancel + ) // Always show a picker to give the user a chance to cancel } private fun setTimer() { @@ -872,4 +869,3 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound { } } } - diff --git a/app/src/main/java/com/zeapo/pwdstore/git/CloneOperation.kt b/app/src/main/java/com/zeapo/pwdstore/git/CloneOperation.kt index 8489eb1d..53fbf77a 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/CloneOperation.kt +++ b/app/src/main/java/com/zeapo/pwdstore/git/CloneOperation.kt @@ -10,7 +10,7 @@ import java.io.File /** * Creates a new clone operation * - * @param fileDir the git working tree directory + * @param fileDir the git working tree directory * @param callingActivity the calling activity */ class CloneOperation(fileDir: File, callingActivity: Activity) : GitOperation(fileDir, callingActivity) { @@ -44,8 +44,8 @@ class CloneOperation(fileDir: File, callingActivity: Activity) : GitOperation(fi /** * sets the authentication for the ssh-key scheme * - * @param sshKey the ssh-key file - * @param username the username + * @param sshKey the ssh-key file + * @param username the username * @param passphrase the passphrase * @return the current object */ @@ -62,10 +62,10 @@ class CloneOperation(fileDir: File, callingActivity: Activity) : GitOperation(fi override fun onError(errorMessage: String) { MaterialAlertDialogBuilder(callingActivity) .setTitle(callingActivity.resources.getString(R.string.jgit_error_dialog_title)) - .setMessage("Error occured during the clone operation, " - + callingActivity.resources.getString(R.string.jgit_error_dialog_text) - + errorMessage - + "\nPlease check the FAQ for possible reasons why this error might occur.") + .setMessage("Error occured during the clone operation, " + + callingActivity.resources.getString(R.string.jgit_error_dialog_text) + + errorMessage + + "\nPlease check the FAQ for possible reasons why this error might occur.") .setPositiveButton(callingActivity.resources.getString(R.string.dialog_ok)) { _, _ -> } .show() } diff --git a/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.kt b/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.kt index 11cc4c1b..403a4e12 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.kt +++ b/app/src/main/java/com/zeapo/pwdstore/git/GitActivity.kt @@ -73,7 +73,6 @@ open class GitActivity : AppCompatActivity() { } override fun onNothingSelected(adapterView: AdapterView<*>) { - } } @@ -107,7 +106,6 @@ open class GitActivity : AppCompatActivity() { } override fun onNothingSelected(adapterView: AdapterView<*>) { - } } @@ -218,10 +216,10 @@ open class GitActivity : AppCompatActivity() { if (uri != null) { when (protocol) { "ssh://" -> { - var hostname = (serverUser.text.toString() - + "@" + - serverUrl.text.toString().trim { it <= ' ' } - + ":") + var hostname = (serverUser.text.toString() + + "@" + + serverUrl.text.toString().trim { it <= ' ' } + + ":") if (serverPort.text.toString() == "22") { hostname += serverPath.text.toString() @@ -258,7 +256,6 @@ open class GitActivity : AppCompatActivity() { else -> { } } - } } @@ -420,7 +417,6 @@ open class GitActivity : AppCompatActivity() { } catch (e: Exception) { // ignore } - } } @@ -477,8 +473,8 @@ open class GitActivity : AppCompatActivity() { return // Warn if non-empty folder unless it's a just-initialized store that has just a .git folder - if (localDir.exists() && localDir.listFiles()!!.isNotEmpty() - && !(localDir.listFiles()!!.size == 1 && localDir.listFiles()!![0].name == ".git")) { + if (localDir.exists() && localDir.listFiles()!!.isNotEmpty() && + !(localDir.listFiles()!!.size == 1 && localDir.listFiles()!![0].name == ".git")) { MaterialAlertDialogBuilder(this) .setTitle(R.string.dialog_delete_title) .setMessage(resources.getString(R.string.dialog_delete_msg) + " " + localDir.toString()) @@ -489,7 +485,7 @@ open class GitActivity : AppCompatActivity() { FileUtils.deleteDirectory(localDir) launchGitOperation(REQUEST_CLONE) } catch (e: IOException) { - //TODO Handle the exception correctly if we are unable to delete the directory... + // TODO Handle the exception correctly if we are unable to delete the directory... e.printStackTrace() MaterialAlertDialogBuilder(this).setMessage(e.message).show() } @@ -509,11 +505,10 @@ open class GitActivity : AppCompatActivity() { e.printStackTrace() MaterialAlertDialogBuilder(this).setMessage(e.message).show() } - } } catch (e: Exception) { - //This is what happens when jgit fails :( - //TODO Handle the diffent cases of exceptions + // This is what happens when jgit fails :( + // TODO Handle the diffent cases of exceptions e.printStackTrace() MaterialAlertDialogBuilder(this).setMessage(e.message).show() } @@ -612,11 +607,13 @@ open class GitActivity : AppCompatActivity() { e.printStackTrace() MaterialAlertDialogBuilder(this).setMessage(e.message).show() } - } - override fun onActivityResult(requestCode: Int, resultCode: Int, - data: Intent?) { + override fun onActivityResult( + requestCode: Int, + resultCode: Int, + data: Intent? + ) { // In addition to the pre-operation-launch series of intents for OpenKeychain auth // that will pass through here and back to launchGitOperation, there is one diff --git a/app/src/main/java/com/zeapo/pwdstore/git/GitAsyncTask.java b/app/src/main/java/com/zeapo/pwdstore/git/GitAsyncTask.java index 0f0cf508..3dd1cd94 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/GitAsyncTask.java +++ b/app/src/main/java/com/zeapo/pwdstore/git/GitAsyncTask.java @@ -3,10 +3,9 @@ package com.zeapo.pwdstore.git; import android.app.Activity; import android.app.ProgressDialog; import android.os.AsyncTask; - import com.zeapo.pwdstore.PasswordStore; import com.zeapo.pwdstore.R; - +import java.lang.ref.WeakReference; import org.eclipse.jgit.api.CommitCommand; import org.eclipse.jgit.api.GitCommand; import org.eclipse.jgit.api.PullCommand; @@ -17,9 +16,6 @@ import org.eclipse.jgit.api.StatusCommand; import org.eclipse.jgit.transport.PushResult; import org.eclipse.jgit.transport.RemoteRefUpdate; -import java.lang.ref.WeakReference; - - public class GitAsyncTask extends AsyncTask { private WeakReference activityWeakReference; private boolean finishOnEnd; @@ -27,7 +23,11 @@ public class GitAsyncTask extends AsyncTask { private ProgressDialog dialog; private GitOperation operation; - public GitAsyncTask(Activity activity, boolean finishOnEnd, boolean refreshListOnEnd, GitOperation operation) { + public GitAsyncTask( + Activity activity, + boolean finishOnEnd, + boolean refreshListOnEnd, + GitOperation operation) { this.activityWeakReference = new WeakReference<>(activity); this.finishOnEnd = finishOnEnd; this.refreshListOnEnd = refreshListOnEnd; @@ -41,7 +41,8 @@ public class GitAsyncTask extends AsyncTask { } protected void onPreExecute() { - this.dialog.setMessage(getActivity().getResources().getString(R.string.running_dialog_text)); + this.dialog.setMessage( + getActivity().getResources().getString(R.string.running_dialog_text)); this.dialog.setCancelable(false); this.dialog.show(); } @@ -58,8 +59,7 @@ public class GitAsyncTask extends AsyncTask { nbChanges = status.getChanged().size() + status.getMissing().size(); } else if (command instanceof CommitCommand) { // the previous status will eventually be used to avoid a commit - if (nbChanges == null || nbChanges > 0) - command.call(); + if (nbChanges == null || nbChanges > 0) command.call(); } else if (command instanceof PullCommand) { final PullResult result = ((PullCommand) command).call(); final RebaseResult rr = result.getRebaseResult(); @@ -79,12 +79,14 @@ public class GitAsyncTask extends AsyncTask { case REJECTED_REMOTE_CHANGED: case NON_EXISTING: case NOT_ATTEMPTED: - return activity.getString(R.string.git_push_generic_error) + rru.getStatus().name(); + return activity.getString(R.string.git_push_generic_error) + + rru.getStatus().name(); case REJECTED_OTHER_REASON: if ("non-fast-forward".equals(rru.getMessage())) { return activity.getString(R.string.git_push_other_error); } else { - return activity.getString(R.string.git_push_generic_error) + rru.getMessage(); + return activity.getString(R.string.git_push_generic_error) + + rru.getMessage(); } default: break; @@ -111,8 +113,7 @@ public class GitAsyncTask extends AsyncTask { // ignore } - if (result == null) - result = "Unexpected error"; + if (result == null) result = "Unexpected error"; if (!result.isEmpty()) { this.operation.onError(result); diff --git a/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.kt b/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.kt index 4ab90e96..e155bdd3 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.kt +++ b/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.kt @@ -29,7 +29,7 @@ import java.io.File /** * Creates a new git operation * - * @param fileDir the git working tree directory + * @param fileDir the git working tree directory * @param callingActivity the calling activity */ abstract class GitOperation(fileDir: File, internal val callingActivity: Activity) { @@ -54,8 +54,8 @@ abstract class GitOperation(fileDir: File, internal val callingActivity: Activit /** * Sets the authentication using ssh-key scheme * - * @param sshKey the ssh-key file - * @param username the username + * @param sshKey the ssh-key file + * @param username the username * @param passphrase the passphrase * @return the current object */ @@ -87,14 +87,16 @@ abstract class GitOperation(fileDir: File, internal val callingActivity: Activit * Executes the GitCommand in an async task after creating the authentication * * @param connectionMode the server-connection mode - * @param username the username - * @param sshKey the ssh-key file to use in ssh-key connection mode - * @param identity the api identity to use for auth in OpenKeychain connection mode + * @param username the username + * @param sshKey the ssh-key file to use in ssh-key connection mode + * @param identity the api identity to use for auth in OpenKeychain connection mode */ - fun executeAfterAuthentication(connectionMode: String, - username: String, - sshKey: File?, - identity: SshApiSessionFactory.ApiIdentity?) { + fun executeAfterAuthentication( + connectionMode: String, + username: String, + sshKey: File?, + identity: SshApiSessionFactory.ApiIdentity? + ) { executeAfterAuthentication(connectionMode, username, sshKey, identity, false) } @@ -102,16 +104,18 @@ abstract class GitOperation(fileDir: File, internal val callingActivity: Activit * Executes the GitCommand in an async task after creating the authentication * * @param connectionMode the server-connection mode - * @param username the username - * @param sshKey the ssh-key file to use in ssh-key connection mode - * @param identity the api identity to use for auth in OpenKeychain connection mode - * @param showError show the passphrase edit text in red + * @param username the username + * @param sshKey the ssh-key file to use in ssh-key connection mode + * @param identity the api identity to use for auth in OpenKeychain connection mode + * @param showError show the passphrase edit text in red */ - private fun executeAfterAuthentication(connectionMode: String, - username: String, - sshKey: File?, - identity: SshApiSessionFactory.ApiIdentity?, - showError: Boolean) { + private fun executeAfterAuthentication( + connectionMode: String, + username: String, + sshKey: File?, + identity: SshApiSessionFactory.ApiIdentity?, + showError: Boolean + ) { if (connectionMode.equals("ssh-key", ignoreCase = true)) { if (sshKey == null || !sshKey.exists()) { MaterialAlertDialogBuilder(callingActivity) @@ -199,7 +203,6 @@ abstract class GitOperation(fileDir: File, internal val callingActivity: Activit .setPositiveButton("Ok") { _, _ -> callingActivity.finish() } .show() } - } } else if (connectionMode.equals("OpenKeychain", ignoreCase = true)) { setAuthentication(username, identity).execute() @@ -216,7 +219,6 @@ abstract class GitOperation(fileDir: File, internal val callingActivity: Activit .setPositiveButton(callingActivity.resources.getString(R.string.dialog_ok)) { _, _ -> // authenticate using the user/pwd and then execute the command setAuthentication(username, password.text.toString()).execute() - } .setNegativeButton(callingActivity.resources.getString(R.string.dialog_cancel)) { _, _ -> callingActivity.finish() diff --git a/app/src/main/java/com/zeapo/pwdstore/git/PullOperation.kt b/app/src/main/java/com/zeapo/pwdstore/git/PullOperation.kt index 90c46878..1ec8ec92 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/PullOperation.kt +++ b/app/src/main/java/com/zeapo/pwdstore/git/PullOperation.kt @@ -10,7 +10,7 @@ import java.io.File /** * Creates a new git operation * - * @param fileDir the git working tree directory + * @param fileDir the git working tree directory * @param callingActivity the calling activity */ class PullOperation(fileDir: File, callingActivity: Activity) : GitOperation(fileDir, callingActivity) { @@ -36,10 +36,10 @@ class PullOperation(fileDir: File, callingActivity: Activity) : GitOperation(fil override fun onError(errorMessage: String) { MaterialAlertDialogBuilder(callingActivity) .setTitle(callingActivity.resources.getString(R.string.jgit_error_dialog_title)) - .setMessage("Error occured during the pull operation, " - + callingActivity.resources.getString(R.string.jgit_error_dialog_text) - + errorMessage - + "\nPlease check the FAQ for possible reasons why this error might occur.") + .setMessage("Error occured during the pull operation, " + + callingActivity.resources.getString(R.string.jgit_error_dialog_text) + + errorMessage + + "\nPlease check the FAQ for possible reasons why this error might occur.") .setPositiveButton(callingActivity.resources.getString(R.string.dialog_ok)) { _, _ -> callingActivity.finish() } .show() } diff --git a/app/src/main/java/com/zeapo/pwdstore/git/PushOperation.kt b/app/src/main/java/com/zeapo/pwdstore/git/PushOperation.kt index 0015c4d1..55feadc3 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/PushOperation.kt +++ b/app/src/main/java/com/zeapo/pwdstore/git/PushOperation.kt @@ -10,7 +10,7 @@ import java.io.File /** * Creates a new git operation * - * @param fileDir the git working tree directory + * @param fileDir the git working tree directory * @param callingActivity the calling activity */ class PushOperation(fileDir: File, callingActivity: Activity) : GitOperation(fileDir, callingActivity) { diff --git a/app/src/main/java/com/zeapo/pwdstore/git/ResetToRemoteOperation.kt b/app/src/main/java/com/zeapo/pwdstore/git/ResetToRemoteOperation.kt index 1bab0981..b988d0af 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/ResetToRemoteOperation.kt +++ b/app/src/main/java/com/zeapo/pwdstore/git/ResetToRemoteOperation.kt @@ -12,7 +12,7 @@ import java.io.File /** * Creates a new git operation * - * @param fileDir the git working tree directory + * @param fileDir the git working tree directory * @param callingActivity the calling activity */ class ResetToRemoteOperation(fileDir: File, callingActivity: Activity) : GitOperation(fileDir, callingActivity) { @@ -42,10 +42,10 @@ class ResetToRemoteOperation(fileDir: File, callingActivity: Activity) : GitOper override fun onError(errorMessage: String) { MaterialAlertDialogBuilder(callingActivity) .setTitle(callingActivity.resources.getString(R.string.jgit_error_dialog_title)) - .setMessage("Error occured during the sync operation, " - + "\nPlease check the FAQ for possible reasons why this error might occur." - + callingActivity.resources.getString(R.string.jgit_error_dialog_text) - + errorMessage) + .setMessage("Error occured during the sync operation, " + + "\nPlease check the FAQ for possible reasons why this error might occur." + + callingActivity.resources.getString(R.string.jgit_error_dialog_text) + + errorMessage) .setPositiveButton(callingActivity.resources.getString(R.string.dialog_ok)) { _, _ -> } .show() } diff --git a/app/src/main/java/com/zeapo/pwdstore/git/SyncOperation.kt b/app/src/main/java/com/zeapo/pwdstore/git/SyncOperation.kt index a0fd52b2..a795921d 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/SyncOperation.kt +++ b/app/src/main/java/com/zeapo/pwdstore/git/SyncOperation.kt @@ -14,7 +14,7 @@ import java.io.File /** * Creates a new git operation * - * @param fileDir the git working tree directory + * @param fileDir the git working tree directory * @param callingActivity the calling activity */ class SyncOperation(fileDir: File, callingActivity: Activity) : GitOperation(fileDir, callingActivity) { @@ -50,10 +50,10 @@ class SyncOperation(fileDir: File, callingActivity: Activity) : GitOperation(fil override fun onError(errorMessage: String) { MaterialAlertDialogBuilder(callingActivity) .setTitle(callingActivity.resources.getString(R.string.jgit_error_dialog_title)) - .setMessage("Error occured during the sync operation, " - + "\nPlease check the FAQ for possible reasons why this error might occur." - + callingActivity.resources.getString(R.string.jgit_error_dialog_text) - + errorMessage) + .setMessage("Error occured during the sync operation, " + + "\nPlease check the FAQ for possible reasons why this error might occur." + + callingActivity.resources.getString(R.string.jgit_error_dialog_text) + + errorMessage) .setPositiveButton(callingActivity.resources.getString(R.string.dialog_ok)) { _, _ -> callingActivity.finish() } .show() } diff --git a/app/src/main/java/com/zeapo/pwdstore/git/config/GitConfigSessionFactory.kt b/app/src/main/java/com/zeapo/pwdstore/git/config/GitConfigSessionFactory.kt index 6485a73c..2ac11ab4 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/config/GitConfigSessionFactory.kt +++ b/app/src/main/java/com/zeapo/pwdstore/git/config/GitConfigSessionFactory.kt @@ -19,4 +19,4 @@ open class GitConfigSessionFactory : JschConfigSessionFactory() { jsch.removeAllIdentity() return jsch } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/zeapo/pwdstore/git/config/SshApiSessionFactory.java b/app/src/main/java/com/zeapo/pwdstore/git/config/SshApiSessionFactory.java index dbb5b7b1..7b2c062f 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/config/SshApiSessionFactory.java +++ b/app/src/main/java/com/zeapo/pwdstore/git/config/SshApiSessionFactory.java @@ -4,9 +4,7 @@ import android.app.Activity; import android.app.PendingIntent; import android.content.Intent; import android.content.IntentSender; - import androidx.annotation.NonNull; - import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.jcraft.jsch.Identity; import com.jcraft.jsch.JSch; @@ -14,7 +12,8 @@ import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; import com.jcraft.jsch.UserInfo; import com.zeapo.pwdstore.R; - +import java.util.List; +import java.util.concurrent.CountDownLatch; import org.eclipse.jgit.errors.UnsupportedCredentialItem; import org.eclipse.jgit.transport.CredentialItem; import org.eclipse.jgit.transport.CredentialsProvider; @@ -33,15 +32,13 @@ import org.openintents.ssh.authentication.request.SigningRequest; import org.openintents.ssh.authentication.request.SshPublicKeyRequest; import org.openintents.ssh.authentication.util.SshAuthenticationApiUtils; -import java.util.List; -import java.util.concurrent.CountDownLatch; - public class SshApiSessionFactory extends GitConfigSessionFactory { /** * Intent request code indicating a completed signature that should be posted to an outstanding * ApiIdentity */ public static final int POST_SIGNATURE = 301; + private String username; private Identity identity; @@ -52,7 +49,8 @@ public class SshApiSessionFactory extends GitConfigSessionFactory { @NonNull @Override - protected JSch getJSch(@NonNull final OpenSshConfig.Host hc, @NonNull FS fs) throws JSchException { + protected JSch getJSch(@NonNull final OpenSshConfig.Host hc, @NonNull FS fs) + throws JSchException { JSch jsch = super.getJSch(hc, fs); jsch.removeAllIdentity(); jsch.addIdentity(identity, null); @@ -64,36 +62,38 @@ public class SshApiSessionFactory extends GitConfigSessionFactory { session.setConfig("StrictHostKeyChecking", "no"); session.setConfig("PreferredAuthentications", "publickey"); - CredentialsProvider provider = new CredentialsProvider() { - @Override - public boolean isInteractive() { - return false; - } - - @Override - public boolean supports(CredentialItem... items) { - return true; - } - - @Override - public boolean get(URIish uri, CredentialItem... items) throws UnsupportedCredentialItem { - for (CredentialItem item : items) { - if (item instanceof CredentialItem.Username) { - ((CredentialItem.Username) item).setValue(username); + CredentialsProvider provider = + new CredentialsProvider() { + @Override + public boolean isInteractive() { + return false; } - } - return true; - } - }; + + @Override + public boolean supports(CredentialItem... items) { + return true; + } + + @Override + public boolean get(URIish uri, CredentialItem... items) + throws UnsupportedCredentialItem { + for (CredentialItem item : items) { + if (item instanceof CredentialItem.Username) { + ((CredentialItem.Username) item).setValue(username); + } + } + return true; + } + }; UserInfo userInfo = new CredentialsProviderUserInfo(session, provider); session.setUserInfo(userInfo); } /** * Helper to build up an ApiIdentity via the invocation of several pending intents that - * communicate with OpenKeychain. The user of this class must handle onActivityResult and - * keep feeding the resulting intents into the IdentityBuilder until it can successfully complete - * the build. + * communicate with OpenKeychain. The user of this class must handle onActivityResult and keep + * feeding the resulting intents into the IdentityBuilder until it can successfully complete the + * build. */ public static class IdentityBuilder { private SshAuthenticationConnection connection; @@ -106,12 +106,14 @@ public class SshApiSessionFactory extends GitConfigSessionFactory { * Construct a new IdentityBuilder * * @param callingActivity Activity that will be used to launch pending intents and that will - * receive and handle the results. + * receive and handle the results. */ public IdentityBuilder(Activity callingActivity) { this.callingActivity = callingActivity; - List providers = SshAuthenticationApiUtils.getAuthenticationProviderPackageNames(callingActivity); + List providers = + SshAuthenticationApiUtils.getAuthenticationProviderPackageNames( + callingActivity); if (providers.isEmpty()) throw new RuntimeException(callingActivity.getString(R.string.no_ssh_api_provider)); @@ -120,42 +122,44 @@ public class SshApiSessionFactory extends GitConfigSessionFactory { connection = new SshAuthenticationConnection(callingActivity, providers.get(0)); } - /** - * Free any resources associated with this IdentityBuilder - */ + /** Free any resources associated with this IdentityBuilder */ public void close() { - if (connection != null && connection.isConnected()) - connection.disconnect(); + if (connection != null && connection.isConnected()) connection.disconnect(); } /** * Helper to invoke an OpenKeyshain SSH API method and correctly interpret the result. * - * @param request The request intent to launch + * @param request The request intent to launch * @param requestCode The request code to use if a pending intent needs to be sent * @return The resulting intent if the request completed immediately, or null if we had to - * launch a pending intent to interact with the user + * launch a pending intent to interact with the user */ private Intent executeApi(Request request, int requestCode) { Intent result = api.executeApi(request.toIntent()); switch (result.getIntExtra(SshAuthenticationApi.EXTRA_RESULT_CODE, -1)) { case SshAuthenticationApi.RESULT_CODE_ERROR: - SshAuthenticationApiError error = result.getParcelableExtra(SshAuthenticationApi.EXTRA_ERROR); + SshAuthenticationApiError error = + result.getParcelableExtra(SshAuthenticationApi.EXTRA_ERROR); throw new RuntimeException(error.getMessage()); case SshAuthenticationApi.RESULT_CODE_SUCCESS: break; case SshAuthenticationApi.RESULT_CODE_USER_INTERACTION_REQUIRED: - PendingIntent pendingIntent = result.getParcelableExtra(SshAuthenticationApi.EXTRA_PENDING_INTENT); + PendingIntent pendingIntent = + result.getParcelableExtra(SshAuthenticationApi.EXTRA_PENDING_INTENT); try { - callingActivity.startIntentSenderForResult(pendingIntent.getIntentSender(), requestCode, null, 0, 0, 0); + callingActivity.startIntentSenderForResult( + pendingIntent.getIntentSender(), requestCode, null, 0, 0, 0); return null; } catch (IntentSender.SendIntentException e) { e.printStackTrace(); - throw new RuntimeException(callingActivity.getString(R.string.ssh_api_pending_intent_failed)); + throw new RuntimeException( + callingActivity.getString(R.string.ssh_api_pending_intent_failed)); } default: - throw new RuntimeException(callingActivity.getString(R.string.ssh_api_unknown_error)); + throw new RuntimeException( + callingActivity.getString(R.string.ssh_api_unknown_error)); } return result; @@ -168,8 +172,7 @@ public class SshApiSessionFactory extends GitConfigSessionFactory { * @param intent The intent to inspect */ public void consume(Intent intent) { - if (intent == null) - return; + if (intent == null) return; if (intent.hasExtra(SshAuthenticationApi.EXTRA_KEY_ID)) { keyId = intent.getStringExtra(SshAuthenticationApi.EXTRA_KEY_ID); @@ -189,27 +192,31 @@ public class SshApiSessionFactory extends GitConfigSessionFactory { * * @param requestCode The request code to use if a pending intent needs to be sent * @return The built identity, or null of user interaction is still required (in which case - * a pending intent will have already been launched) + * a pending intent will have already been launched) */ public ApiIdentity tryBuild(int requestCode) { // First gate, need to initiate a connection to the service and wait for it to connect. if (api == null) { - connection.connect(new SshAuthenticationConnection.OnBound() { - @Override - public void onBound(ISshAuthenticationService sshAgent) { - api = new SshAuthenticationApi(callingActivity, sshAgent); - // We can immediately try the next phase without needing to post back - // though onActivityResult - tryBuild(requestCode); - } + connection.connect( + new SshAuthenticationConnection.OnBound() { + @Override + public void onBound(ISshAuthenticationService sshAgent) { + api = new SshAuthenticationApi(callingActivity, sshAgent); + // We can immediately try the next phase without needing to post + // back + // though onActivityResult + tryBuild(requestCode); + } - @Override - public void onError() { - new MaterialAlertDialogBuilder(callingActivity) - .setMessage(callingActivity.getString( - R.string.openkeychain_ssh_api_connect_fail)).show(); - } - }); + @Override + public void onError() { + new MaterialAlertDialogBuilder(callingActivity) + .setMessage( + callingActivity.getString( + R.string.openkeychain_ssh_api_connect_fail)) + .show(); + } + }); return null; } @@ -218,8 +225,7 @@ public class SshApiSessionFactory extends GitConfigSessionFactory { if (keyId == null) { consume(executeApi(new KeySelectionRequest(), requestCode)); // If we did not immediately get the result, bail for now and wait to be re-entered - if (keyId == null) - return null; + if (keyId == null) return null; } // Third gate, need to get the public key for the selected key. This one often does not @@ -227,8 +233,7 @@ public class SshApiSessionFactory extends GitConfigSessionFactory { if (publicKey == null) { consume(executeApi(new SshPublicKeyRequest(keyId), requestCode)); // If we did not immediately get the result, bail for now and wait to be re-entered - if (publicKey == null) - return null; + if (publicKey == null) return null; } // Have everything we need for now, build the identify @@ -236,9 +241,7 @@ public class SshApiSessionFactory extends GitConfigSessionFactory { } } - /** - * A Jsch identity that delegates key operations via the OpenKeychain SSH API - */ + /** A Jsch identity that delegates key operations via the OpenKeychain SSH API */ public static class ApiIdentity implements Identity { private String keyId, description, alg; private byte[] publicKey; @@ -247,7 +250,13 @@ public class SshApiSessionFactory extends GitConfigSessionFactory { private CountDownLatch latch; private byte[] signature; - ApiIdentity(String keyId, String description, byte[] publicKey, String alg, Activity callingActivity, SshAuthenticationApi api) { + ApiIdentity( + String keyId, + String description, + byte[] publicKey, + String alg, + Activity callingActivity, + SshAuthenticationApi api) { this.keyId = keyId; this.description = description; this.publicKey = publicKey; @@ -271,33 +280,37 @@ public class SshApiSessionFactory extends GitConfigSessionFactory { * Helper to handle the result of an OpenKeyshain SSH API signing request * * @param result The result intent to handle - * @return The signed challenge, or null if it was not immediately available, in which - * case the latch has been initialized and the pending intent started + * @return The signed challenge, or null if it was not immediately available, in which case + * the latch has been initialized and the pending intent started */ private byte[] handleSignResult(Intent result) { switch (result.getIntExtra(SshAuthenticationApi.EXTRA_RESULT_CODE, -1)) { case SshAuthenticationApi.RESULT_CODE_ERROR: - SshAuthenticationApiError error = result.getParcelableExtra(SshAuthenticationApi.EXTRA_ERROR); + SshAuthenticationApiError error = + result.getParcelableExtra(SshAuthenticationApi.EXTRA_ERROR); throw new RuntimeException(error.getMessage()); case SshAuthenticationApi.RESULT_CODE_SUCCESS: return result.getByteArrayExtra(SshAuthenticationApi.EXTRA_SIGNATURE); case SshAuthenticationApi.RESULT_CODE_USER_INTERACTION_REQUIRED: - PendingIntent pendingIntent = result.getParcelableExtra(SshAuthenticationApi.EXTRA_PENDING_INTENT); + PendingIntent pendingIntent = + result.getParcelableExtra(SshAuthenticationApi.EXTRA_PENDING_INTENT); try { latch = new CountDownLatch(1); - callingActivity.startIntentSenderForResult(pendingIntent.getIntentSender(), POST_SIGNATURE, null, 0, 0, 0); + callingActivity.startIntentSenderForResult( + pendingIntent.getIntentSender(), POST_SIGNATURE, null, 0, 0, 0); return null; } catch (Exception e) { e.printStackTrace(); - throw new RuntimeException(callingActivity.getString(R.string.ssh_api_pending_intent_failed)); + throw new RuntimeException( + callingActivity.getString(R.string.ssh_api_pending_intent_failed)); } default: if (result.hasExtra(SshAuthenticationApi.EXTRA_CHALLENGE)) return handleSignResult(api.executeApi(result)); - throw new RuntimeException(callingActivity.getString(R.string.ssh_api_unknown_error)); + throw new RuntimeException( + callingActivity.getString(R.string.ssh_api_unknown_error)); } - } @Override @@ -318,7 +331,6 @@ public class SshApiSessionFactory extends GitConfigSessionFactory { return signature; } - /** * Post a signature response back to an in-progress operation using this ApiIdentity. * @@ -328,8 +340,7 @@ public class SshApiSessionFactory extends GitConfigSessionFactory { try { signature = handleSignResult(data); } finally { - if (latch != null) - latch.countDown(); + if (latch != null) latch.countDown(); } } @@ -354,8 +365,6 @@ public class SshApiSessionFactory extends GitConfigSessionFactory { } @Override - public void clear() { - - } + public void clear() {} } } diff --git a/app/src/main/java/com/zeapo/pwdstore/pwgen/PasswordGenerator.kt b/app/src/main/java/com/zeapo/pwdstore/pwgen/PasswordGenerator.kt index 29d2dd73..09988ad1 100644 --- a/app/src/main/java/com/zeapo/pwdstore/pwgen/PasswordGenerator.kt +++ b/app/src/main/java/com/zeapo/pwdstore/pwgen/PasswordGenerator.kt @@ -5,7 +5,6 @@ import com.zeapo.pwdstore.R import java.util.ArrayList - object PasswordGenerator { internal const val DIGITS = 0x0001 internal const val UPPERS = 0x0002 @@ -27,9 +26,9 @@ object PasswordGenerator { /** * Sets password generation preferences. * - * @param ctx context from which to retrieve SharedPreferences from + * @param ctx context from which to retrieve SharedPreferences from * preferences file 'PasswordGenerator' - * @param argv options for password generation + * @param argv options for password generation * * * @@ -102,7 +101,7 @@ object PasswordGenerator { phonemes = false pwgenFlags = pwgenFlags or NO_VOWELS // | DIGITS | UPPERS; } - }// pwgenFlags = DIGITS | UPPERS; + } // pwgenFlags = DIGITS | UPPERS; } } @@ -128,7 +127,6 @@ object PasswordGenerator { phonemes = false } - val passwords = ArrayList() val num = prefs.getInt("num", 1) for (i in 0 until num) { @@ -143,4 +141,3 @@ object PasswordGenerator { class PasswordGeneratorExeption(string: String) : Exception(string) } - diff --git a/app/src/main/java/com/zeapo/pwdstore/pwgen/Phonemes.kt b/app/src/main/java/com/zeapo/pwdstore/pwgen/Phonemes.kt index 98e9bfe4..f4477681 100644 --- a/app/src/main/java/com/zeapo/pwdstore/pwgen/Phonemes.kt +++ b/app/src/main/java/com/zeapo/pwdstore/pwgen/Phonemes.kt @@ -56,7 +56,7 @@ internal object Phonemes { /** * Generates a human-readable password. * - * @param size length of password to generate + * @param size length of password to generate * @param pwFlags flag field where set bits indicate conditions the * generated password must meet *
OptionDescription
0don't include numbers
@@ -105,8 +105,8 @@ internal object Phonemes { continue } // Don't allow VOWEL followed a Vowel/Dipthong pair - if (prev and VOWEL > 0 && flags and VOWEL > 0 - && flags and DIPTHONG > 0 + if (prev and VOWEL > 0 && flags and VOWEL > 0 && + flags and DIPTHONG > 0 ) { continue } @@ -200,8 +200,8 @@ internal object Phonemes { shouldBe = if (shouldBe == CONSONANT) { VOWEL } else { - if (prev and VOWEL > 0 || flags and DIPTHONG > 0 - || RandomNumberGenerator.number(10) > 3 + if (prev and VOWEL > 0 || flags and DIPTHONG > 0 || + RandomNumberGenerator.number(10) > 3 ) { CONSONANT } else { diff --git a/app/src/main/java/com/zeapo/pwdstore/pwgen/RandomPasswordGenerator.kt b/app/src/main/java/com/zeapo/pwdstore/pwgen/RandomPasswordGenerator.kt index e3ae3397..f37267b8 100644 --- a/app/src/main/java/com/zeapo/pwdstore/pwgen/RandomPasswordGenerator.kt +++ b/app/src/main/java/com/zeapo/pwdstore/pwgen/RandomPasswordGenerator.kt @@ -5,7 +5,7 @@ internal object RandomPasswordGenerator { /** * Generates a completely random password. * - * @param size length of password to generate + * @param size length of password to generate * @param pwFlags flag field where set bits indicate conditions the * generated password must meet *
@@ -48,8 +48,8 @@ internal object RandomPasswordGenerator { num = RandomNumberGenerator.number(bank.length) cha = bank.toCharArray()[num] character = cha.toString() - if (pwFlags and PasswordGenerator.AMBIGUOUS > 0 - && PasswordGenerator.AMBIGUOUS_STR.contains(character)) { + if (pwFlags and PasswordGenerator.AMBIGUOUS > 0 && + PasswordGenerator.AMBIGUOUS_STR.contains(character)) { continue } if (pwFlags and PasswordGenerator.NO_VOWELS > 0 && PasswordGenerator.VOWELS_STR.contains(character)) { diff --git a/app/src/main/java/com/zeapo/pwdstore/utils/EntryRecyclerAdapter.kt b/app/src/main/java/com/zeapo/pwdstore/utils/EntryRecyclerAdapter.kt index f52756f4..bf2fac94 100644 --- a/app/src/main/java/com/zeapo/pwdstore/utils/EntryRecyclerAdapter.kt +++ b/app/src/main/java/com/zeapo/pwdstore/utils/EntryRecyclerAdapter.kt @@ -98,19 +98,23 @@ abstract class EntryRecyclerAdapter internal constructor(val values: ArrayList

+class FolderRecyclerAdapter( + private val listener: SelectFolderFragment.OnFragmentInteractionListener, + values: ArrayList ) : EntryRecyclerAdapter(values) { override fun getOnClickListener(holder: ViewHolder, pass: PasswordItem): View.OnClickListener { @@ -16,5 +17,4 @@ class FolderRecyclerAdapter(private val listener: SelectFolderFragment.OnFragmen notifyItemChanged(holder.adapterPosition) } } - } diff --git a/app/src/main/java/com/zeapo/pwdstore/utils/Otp.java b/app/src/main/java/com/zeapo/pwdstore/utils/Otp.java index cb949f2e..1a77c380 100644 --- a/app/src/main/java/com/zeapo/pwdstore/utils/Otp.java +++ b/app/src/main/java/com/zeapo/pwdstore/utils/Otp.java @@ -1,29 +1,27 @@ package com.zeapo.pwdstore.utils; import android.util.Log; - -import org.apache.commons.codec.binary.Base32; - import java.math.BigInteger; import java.nio.ByteBuffer; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.Arrays; - import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; +import org.apache.commons.codec.binary.Base32; public class Otp { private static final Base32 BASE_32 = new Base32(); - private Otp() { - } + private Otp() {} - public static String calculateCode(String secret, long counter, String algorithm, String digits) { - String[] steam = {"2", "3", "4", "5", "6", "7", "8", "9", "B", "C", - "D", "F", "G", "H", "J", "K", "M", "N", "P", "Q", - "R", "T", "V", "W", "X", "Y"}; + public static String calculateCode( + String secret, long counter, String algorithm, String digits) { + String[] steam = { + "2", "3", "4", "5", "6", "7", "8", "9", "B", "C", "D", "F", "G", "H", "J", "K", "M", + "N", "P", "Q", "R", "T", "V", "W", "X", "Y" + }; String ALGORITHM = "Hmac" + algorithm.toUpperCase(); SecretKeySpec signingKey = new SecretKeySpec(BASE_32.decode(secret), ALGORITHM); diff --git a/app/src/main/java/com/zeapo/pwdstore/utils/PasswordItem.kt b/app/src/main/java/com/zeapo/pwdstore/utils/PasswordItem.kt index ddecd2da..f16e5111 100644 --- a/app/src/main/java/com/zeapo/pwdstore/utils/PasswordItem.kt +++ b/app/src/main/java/com/zeapo/pwdstore/utils/PasswordItem.kt @@ -4,11 +4,11 @@ import com.zeapo.pwdstore.crypto.PgpActivity import java.io.File data class PasswordItem( - val name: String, - val parent: PasswordItem? = null, - val type: Char, - val file: File, - val rootDir: File + val name: String, + val parent: PasswordItem? = null, + val type: Char, + val file: File, + val rootDir: File ) : Comparable { val fullPathToParent = file.absolutePath .replace(rootDir.absolutePath, "") @@ -41,41 +41,40 @@ data class PasswordItem( @JvmStatic fun newCategory( - name: String, - file: File, - parent: PasswordItem, - rootDir: File + name: String, + file: File, + parent: PasswordItem, + rootDir: File ): PasswordItem { return PasswordItem(name, parent, TYPE_CATEGORY, file, rootDir) } @JvmStatic fun newCategory( - name: String, - file: File, - rootDir: File + name: String, + file: File, + rootDir: File ): PasswordItem { return PasswordItem(name, null, TYPE_CATEGORY, file, rootDir) } @JvmStatic fun newPassword( - name: String, - file: File, - parent: PasswordItem, - rootDir: File + name: String, + file: File, + parent: PasswordItem, + rootDir: File ): PasswordItem { return PasswordItem(name, parent, TYPE_PASSWORD, file, rootDir) } @JvmStatic fun newPassword( - name: String, - file: File, - rootDir: File + name: String, + file: File, + rootDir: File ): PasswordItem { return PasswordItem(name, null, TYPE_PASSWORD, file, rootDir) } } - -} \ No newline at end of file +} diff --git a/app/src/main/java/com/zeapo/pwdstore/utils/PasswordRecyclerAdapter.kt b/app/src/main/java/com/zeapo/pwdstore/utils/PasswordRecyclerAdapter.kt index d7493a48..55ea3ddf 100644 --- a/app/src/main/java/com/zeapo/pwdstore/utils/PasswordRecyclerAdapter.kt +++ b/app/src/main/java/com/zeapo/pwdstore/utils/PasswordRecyclerAdapter.kt @@ -12,9 +12,10 @@ import com.zeapo.pwdstore.R import java.util.ArrayList import java.util.TreeSet -class PasswordRecyclerAdapter(private val activity: PasswordStore, - private val listener: PasswordFragment.OnFragmentInteractionListener, - values: ArrayList +class PasswordRecyclerAdapter( + private val activity: PasswordStore, + private val listener: PasswordFragment.OnFragmentInteractionListener, + values: ArrayList ) : EntryRecyclerAdapter(values) { var actionMode: ActionMode? = null private var canEdit: Boolean = false diff --git a/app/src/main/java/com/zeapo/pwdstore/utils/PasswordRepository.kt b/app/src/main/java/com/zeapo/pwdstore/utils/PasswordRepository.kt index 9e94e400..db37c547 100644 --- a/app/src/main/java/com/zeapo/pwdstore/utils/PasswordRepository.kt +++ b/app/src/main/java/com/zeapo/pwdstore/utils/PasswordRepository.kt @@ -32,7 +32,6 @@ open class PasswordRepository protected constructor() { (p2.type + p1.name).compareTo(p1.type + p2.name, ignoreCase = true) }); - companion object { @JvmStatic fun getSortOrder(settings: SharedPreferences): PasswordSortOrder { @@ -63,7 +62,6 @@ open class PasswordRepository protected constructor() { e.printStackTrace() return null } - } return repository } @@ -104,7 +102,6 @@ open class PasswordRepository protected constructor() { } catch (e: Exception) { e.printStackTrace() } - } else if (replace!!) { try { val uri = URIish(url) @@ -127,7 +124,6 @@ open class PasswordRepository protected constructor() { } catch (e: Exception) { e.printStackTrace() } - } } @@ -214,7 +210,7 @@ open class PasswordRepository protected constructor() { */ @JvmStatic fun getPasswords(path: File, rootDir: File, sortOrder: PasswordSortOrder): ArrayList { - //We need to recover the passwords then parse the files + // We need to recover the passwords then parse the files val passList = getFilesList(path) if (passList.size == 0) return ArrayList() @@ -259,10 +255,10 @@ open class PasswordRepository protected constructor() { /** * Sets a git config value * - * @param section config section name + * @param section config section name * @param subsection config subsection name - * @param name config name - * @param value the value to be set + * @param name config name + * @param value the value to be set */ @JvmStatic @Suppress("SameParameterValue") @@ -275,7 +271,6 @@ open class PasswordRepository protected constructor() { } catch (e: Exception) { e.printStackTrace() } - } } } diff --git a/app/src/main/java/com/zeapo/pwdstore/utils/auth/Authenticator.kt b/app/src/main/java/com/zeapo/pwdstore/utils/auth/Authenticator.kt index 5139ef01..98d787f9 100644 --- a/app/src/main/java/com/zeapo/pwdstore/utils/auth/Authenticator.kt +++ b/app/src/main/java/com/zeapo/pwdstore/utils/auth/Authenticator.kt @@ -8,8 +8,8 @@ import androidx.fragment.app.FragmentActivity import com.zeapo.pwdstore.R internal class Authenticator( - private val fragmentActivity: FragmentActivity, - private val callback: (AuthenticationResult) -> Unit + private val fragmentActivity: FragmentActivity, + private val callback: (AuthenticationResult) -> Unit ) { private val handler = Handler() private val biometricManager = BiometricManager.from(fragmentActivity) @@ -18,7 +18,7 @@ internal class Authenticator( override fun onAuthenticationError(errorCode: Int, errString: CharSequence) { super.onAuthenticationError(errorCode, errString) - Log.d(TAG,"Error: $errorCode: $errString") + Log.d(TAG, "Error: $errorCode: $errString") callback(AuthenticationResult.UnrecoverableError(errorCode, errString)) } diff --git a/app/src/main/java/com/zeapo/pwdstore/widget/MultiselectableLinearLayout.kt b/app/src/main/java/com/zeapo/pwdstore/widget/MultiselectableLinearLayout.kt index 7ceea1db..22fb6f00 100644 --- a/app/src/main/java/com/zeapo/pwdstore/widget/MultiselectableLinearLayout.kt +++ b/app/src/main/java/com/zeapo/pwdstore/widget/MultiselectableLinearLayout.kt @@ -13,10 +13,10 @@ import android.widget.LinearLayout import com.zeapo.pwdstore.R class MultiselectableLinearLayout @JvmOverloads constructor( - context: Context, - attrs: AttributeSet? = null, - defStyleAttr: Int = 0, - defStyleRes: Int = 0 + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + defStyleRes: Int = 0 ) : LinearLayout(context, attrs, defStyleAttr, defStyleRes) { private var multiselected: Boolean = false @@ -48,4 +48,4 @@ class MultiselectableLinearLayout @JvmOverloads constructor( companion object { private val STATE_MULTISELECTED = intArrayOf(R.attr.state_multiselected) } -} \ No newline at end of file +} diff --git a/build.gradle.kts b/build.gradle.kts index c56ed91b..28b13bd7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -45,3 +45,5 @@ tasks { distributionType = Wrapper.DistributionType.ALL } } + +configureSpotless() diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 00000000..8c3ae64d --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,16 @@ +plugins { + `kotlin-dsl` +} + +repositories { + maven("https://plugins.gradle.org/m2/") + jcenter() +} + +kotlinDslPluginOptions { + experimentalWarning.set(false) +} + +dependencies { + implementation("com.diffplug.spotless:spotless-plugin-gradle:3.24.3") +} diff --git a/buildSrc/src/main/kotlin/SpotlessConfiguration.kt b/buildSrc/src/main/kotlin/SpotlessConfiguration.kt new file mode 100644 index 00000000..3c183c5f --- /dev/null +++ b/buildSrc/src/main/kotlin/SpotlessConfiguration.kt @@ -0,0 +1,47 @@ +import com.diffplug.gradle.spotless.SpotlessExtension +import com.diffplug.gradle.spotless.SpotlessPlugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.apply +import org.gradle.kotlin.dsl.configure + +val kotlinLicenseHeader = """/* + * Copyright © 2014-2019 The Android Password Store Authors. All Rights Reserved. + * SPDX-License-Identifier: GPL-2.0 + */ +""".trimIndent() + +fun Project.configureSpotless() { + apply() + + configure { + java { + target("**/src/main/**/*.java") + trimTrailingWhitespace() + // @Suppress("INACCESSIBLE_TYPE") + // licenseHeader(kotlinLicenseHeader) + removeUnusedImports() + googleJavaFormat().aosp() + endWithNewline() + } + + kotlinGradle { + target("*.gradle.kts", "gradle/*.gradle.kts", "buildSrc/*.gradle.kts") + ktlint("0.31.0").userData(mapOf("indent_size" to "4", "continuation_indent_size" to "4")) + // @Suppress("INACCESSIBLE_TYPE") + // licenseHeader(kotlinLicenseHeader, "import|tasks|apply|plugins|include") + trimTrailingWhitespace() + indentWithSpaces() + endWithNewline() + } + + kotlin { + target("**/src/main/**/*.kt", "buildSrc/**/*.kt") + ktlint("0.31.0").userData(mapOf("indent_size" to "4", "continuation_indent_size" to "4")) + // @Suppress("INACCESSIBLE_TYPE") + // licenseHeader(kotlinLicenseHeader) + trimTrailingWhitespace() + indentWithSpaces() + endWithNewline() + } + } +}