diff options
author | Felix Bechstein <f@ub0r.de> | 2017-07-22 12:09:34 +0200 |
---|---|---|
committer | Mohamed Zenadi <zeapo@users.noreply.github.com> | 2017-07-22 12:09:34 +0200 |
commit | 5cba6c62d7b4628dfaf482dd883e333f93d323d4 (patch) | |
tree | b28df0db4ca187df0cabc575bbd89c009f69e127 /app/src/main/java | |
parent | 6ce31056c987b8fd73513d5b4eebc8d0d763a7a2 (diff) |
Parse username from password entry, refs #192 (#318)
This is a first step of letting APS handle usernames from password
entries. It shows the username in PgpHandler and allows to copy it to
the clipboard.
Diffstat (limited to 'app/src/main/java')
3 files changed, 103 insertions, 24 deletions
diff --git a/app/src/main/java/com/zeapo/pwdstore/PasswordEntry.java b/app/src/main/java/com/zeapo/pwdstore/PasswordEntry.java new file mode 100644 index 00000000..d4d3fe81 --- /dev/null +++ b/app/src/main/java/com/zeapo/pwdstore/PasswordEntry.java @@ -0,0 +1,59 @@ +package com.zeapo.pwdstore; + +import java.io.ByteArrayOutputStream; +import java.io.UnsupportedEncodingException; + +/** + * A single entry in password store. + */ +public class PasswordEntry { + + private static final String[] USERNAME_FIELDS = new String[]{"login", "username"}; + + private final String extraContent; + private final String password; + private final String username; + + public PasswordEntry(final ByteArrayOutputStream os) throws UnsupportedEncodingException { + this(os.toString("UTF-8")); + } + + public PasswordEntry(final String decryptedContent) { + final String[] passContent = decryptedContent.split("\n", 2); + password = passContent[0]; + extraContent = passContent.length > 1 ? passContent[1] : ""; + username = findUsername(); + } + + public String getPassword() { + return password; + } + + public String getExtraContent() { + return extraContent; + } + + public String getUsername() { + return username; + } + + public boolean hasExtraContent() { + return extraContent.length() != 0; + } + + public boolean hasUsername() { + return username != null; + } + + private String findUsername() { + final String[] extraLines = extraContent.split("\n"); + for (String line : extraLines) { + for (String field : USERNAME_FIELDS) { + if (line.toLowerCase().startsWith(field + ":")) { + return line.split(": *", 2)[1]; + } + } + } + return null; + } +} diff --git a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillService.java b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillService.java index 447f39f3..004a0bbd 100644 --- a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillService.java +++ b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillService.java @@ -23,6 +23,7 @@ import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityWindowInfo; import android.widget.Toast; +import com.zeapo.pwdstore.PasswordEntry; import com.zeapo.pwdstore.R; import com.zeapo.pwdstore.utils.PasswordRepository; @@ -492,7 +493,7 @@ public class AutofillService extends AccessibilityService { switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) { case OpenPgpApi.RESULT_CODE_SUCCESS: { try { - String[] passContent = os.toString("UTF-8").split("\n"); + final PasswordEntry entry = new PasswordEntry(os); // if the user focused on something else, take focus back // but this will open another dialog...hack to ignore this @@ -501,11 +502,11 @@ public class AutofillService extends AccessibilityService { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Bundle args = new Bundle(); args.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, - passContent[0]); + entry.getPassword()); info.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, args); } else { ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); - ClipData clip = ClipData.newPlainText("autofill_pm", passContent[0]); + ClipData clip = ClipData.newPlainText("autofill_pm", entry.getPassword()); clipboard.setPrimaryClip(clip); info.performAction(AccessibilityNodeInfo.ACTION_PASTE); diff --git a/app/src/main/java/com/zeapo/pwdstore/crypto/PgpHandler.java b/app/src/main/java/com/zeapo/pwdstore/crypto/PgpHandler.java index 232c7b94..e938fdd4 100644 --- a/app/src/main/java/com/zeapo/pwdstore/crypto/PgpHandler.java +++ b/app/src/main/java/com/zeapo/pwdstore/crypto/PgpHandler.java @@ -34,6 +34,7 @@ import android.widget.Toast; import com.google.common.primitives.Longs; import com.zeapo.pwdstore.BuildConfig; +import com.zeapo.pwdstore.PasswordEntry; import com.zeapo.pwdstore.R; import com.zeapo.pwdstore.SelectFolderFragment; import com.zeapo.pwdstore.UserPreference; @@ -163,7 +164,7 @@ public class PgpHandler extends AppCompatActivity implements OpenPgpServiceConne finish(); return true; case R.id.copy_password: - copyToClipBoard(); + copyPasswordToClipBoard(); break; case R.id.share_password_as_plaintext: shareAsPlaintext(); @@ -245,7 +246,7 @@ public class PgpHandler extends AppCompatActivity implements OpenPgpServiceConne startActivity(Intent.createChooser(sendIntent, getResources().getText(R.string.send_plaintext_password_to)));//Always show a picker to give the user a chance to cancel } - public void copyToClipBoard() { + public void copyPasswordToClipBoard() { if (findViewById(R.id.crypto_password_show) == null) return; @@ -261,7 +262,13 @@ public class PgpHandler extends AppCompatActivity implements OpenPgpServiceConne } catch (NumberFormatException e) { // ignore and keep default } - showToast(this.getResources().getString(R.string.clipboard_toast_text, clearAfter)); + showToast(this.getResources().getString(R.string.clipboard_password_toast_text, clearAfter)); + } + + public void copyUsernameToClipBoard(final String username) { + ClipData clip = ClipData.newPlainText("pgp_handler_result_pm", username); + clipboard.setPrimaryClip(clip); + showToast(this.getResources().getString(R.string.clipboard_username_toast_text)); } public void handleClick(View view) { @@ -490,34 +497,46 @@ public class PgpHandler extends AppCompatActivity implements OpenPgpServiceConne findViewById(R.id.crypto_container).setVisibility(View.VISIBLE); Typeface monoTypeface = Typeface.createFromAsset(getAssets(), "fonts/sourcecodepro.ttf"); - final String[] passContent = os.toString("UTF-8").split("\n", 2); - final String decodedPassword = passContent[0]; - final String extraContent = passContent.length > 1 ? passContent[1] : ""; - textViewPassword - .setTypeface(monoTypeface); - textViewPassword - .setText(decodedPassword); + final PasswordEntry entry = new PasswordEntry(os); + textViewPassword.setTypeface(monoTypeface); + textViewPassword.setText(entry.getPassword()); Button toggleVisibilityButton = (Button) findViewById(R.id.crypto_password_toggle_show); toggleVisibilityButton.setVisibility(showPassword?View.GONE:View.VISIBLE); textViewPassword.setTransformationMethod(showPassword?null:new HoldToShowPasswordTransformation(toggleVisibilityButton, new Runnable() { @Override public void run() { - textViewPassword - .setText(decodedPassword); + textViewPassword.setText(entry.getPassword()); } })); - if (extraContent.length() != 0) { + if (entry.hasExtraContent()) { findViewById(R.id.crypto_extra_show_layout).setVisibility(showExtraContent ? View.VISIBLE : View.GONE); - ((TextView) findViewById(R.id.crypto_extra_show)) - .setTypeface(monoTypeface); - ((TextView) findViewById(R.id.crypto_extra_show)) - .setText(extraContent); + final TextView extraView = (TextView) findViewById(R.id.crypto_extra_show); + extraView.setTypeface(monoTypeface); + extraView.setText(entry.getExtraContent()); + if (entry.hasUsername()) { + findViewById(R.id.crypto_username_show).setVisibility(View.VISIBLE); + findViewById(R.id.crypto_username_show_label).setVisibility(View.VISIBLE); + findViewById(R.id.crypto_copy_username).setVisibility(View.VISIBLE); + findViewById(R.id.crypto_copy_username).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + copyUsernameToClipBoard(entry.getUsername()); + } + }); + final TextView usernameView = (TextView) findViewById(R.id.crypto_username_show); + usernameView.setTypeface(monoTypeface); + usernameView.setText(entry.getUsername()); + } else { + findViewById(R.id.crypto_username_show).setVisibility(View.GONE); + findViewById(R.id.crypto_username_show_label).setVisibility(View.GONE); + findViewById(R.id.crypto_copy_username).setVisibility(View.GONE); + } } if (settings.getBoolean("copy_on_decrypt", true)) { - copyToClipBoard(); + copyPasswordToClipBoard(); } } else { Log.d("PGPHANDLER", "Error message after decrypt : " + os.toString()); @@ -569,12 +588,12 @@ public class PgpHandler extends AppCompatActivity implements OpenPgpServiceConne findViewById(R.id.crypto_container).setVisibility(View.VISIBLE); Typeface monoTypeface = Typeface.createFromAsset(getAssets(), "fonts/sourcecodepro.ttf"); - String[] passContent = os.toString("UTF-8").split("\n"); + final PasswordEntry entry = new PasswordEntry(os); + decodedPassword = entry.getPassword(); textViewPassword .setTypeface(monoTypeface); textViewPassword - .setText(passContent[0]); - decodedPassword = passContent[0]; + .setText(decodedPassword); String extraContent = os.toString("UTF-8").replaceFirst(".*\n", ""); if (extraContent.length() != 0) { |