Search in sources :

Example 6 with Entry

use of org.shadowice.flocke.andotp.Database.Entry in project andOTP by andOTP.

the class EntriesCardAdapter method editEntryLabel.

public void editEntryLabel(final int pos) {
    AlertDialog.Builder builder = new AlertDialog.Builder(context);
    int marginSmall = context.getResources().getDimensionPixelSize(R.dimen.activity_margin_small);
    int marginMedium = context.getResources().getDimensionPixelSize(R.dimen.activity_margin_medium);
    final EditText input = new EditText(context);
    input.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
    input.setText(displayedEntries.get(pos).getLabel());
    input.setSingleLine();
    FrameLayout container = new FrameLayout(context);
    container.setPaddingRelative(marginMedium, marginSmall, marginMedium, 0);
    container.addView(input);
    builder.setTitle(R.string.dialog_title_rename).setView(container).setPositiveButton(R.string.button_save, new DialogInterface.OnClickListener() {

        @Override
        public void onClick(DialogInterface dialogInterface, int i) {
            int realIndex = getRealIndex(pos);
            String newLabel = input.getEditableText().toString();
            displayedEntries.get(pos).setLabel(newLabel);
            if (sortMode == SortMode.LABEL) {
                displayedEntries = sortEntries(displayedEntries);
                notifyDataSetChanged();
            } else {
                notifyItemChanged(pos);
            }
            Entry e = entries.get(realIndex);
            e.setLabel(newLabel);
            DatabaseHelper.saveDatabase(context, entries, encryptionKey);
        }
    }).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {

        @Override
        public void onClick(DialogInterface dialogInterface, int i) {
        }
    }).create().show();
}
Also used : AlertDialog(android.app.AlertDialog) EditText(android.widget.EditText) DialogInterface(android.content.DialogInterface) Entry(org.shadowice.flocke.andotp.Database.Entry) FrameLayout(android.widget.FrameLayout)

Example 7 with Entry

use of org.shadowice.flocke.andotp.Database.Entry in project andOTP by andOTP.

the class ManualEntryDialog method show.

public static void show(final MainActivity callingActivity, Settings settings, final EntriesCardAdapter adapter) {
    ViewGroup container = callingActivity.findViewById(R.id.main_content);
    View inputView = callingActivity.getLayoutInflater().inflate(R.layout.dialog_manual_entry, container, false);
    final Spinner typeInput = inputView.findViewById(R.id.manual_type);
    final EditText labelInput = inputView.findViewById(R.id.manual_label);
    final EditText secretInput = inputView.findViewById(R.id.manual_secret);
    final EditText counterInput = inputView.findViewById(R.id.manual_counter);
    final EditText periodInput = inputView.findViewById(R.id.manual_period);
    final EditText digitsInput = inputView.findViewById(R.id.manual_digits);
    final LinearLayout counterLayout = inputView.findViewById(R.id.manual_layout_counter);
    final LinearLayout periodLayout = inputView.findViewById(R.id.manual_layout_period);
    final Spinner algorithmInput = inputView.findViewById(R.id.manual_algorithm);
    final Button tagsInput = inputView.findViewById(R.id.manual_tags);
    final ArrayAdapter<TokenCalculator.HashAlgorithm> algorithmAdapter = new ArrayAdapter<>(callingActivity, android.R.layout.simple_expandable_list_item_1, TokenCalculator.HashAlgorithm.values());
    final ArrayAdapter<Entry.OTPType> typeAdapter = new ArrayAdapter<>(callingActivity, android.R.layout.simple_expandable_list_item_1, Entry.PublicTypes.toArray(new Entry.OTPType[Entry.PublicTypes.size()]));
    final ArrayAdapter<Entry.OTPType> fullTypeAdapter = new ArrayAdapter<>(callingActivity, android.R.layout.simple_expandable_list_item_1, Entry.OTPType.values());
    if (settings.getSpecialFeatures())
        typeInput.setAdapter(fullTypeAdapter);
    else
        typeInput.setAdapter(typeAdapter);
    algorithmInput.setAdapter(algorithmAdapter);
    periodInput.setText(String.format(Locale.US, "%d", TokenCalculator.TOTP_DEFAULT_PERIOD));
    digitsInput.setText(String.format(Locale.US, "%d", TokenCalculator.TOTP_DEFAULT_DIGITS));
    counterInput.setText(String.format(Locale.US, "%d", TokenCalculator.HOTP_INITIAL_COUNTER));
    typeInput.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

        @Override
        public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
            Entry.OTPType type = (Entry.OTPType) adapterView.getSelectedItem();
            if (type == Entry.OTPType.STEAM) {
                counterLayout.setVisibility(View.GONE);
                periodLayout.setVisibility(View.VISIBLE);
                digitsInput.setText(String.format(Locale.US, "%d", TokenCalculator.STEAM_DEFAULT_DIGITS));
                periodInput.setText(String.format(Locale.US, "%d", TokenCalculator.TOTP_DEFAULT_PERIOD));
                algorithmInput.setSelection(algorithmAdapter.getPosition(TokenCalculator.HashAlgorithm.SHA1));
                digitsInput.setEnabled(false);
                periodInput.setEnabled(false);
                algorithmInput.setEnabled(false);
            } else if (type == Entry.OTPType.TOTP) {
                counterLayout.setVisibility(View.GONE);
                periodLayout.setVisibility(View.VISIBLE);
                digitsInput.setText(String.format(Locale.US, "%d", TokenCalculator.TOTP_DEFAULT_DIGITS));
                digitsInput.setEnabled(true);
                periodInput.setEnabled(true);
                algorithmInput.setEnabled(true);
            } else if (type == Entry.OTPType.HOTP) {
                counterLayout.setVisibility(View.VISIBLE);
                periodLayout.setVisibility(View.GONE);
                digitsInput.setText(String.format(Locale.US, "%d", TokenCalculator.TOTP_DEFAULT_DIGITS));
                digitsInput.setEnabled(true);
                periodInput.setEnabled(true);
                algorithmInput.setEnabled(true);
            }
        }

        @Override
        public void onNothingSelected(AdapterView<?> adapterView) {
        }
    });
    List<String> allTags = adapter.getTags();
    HashMap<String, Boolean> tagsHashMap = new HashMap<>();
    for (String tag : allTags) {
        tagsHashMap.put(tag, false);
    }
    final TagsAdapter tagsAdapter = new TagsAdapter(callingActivity, tagsHashMap);
    final Callable tagsCallable = new Callable() {

        @Override
        public Object call() throws Exception {
            List<String> selectedTags = tagsAdapter.getActiveTags();
            StringBuilder stringBuilder = new StringBuilder();
            for (int j = 0; j < selectedTags.size(); j++) {
                stringBuilder.append(selectedTags.get(j));
                if (j < selectedTags.size() - 1) {
                    stringBuilder.append(", ");
                }
            }
            tagsInput.setText(stringBuilder.toString());
            return null;
        }
    };
    tagsInput.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View view) {
            TagsDialog.show(callingActivity, tagsAdapter, tagsCallable, tagsCallable);
        }
    });
    final Button expandButton = inputView.findViewById(R.id.dialog_expand_button);
    final ExpandableLinearLayout expandLayout = inputView.findViewById(R.id.dialog_expand_layout);
    expandButton.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View view) {
            expandLayout.toggle();
        }
    });
    expandLayout.setListener(new ExpandableLayoutListenerAdapter() {

        @Override
        public void onOpened() {
            super.onOpened();
            expandButton.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.ic_arrow_up_accent, 0);
        }

        @Override
        public void onClosed() {
            super.onClosed();
            expandButton.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.ic_arrow_down_accent, 0);
        }
    });
    AlertDialog.Builder builder = new AlertDialog.Builder(callingActivity);
    builder.setTitle(R.string.dialog_title_manual_entry).setView(inputView).setPositiveButton(R.string.button_save, new DialogInterface.OnClickListener() {

        @Override
        public void onClick(DialogInterface dialogInterface, int i) {
            Entry.OTPType type = (Entry.OTPType) typeInput.getSelectedItem();
            TokenCalculator.HashAlgorithm algorithm = (TokenCalculator.HashAlgorithm) algorithmInput.getSelectedItem();
            String label = labelInput.getText().toString();
            String secret = secretInput.getText().toString();
            int digits = Integer.parseInt(digitsInput.getText().toString());
            if (type == Entry.OTPType.TOTP || type == Entry.OTPType.STEAM) {
                int period = Integer.parseInt(periodInput.getText().toString());
                Entry e = new Entry(type, secret, period, digits, label, algorithm, tagsAdapter.getActiveTags());
                e.updateOTP();
                adapter.addEntry(e);
                adapter.saveEntries();
                callingActivity.refreshTags();
            } else if (type == Entry.OTPType.HOTP) {
                long counter = Long.parseLong(counterInput.getText().toString());
                Entry e = new Entry(type, secret, counter, digits, label, algorithm, tagsAdapter.getActiveTags());
                e.updateOTP();
                adapter.addEntry(e);
                adapter.saveEntries();
            }
        }
    }).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {

        @Override
        public void onClick(DialogInterface dialogInterface, int i) {
        }
    });
    AlertDialog dialog = builder.create();
    dialog.show();
    final Button positiveButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
    positiveButton.setEnabled(false);
    TextWatcher watcher = new TextWatcher() {

        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        }

        @Override
        public void afterTextChanged(Editable editable) {
            if (TextUtils.isEmpty(labelInput.getText()) || TextUtils.isEmpty(secretInput.getText()) || TextUtils.isEmpty(digitsInput.getText()) || Integer.parseInt(digitsInput.getText().toString()) == 0) {
                positiveButton.setEnabled(false);
            } else {
                Entry.OTPType type = (Entry.OTPType) typeInput.getSelectedItem();
                if (type == Entry.OTPType.HOTP) {
                    if (TextUtils.isEmpty(counterInput.getText())) {
                        positiveButton.setEnabled(false);
                    } else {
                        positiveButton.setEnabled(true);
                    }
                } else if (type == Entry.OTPType.TOTP || type == Entry.OTPType.STEAM) {
                    if (TextUtils.isEmpty(periodInput.getText()) || Integer.parseInt(periodInput.getText().toString()) == 0) {
                        positiveButton.setEnabled(false);
                    } else {
                        positiveButton.setEnabled(true);
                    }
                } else {
                    positiveButton.setEnabled(true);
                }
            }
        }
    };
    labelInput.addTextChangedListener(watcher);
    secretInput.addTextChangedListener(watcher);
    periodInput.addTextChangedListener(watcher);
    digitsInput.addTextChangedListener(watcher);
    counterInput.addTextChangedListener(watcher);
}
Also used : AlertDialog(android.app.AlertDialog) HashMap(java.util.HashMap) DialogInterface(android.content.DialogInterface) Spinner(android.widget.Spinner) TokenCalculator(org.shadowice.flocke.andotp.Utilities.TokenCalculator) Callable(java.util.concurrent.Callable) Entry(org.shadowice.flocke.andotp.Database.Entry) Button(android.widget.Button) TextWatcher(android.text.TextWatcher) Editable(android.text.Editable) EditText(android.widget.EditText) ViewGroup(android.view.ViewGroup) View(android.view.View) AdapterView(android.widget.AdapterView) ExpandableLayoutListenerAdapter(com.github.aakira.expandablelayout.ExpandableLayoutListenerAdapter) AdapterView(android.widget.AdapterView) LinearLayout(android.widget.LinearLayout) ExpandableLinearLayout(com.github.aakira.expandablelayout.ExpandableLinearLayout) ArrayAdapter(android.widget.ArrayAdapter) ExpandableLinearLayout(com.github.aakira.expandablelayout.ExpandableLinearLayout)

Example 8 with Entry

use of org.shadowice.flocke.andotp.Database.Entry in project andOTP by andOTP.

the class PlainTextBackupBroadcastReceiver method onReceive.

@Override
public void onReceive(Context context, Intent intent) {
    Settings settings = new Settings(context);
    if (settings.isPlainTextBackupBroadcastEnabled()) {
        if (!canSaveBackup(context))
            return;
        Uri savePath = Tools.buildUri(settings.getBackupDir(), FileHelper.backupFilename(context, Constants.BackupType.PLAIN_TEXT));
        SecretKey encryptionKey = null;
        if (settings.getEncryption() == Constants.EncryptionType.KEYSTORE) {
            encryptionKey = KeyStoreHelper.loadEncryptionKeyFromKeyStore(context, false);
        } else {
            NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_FAILED, R.string.backup_receiver_title_backup_failed, R.string.backup_receiver_custom_encryption_failed);
            return;
        }
        if (Tools.isExternalStorageWritable()) {
            ArrayList<Entry> entries = DatabaseHelper.loadDatabase(context, encryptionKey);
            if (FileHelper.writeStringToFile(context, savePath, DatabaseHelper.entriesToString(entries))) {
                NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_SUCCESS, R.string.backup_receiver_title_backup_success, savePath.getPath());
            } else {
                NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_FAILED, R.string.backup_receiver_title_backup_failed, R.string.backup_toast_export_failed);
            }
        } else {
            NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_FAILED, R.string.backup_receiver_title_backup_failed, R.string.backup_toast_storage_not_accessible);
        }
    } else {
        NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_FAILED, R.string.backup_receiver_title_backup_failed, R.string.backup_receiver_plain_disabled);
    }
}
Also used : SecretKey(javax.crypto.SecretKey) Entry(org.shadowice.flocke.andotp.Database.Entry) Uri(android.net.Uri) Settings(org.shadowice.flocke.andotp.Utilities.Settings)

Example 9 with Entry

use of org.shadowice.flocke.andotp.Database.Entry in project andOTP by andOTP.

the class EntriesCardAdapter method setCounter.

private void setCounter(final int pos) {
    AlertDialog.Builder builder = new AlertDialog.Builder(context);
    int marginSmall = context.getResources().getDimensionPixelSize(R.dimen.activity_margin_small);
    int marginMedium = context.getResources().getDimensionPixelSize(R.dimen.activity_margin_medium);
    final EditText input = new EditText(context);
    input.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
    input.setText(String.format(Locale.ENGLISH, "%d", displayedEntries.get(pos).getCounter()));
    input.setInputType(InputType.TYPE_CLASS_NUMBER);
    input.setSingleLine();
    FrameLayout container = new FrameLayout(context);
    container.setPaddingRelative(marginMedium, marginSmall, marginMedium, 0);
    container.addView(input);
    builder.setTitle(R.string.dialog_title_counter).setView(container).setPositiveButton(R.string.button_save, new DialogInterface.OnClickListener() {

        @Override
        public void onClick(DialogInterface dialogInterface, int i) {
            int realIndex = getRealIndex(pos);
            long newCounter = Long.parseLong(input.getEditableText().toString());
            displayedEntries.get(pos).setCounter(newCounter);
            notifyItemChanged(pos);
            Entry e = entries.get(realIndex);
            e.setCounter(newCounter);
            DatabaseHelper.saveDatabase(context, entries, encryptionKey);
        }
    }).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {

        @Override
        public void onClick(DialogInterface dialogInterface, int i) {
        }
    }).create().show();
}
Also used : AlertDialog(android.app.AlertDialog) EditText(android.widget.EditText) DialogInterface(android.content.DialogInterface) Entry(org.shadowice.flocke.andotp.Database.Entry) FrameLayout(android.widget.FrameLayout)

Example 10 with Entry

use of org.shadowice.flocke.andotp.Database.Entry in project andOTP by andOTP.

the class ApplicationTest method testSettingsHelper.

public void testSettingsHelper() throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
    Context context = getContext();
    final KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
    keyStore.load(null);
    keyStore.deleteEntry("settings");
    new File(context.getFilesDir() + "/" + Constants.FILENAME_DATABASE).delete();
    new File(context.getFilesDir() + "/" + Constants.FILENAME_ENCRYPTED_KEY).delete();
    SecretKey encryptionKey = KeyStoreHelper.loadEncryptionKeyFromKeyStore(context, false);
    ArrayList<Entry> b = DatabaseHelper.loadDatabase(context, encryptionKey);
    assertEquals(0, b.size());
    ArrayList<Entry> a = new ArrayList<>();
    Entry e = new Entry();
    e.setLabel("label");
    e.setSecret("secret".getBytes());
    a.add(e);
    e = new Entry();
    e.setLabel("label2");
    e.setSecret("secret2".getBytes());
    a.add(e);
    DatabaseHelper.saveDatabase(context, a, encryptionKey);
    b = DatabaseHelper.loadDatabase(context, encryptionKey);
    assertEquals(a, b);
    new File(context.getFilesDir() + "/" + Constants.FILENAME_DATABASE).delete();
    new File(context.getFilesDir() + "/" + Constants.FILENAME_ENCRYPTED_KEY).delete();
}
Also used : Context(android.content.Context) SecretKey(javax.crypto.SecretKey) Entry(org.shadowice.flocke.andotp.Database.Entry) ArrayList(java.util.ArrayList) KeyStore(java.security.KeyStore) File(java.io.File)

Aggregations

Entry (org.shadowice.flocke.andotp.Database.Entry)19 ArrayList (java.util.ArrayList)5 SecretKey (javax.crypto.SecretKey)5 AlertDialog (android.app.AlertDialog)4 DialogInterface (android.content.DialogInterface)4 EditText (android.widget.EditText)4 View (android.view.View)3 AdapterView (android.widget.AdapterView)3 FrameLayout (android.widget.FrameLayout)3 IOException (java.io.IOException)3 Uri (android.net.Uri)2 RecyclerView (android.support.v7.widget.RecyclerView)2 Editable (android.text.Editable)2 TextWatcher (android.text.TextWatcher)2 ViewGroup (android.view.ViewGroup)2 GridView (android.widget.GridView)2 LinearLayout (android.widget.LinearLayout)2 File (java.io.File)2 HashMap (java.util.HashMap)2 Callable (java.util.concurrent.Callable)2