commit 894c7ba11e1357833e4f40f2988ba856c96ae487 Author: bim dsnake@protonmail.com Date: Mon Mar 1 15:51:49 2021 -0500
- Fixed .auth_privates being saved as .auth_private.txt - Better input validation on backing up client auth keys - Fixed minor bug where backup filename would clear on device rotation --- .../clientauth/ClientAuthActivity.java | 20 +++++++-- .../clientauth/ClientAuthBackupDialogFragment.java | 47 ++++++++++++++++++++-- 2 files changed, 60 insertions(+), 7 deletions(-)
diff --git a/app/src/main/java/org/torproject/android/ui/v3onionservice/clientauth/ClientAuthActivity.java b/app/src/main/java/org/torproject/android/ui/v3onionservice/clientauth/ClientAuthActivity.java index e33ddf78..761ce171 100644 --- a/app/src/main/java/org/torproject/android/ui/v3onionservice/clientauth/ClientAuthActivity.java +++ b/app/src/main/java/org/torproject/android/ui/v3onionservice/clientauth/ClientAuthActivity.java @@ -8,6 +8,7 @@ import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.os.Handler; +import android.provider.OpenableColumns; import android.view.Menu; import android.view.MenuItem; import android.widget.ListView; @@ -22,7 +23,6 @@ import org.torproject.android.R; import org.torproject.android.core.DiskUtils; import org.torproject.android.core.LocaleHelper; import org.torproject.android.ui.hiddenservices.backup.BackupUtils; -import org.torproject.android.ui.hiddenservices.backup.ZipUtilities;
import java.io.File; import java.util.List; @@ -36,6 +36,9 @@ public class ClientAuthActivity extends AppCompatActivity { private ContentResolver mResolver; private ClientAuthListAdapter mAdapter;
+ static final String CLIENT_AUTH_FILE_EXTENSION = ".auth_private", + CLIENT_AUTH_SAF_MIME_TYPE = "*/*"; + @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -69,14 +72,22 @@ public class ClientAuthActivity extends AppCompatActivity { if (requestCode == REQUEST_CODE_READ_ZIP_BACKUP && resultCode == RESULT_OK) { Uri uri = data.getData(); if (uri != null) { + Cursor cursor = getContentResolver().query(uri, null, null, null, null); + int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); + cursor.moveToFirst(); + String filename = cursor.getString(nameIndex); + cursor.close(); + if (!filename.endsWith(CLIENT_AUTH_FILE_EXTENSION)) { + Toast.makeText(this, R.string.error, Toast.LENGTH_LONG).show(); + return; + } String authText = DiskUtils.readFileFromInputStream(getContentResolver(), uri); new BackupUtils(this).restoreClientAuthBackup(authText); } } else { super.onActivityResult(requestCode, resultCode, data); List<Fragment> frags = getSupportFragmentManager().getFragments(); - if (frags != null) - for (Fragment f : frags) f.onActivityResult(requestCode, resultCode, data); + for (Fragment f : frags) f.onActivityResult(requestCode, resultCode, data); } }
@@ -103,7 +114,8 @@ public class ClientAuthActivity extends AppCompatActivity { public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.menu_import_auth_priv) { if (DiskUtils.supportsStorageAccessFramework()) { - Intent readFileIntent = DiskUtils.createReadFileIntent("text/*"); + // unfortunately no good way to filter .auth_private files + Intent readFileIntent = DiskUtils.createReadFileIntent(CLIENT_AUTH_SAF_MIME_TYPE); startActivityForResult(readFileIntent, REQUEST_CODE_READ_ZIP_BACKUP); } else { // APIs 16, 17, 18 doRestoreLegacy(); diff --git a/app/src/main/java/org/torproject/android/ui/v3onionservice/clientauth/ClientAuthBackupDialogFragment.java b/app/src/main/java/org/torproject/android/ui/v3onionservice/clientauth/ClientAuthBackupDialogFragment.java index c924fe0e..b56bc337 100644 --- a/app/src/main/java/org/torproject/android/ui/v3onionservice/clientauth/ClientAuthBackupDialogFragment.java +++ b/app/src/main/java/org/torproject/android/ui/v3onionservice/clientauth/ClientAuthBackupDialogFragment.java @@ -3,9 +3,13 @@ package org.torproject.android.ui.v3onionservice.clientauth; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; +import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; import android.os.Bundle; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.Toast; @@ -23,6 +27,9 @@ import java.io.File; public class ClientAuthBackupDialogFragment extends DialogFragment {
private NoPersonalizedLearningEditText etFilename; + private TextWatcher fileNameTextWatcher; + + private static final String BUNDLE_KEY_FILENAME = "filename";
public ClientAuthBackupDialogFragment() { } @@ -50,18 +57,52 @@ public class ClientAuthBackupDialogFragment extends DialogFragment { etFilename = new NoPersonalizedLearningEditText(ad.getContext(), null); etFilename.setSingleLine(true); etFilename.setHint(R.string.v3_backup_name_hint); + if (savedInstanceState != null) + etFilename.setText(savedInstanceState.getString(BUNDLE_KEY_FILENAME, "")); + fileNameTextWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + ad.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(!TextUtils.isEmpty(s.toString().trim())); + } + }; + etFilename.addTextChangedListener(fileNameTextWatcher); etFilename.setLayoutParams(params); container.addView(etFilename); ad.setView(container); return ad; }
+ @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putString(BUNDLE_KEY_FILENAME, etFilename.getText().toString()); + } + + + @Override + public void onStart() { + super.onStart(); + fileNameTextWatcher.afterTextChanged(etFilename.getEditableText()); + } + + + private void doBackup() { String filename = etFilename.getText().toString().trim(); - if (filename.equals("")) filename = "filename"; - filename += ".auth_private"; + if (!filename.endsWith(ClientAuthActivity.CLIENT_AUTH_FILE_EXTENSION)) + filename += ClientAuthActivity.CLIENT_AUTH_FILE_EXTENSION; if (DiskUtils.supportsStorageAccessFramework()) { - Intent createFileIntent = DiskUtils.createWriteFileIntent(filename, "text/*"); + Intent createFileIntent = DiskUtils.createWriteFileIntent(filename, ClientAuthActivity.CLIENT_AUTH_SAF_MIME_TYPE); getActivity().startActivityForResult(createFileIntent, REQUEST_CODE_WRITE_FILE); } else { // APIs 16, 17, 18 attemptToWriteBackup(Uri.fromFile(new File(DiskUtils.getOrCreateLegacyBackupDir("Orbot"), filename)));
tor-commits@lists.torproject.org