commit 894c7ba11e1357833e4f40f2988ba856c96ae487
Author: bim <dsnake(a)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)));