tor-commits
Threads by month
- ----- 2025 -----
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
December 2021
- 15 participants
- 1464 discussions
commit 85dba3bf440f68ba1036dda596f4adceea1b5d94
Author: bim <dsnake(a)protonmail.com>
Date: Sat Nov 28 12:46:28 2020 -0500
Battery permissions on v3 services
---
.../android/ui/v3onionservice/OnionServicesActivity.java | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServicesActivity.java b/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServicesActivity.java
index ba06b7c0..64a014e4 100644
--- a/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServicesActivity.java
+++ b/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServicesActivity.java
@@ -26,6 +26,7 @@ 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 org.torproject.android.ui.hiddenservices.permissions.PermissionManager;
import java.io.File;
@@ -161,8 +162,16 @@ public class OnionServicesActivity extends AppCompatActivity {
@Override
public void onChange(boolean selfChange) {
- mAdapter.changeCursor(mContentResolver.query(OnionServiceContentProvider.CONTENT_URI, OnionServiceContentProvider.PROJECTION, BASE_WHERE_SELECTION_CLAUSE + '1', null, null));
- // todo battery optimization stuff if lollipop or higher and running onion services
+ filterServices(radioShowUserServices.isChecked()); // updates adapter
+ if (!PermissionManager.isLollipopOrHigher()) return;
+ Cursor activeServices = mContentResolver.query(OnionServiceContentProvider.CONTENT_URI, OnionServiceContentProvider.PROJECTION,
+ OnionServiceContentProvider.OnionService.ENABLED + "=1", null, null);
+ if (activeServices == null) return;
+ if (activeServices.getCount() > 0)
+ PermissionManager.requestBatteryPermissions(OnionServicesActivity.this, getApplicationContext());
+ else
+ PermissionManager.requestDropBatteryPermissions(OnionServicesActivity.this, getApplicationContext());
+ activeServices.close();
}
}
1
0

[orbot/master] altered code that will break with gradle 5 (resource IDs will be declared non-final in Java)
by n8fr8@torproject.org 22 Dec '21
by n8fr8@torproject.org 22 Dec '21
22 Dec '21
commit fe69a3156a4ea5e9e1af38e32eb881b51c436d71
Author: bim <dsnake(a)protonmail.com>
Date: Wed Feb 3 11:45:51 2021 -0500
altered code that will break with gradle 5 (resource IDs will be declared non-final in Java)
---
.../ui/hiddenservices/HiddenServicesActivity.java | 13 ++---
.../ui/onboarding/CustomBridgesActivity.java | 66 +++++++---------------
2 files changed, 24 insertions(+), 55 deletions(-)
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java
index 62b3613b..6c780dde 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java
@@ -166,15 +166,10 @@ public class HiddenServicesActivity extends AppCompatActivity {
}
public void onRadioButtonClick(View view) {
- switch (view.getId()) {
- case R.id.radioUserServices:
- filterServices(true);
- break;
- case R.id.radioAppServices:
- filterServices(false);
- break;
- default:
- break;
+ if (view.getId() == R.id.radioUserServices) {
+ filterServices(true);
+ } else if (view.getId() == R.id.radioAppServices) {
+ filterServices(false);
}
}
diff --git a/app/src/main/java/org/torproject/android/ui/onboarding/CustomBridgesActivity.java b/app/src/main/java/org/torproject/android/ui/onboarding/CustomBridgesActivity.java
index a8eeb30f..6fce9852 100644
--- a/app/src/main/java/org/torproject/android/ui/onboarding/CustomBridgesActivity.java
+++ b/app/src/main/java/org/torproject/android/ui/onboarding/CustomBridgesActivity.java
@@ -40,7 +40,7 @@ import java.net.URLEncoder;
import static org.torproject.android.MainConstants.EMAIL_TOR_BRIDGES;
import static org.torproject.android.MainConstants.URL_TOR_BRIDGES;
-public class CustomBridgesActivity extends AppCompatActivity implements View.OnClickListener, TextWatcher {
+public class CustomBridgesActivity extends AppCompatActivity implements TextWatcher {
private EditText mEtPastedBridges;
@@ -75,7 +75,7 @@ public class CustomBridgesActivity extends AppCompatActivity implements View.OnC
((TextView) findViewById(R.id.tvDescription)).setText(getString(R.string.in_a_browser, URL_TOR_BRIDGES));
- findViewById(R.id.btCopyUrl).setOnClickListener(this);
+ findViewById(R.id.btCopyUrl).setOnClickListener(v -> ClipboardUtils.copyToClipboard("bridge_url", URL_TOR_BRIDGES, getString(R.string.done), this));
String bridges = Prefs.getBridgesList().trim();
if (!Prefs.bridgesEnabled() || userHasSetPreconfiguredBridge(bridges)) {
@@ -86,62 +86,36 @@ public class CustomBridgesActivity extends AppCompatActivity implements View.OnC
configureMultilineEditTextInScrollView(mEtPastedBridges);
mEtPastedBridges.setText(bridges);
mEtPastedBridges.addTextChangedListener(this);
+ final IntentIntegrator integrator = new IntentIntegrator(this);
- findViewById(R.id.btScanQr).setOnClickListener(this);
- findViewById(R.id.btShareQr).setOnClickListener(this);
- findViewById(R.id.btEmail).setOnClickListener(this);
+ findViewById(R.id.btScanQr).setOnClickListener(v -> integrator.initiateScan());
+ findViewById(R.id.btShareQr).setOnClickListener(v -> {
+ String setBridges = Prefs.getBridgesList();
+ if (!TextUtils.isEmpty(setBridges)) {
+ try {
+ integrator.shareText("bridge://" + URLEncoder.encode(setBridges, "UTF-8"));
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ findViewById(R.id.btEmail).setOnClickListener(v -> {
+ Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:" + EMAIL_TOR_BRIDGES));
+ emailIntent.putExtra(Intent.EXTRA_SUBJECT, "get transport");
+ emailIntent.putExtra(Intent.EXTRA_TEXT, "get transport");
+ startActivity(Intent.createChooser(emailIntent, getString(R.string.send_email)));
+ });
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
-
return true;
}
-
return super.onOptionsItemSelected(item);
}
- @Override
- public void onClick(View view) {
- IntentIntegrator integrator = new IntentIntegrator(this);
-
- switch (view.getId()) {
- case R.id.btCopyUrl:
- ClipboardUtils.copyToClipboard("bridge_url", URL_TOR_BRIDGES, getString(R.string.done), this);
- break;
-
- case R.id.btScanQr:
- integrator.initiateScan();
- break;
-
- case R.id.btShareQr:
- String bridges = Prefs.getBridgesList();
-
- if (!TextUtils.isEmpty(bridges)) {
- try {
- bridges = "bridge://" + URLEncoder.encode(bridges, "UTF-8");
-
- integrator.shareText(bridges);
-
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- }
-
- break;
-
- case R.id.btEmail:
- Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:" + EMAIL_TOR_BRIDGES));
- emailIntent.putExtra(Intent.EXTRA_SUBJECT, "get transport");
- emailIntent.putExtra(Intent.EXTRA_TEXT, "get transport");
- startActivity(Intent.createChooser(emailIntent, getString(R.string.send_email)));
-
- break;
- }
- }
-
@Override
protected void onActivityResult(int request, int response, Intent data) {
super.onActivityResult(request, response, data);
1
0
commit 7ce301042cd9a56155b764f1e18f7396bc21b8fc
Author: bim <dsnake(a)protonmail.com>
Date: Sat Nov 14 20:59:02 2020 -0500
Initial work for V3 UI, DB Stuff, etc
---
app/src/main/AndroidManifest.xml | 14 +
.../org/torproject/android/OrbotMainActivity.java | 33 +-
.../ui/hiddenservices/HiddenServicesActivity.java | 6 +-
.../hiddenservices/adapters/OnionListAdapter.java | 7 +-
.../ui/hiddenservices/dialogs/HSDeleteDialog.java | 6 +-
.../permissions/PermissionManager.java | 14 +-
.../providers/HSContentProvider.java | 6 +-
.../DeleteOnionServiceDialogFragment.java | 41 +++
.../NewOnionServiceDialogFragment.java | 98 +++++
.../OnionServiceActionsDialogFragment.java | 93 +++++
.../OnionServiceContentProvider.java | 117 ++++++
.../ui/v3onionservice/OnionServiceDatabase.java | 38 ++
.../ui/v3onionservice/OnionServicesActivity.java | 98 +++++
.../ui/v3onionservice/OnionV3ListAdapter.java | 54 +++
app/src/main/res/menu/orbot_main.xml | 125 ++++---
app/src/main/res/values/strings.xml | 2 +
.../java/org/torproject/android/core/DiskUtils.kt | 8 +-
.../torproject/android/service/OrbotService.java | 408 +++++++--------------
.../android/service/TorServiceConstants.java | 2 +-
19 files changed, 797 insertions(+), 373 deletions(-)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index a9db7611..7b81951f 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -92,6 +92,15 @@
android:value=".OrbotMainActivity" />
</activity>
+ <activity
+ android:name=".ui.v3onionservice.OnionServicesActivity"
+ android:label="@string/hidden_services"
+ android:theme="@style/DefaultTheme">
+ <meta-data
+ android:name="android.support.PARENT_ACTIVITY"
+ android:value=".OrbotMainActivity" />
+ </activity>
+
<activity
android:name=".ui.hiddenservices.ClientCookiesActivity"
android:label="@string/client_cookies"
@@ -123,6 +132,11 @@
android:authorities="org.torproject.android.ui.hiddenservices.providers"
android:exported="false" />
+ <provider
+ android:name=".ui.v3onionservice.OnionServiceContentProvider"
+ android:authorities="org.torproject.android.ui.v3onionservice"
+ android:exported="false" />
+
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="org.torproject.android.ui.hiddenservices.storage"
diff --git a/app/src/main/java/org/torproject/android/OrbotMainActivity.java b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
index 1ee58106..abc87cc0 100644
--- a/app/src/main/java/org/torproject/android/OrbotMainActivity.java
+++ b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
@@ -74,6 +74,7 @@ import org.torproject.android.ui.hiddenservices.permissions.PermissionManager;
import org.torproject.android.ui.hiddenservices.providers.HSContentProvider;
import org.torproject.android.ui.onboarding.BridgeWizardActivity;
import org.torproject.android.ui.onboarding.OnboardingActivity;
+import org.torproject.android.ui.v3onionservice.OnionServicesActivity;
import java.io.File;
import java.io.UnsupportedEncodingException;
@@ -114,6 +115,9 @@ public class OrbotMainActivity extends AppCompatActivity implements OrbotConstan
private static final int MESSAGE_PORTS = 3;
private static final float ROTATE_FROM = 0.0f;
private static final float ROTATE_TO = 360.0f * 4f;// 3.141592654f * 32.0f;
+ // this is what takes messages or values from the callback threads or other non-mainUI threads
+ // and passes them back into the main UI thread for display to the user
+ private final Handler mStatusUpdateHandler = new MainActivityStatusUpdateHandler(this);
PulsatorLayout mPulsator;
AlertDialog aDialog = null;
/* Useful UI bits */
@@ -131,11 +135,6 @@ public class OrbotMainActivity extends AppCompatActivity implements OrbotConstan
/* Some tracking bits */
private String torStatus = null; //latest status reported from the tor service
private Intent lastStatusIntent; // the last ACTION_STATUS Intent received
- private SharedPreferences mPrefs = null;
- private boolean autoStartFromIntent = false;
- // this is what takes messages or values from the callback threads or other non-mainUI threads
- // and passes them back into the main UI thread for display to the user
- private final Handler mStatusUpdateHandler = new MainActivityStatusUpdateHandler(this);
/**
* The state and log info from {@link OrbotService} are sent to the UI here in
* the form of a local broadcast. Regular broadcasts can be sent by any app,
@@ -202,6 +201,8 @@ public class OrbotMainActivity extends AppCompatActivity implements OrbotConstan
}
}
};
+ private SharedPreferences mPrefs = null;
+ private boolean autoStartFromIntent = false;
private void migratePreferences() {
String hsPortString = mPrefs.getString("pref_hs_ports", "");
@@ -463,6 +464,8 @@ public class OrbotMainActivity extends AppCompatActivity implements OrbotConstan
}
}
+ } else if (item.getItemId() == R.id.menu_v3_onion_services) {
+ startActivity(new Intent(this, OnionServicesActivity.class));
} else if (item.getItemId() == R.id.menu_hidden_services) {
startActivity(new Intent(this, HiddenServicesActivity.class));
} else if (item.getItemId() == R.id.menu_client_cookies) {
@@ -534,12 +537,8 @@ public class OrbotMainActivity extends AppCompatActivity implements OrbotConstan
sendIntentToService(ACTION_START_VPN);
}
- private void enableHiddenServicePort(
- String hsName, final int hsPort, int hsRemotePort,
- final String backupToPackage, final Uri hsKeyPath,
- final Boolean authCookie
- ) {
-
+ private void enableHiddenServicePort(String hsName, final int hsPort, int hsRemotePort,
+ final String backupToPackage, final Uri hsKeyPath, final Boolean authCookie) {
String onionHostname = null;
if (hsName == null)
@@ -687,9 +686,9 @@ public class OrbotMainActivity extends AppCompatActivity implements OrbotConstan
};
String requestMsg = getString(R.string.hidden_service_request, String.valueOf(hiddenServicePort));
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setMessage(requestMsg).setPositiveButton("Allow", dialogClickListener)
- .setNegativeButton("Deny", dialogClickListener).show();
+ new AlertDialog.Builder(this).setMessage(requestMsg)
+ .setPositiveButton(R.string.allow, dialogClickListener)
+ .setNegativeButton(R.string.deny, dialogClickListener).show();
return; //don't null the setIntent() as we need it later
@@ -1103,12 +1102,14 @@ public class OrbotMainActivity extends AppCompatActivity implements OrbotConstan
imgStatus.startAnimation(rotation);
lblStatus.setText(getString(R.string.newnym));
break;
- case STATUS_STARTING: return; // tor is starting up, a new identity isn't needed
+ case STATUS_STARTING:
+ return; // tor is starting up, a new identity isn't needed
case STATUS_OFF:
case STATUS_STOPPING:
startTor();
break;
- default: break;
+ default:
+ break;
}
}
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java
index 6c780dde..d7429181 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java
@@ -61,13 +61,9 @@ public class HiddenServicesActivity extends AppCompatActivity {
mResolver = getContentResolver();
fab = findViewById(R.id.fab);
- fab.setOnClickListener(view -> {
- HSDataDialog dialog = new HSDataDialog();
- dialog.show(getSupportFragmentManager(), "HSDataDialog");
- });
+ fab.setOnClickListener(view -> new HSDataDialog().show(getSupportFragmentManager(), "HSDataDialog"));
mAdapter = new OnionListAdapter(this, mResolver.query(HSContentProvider.CONTENT_URI, HSContentProvider.PROJECTION, mWhere, null, null), 0);
-
mResolver.registerContentObserver(HSContentProvider.CONTENT_URI, true, new HSObserver(new Handler()));
ListView onion_list = findViewById(R.id.onion_list);
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/adapters/OnionListAdapter.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/adapters/OnionListAdapter.java
index d4e39ece..e3983cfd 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/adapters/OnionListAdapter.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/adapters/OnionListAdapter.java
@@ -25,8 +25,7 @@ public class OnionListAdapter extends CursorAdapter {
}
@Override
- public void bindView(View view, Context context, Cursor cursor) {
- final Context mContext = context;
+ public void bindView(View view, final Context context, Cursor cursor) {
int id = cursor.getInt(cursor.getColumnIndex(HSContentProvider.HiddenService._ID));
final String where = HSContentProvider.HiddenService._ID + "=" + id;
@@ -40,12 +39,12 @@ public class OnionListAdapter extends CursorAdapter {
SwitchCompat enabled = view.findViewById(R.id.hs_switch);
enabled.setChecked(cursor.getInt(cursor.getColumnIndex(HSContentProvider.HiddenService.ENABLED)) == 1);
enabled.setOnCheckedChangeListener((buttonView, isChecked) -> {
- ContentResolver resolver = mContext.getContentResolver();
+ ContentResolver resolver = context.getContentResolver();
ContentValues fields = new ContentValues();
fields.put(HSContentProvider.HiddenService.ENABLED, isChecked);
resolver.update(HSContentProvider.CONTENT_URI, fields, where, null);
- Toast.makeText(mContext, R.string.please_restart_Orbot_to_enable_the_changes, Toast.LENGTH_LONG).show();
+ Toast.makeText(context, R.string.please_restart_Orbot_to_enable_the_changes, Toast.LENGTH_LONG).show();
});
}
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSDeleteDialog.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSDeleteDialog.java
index d26141a0..f4a96226 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSDeleteDialog.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSDeleteDialog.java
@@ -20,11 +20,9 @@ public class HSDeleteDialog extends DialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
- final Bundle arguments = getArguments();
- final Context context = getContext();
- return new AlertDialog.Builder(context)
+ return new AlertDialog.Builder(getContext())
.setTitle(R.string.confirm_service_deletion)
- .setPositiveButton(android.R.string.ok, (dialog, which) -> doDelete(arguments, context))
+ .setPositiveButton(android.R.string.ok, (dialog, which) -> doDelete(getArguments(), getContext()))
.setNegativeButton(android.R.string.cancel, (dialog, which) -> dialog.cancel())
.create();
}
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/permissions/PermissionManager.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/permissions/PermissionManager.java
index 6d181967..52c5dc20 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/permissions/PermissionManager.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/permissions/PermissionManager.java
@@ -23,9 +23,8 @@ public class PermissionManager {
@TargetApi(Build.VERSION_CODES.M)
public static void requestBatteryPermissions(FragmentActivity activity, Context context) {
- final Context mContext = context;
- final String packageName = mContext.getPackageName();
- PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ final String packageName = context.getPackageName();
+ PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (pm.isIgnoringBatteryOptimizations(packageName))
return;
@@ -37,18 +36,15 @@ public class PermissionManager {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + packageName));
- mContext.startActivity(intent);
+ context.startActivity(intent);
}).show();
}
@TargetApi(Build.VERSION_CODES.M)
public static void requestDropBatteryPermissions(FragmentActivity activity, Context context) {
- final Context mContext = context;
-
- final String packageName = context.getPackageName();
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- if (!pm.isIgnoringBatteryOptimizations(packageName))
+ if (!pm.isIgnoringBatteryOptimizations(context.getPackageName()))
return;
Snackbar.make(activity.findViewById(android.R.id.content),
@@ -57,7 +53,7 @@ public class PermissionManager {
v -> {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
- mContext.startActivity(intent);
+ context.startActivity(intent);
}).show();
}
}
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/providers/HSContentProvider.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/providers/HSContentProvider.java
index 87cad0ad..79b566fd 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/providers/HSContentProvider.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/providers/HSContentProvider.java
@@ -27,8 +27,7 @@ public class HSContentProvider extends ContentProvider {
HiddenService.ENABLED
};
private static final String AUTH = "org.torproject.android.ui.hiddenservices.providers";
- public static final Uri CONTENT_URI =
- Uri.parse("content://" + AUTH + "/hs");
+ public static final Uri CONTENT_URI = Uri.parse("content://" + AUTH + "/hs");
//UriMatcher
private static final int ONIONS = 1;
private static final int ONION_ID = 2;
@@ -61,8 +60,7 @@ public class HSContentProvider extends ContentProvider {
SQLiteDatabase db = mServervices.getReadableDatabase();
- return db.query(HSDatabase.HS_DATA_TABLE_NAME, projection, where,
- selectionArgs, null, null, sortOrder);
+ return db.query(HSDatabase.HS_DATA_TABLE_NAME, projection, where, selectionArgs, null, null, sortOrder);
}
@Nullable
diff --git a/app/src/main/java/org/torproject/android/ui/v3onionservice/DeleteOnionServiceDialogFragment.java b/app/src/main/java/org/torproject/android/ui/v3onionservice/DeleteOnionServiceDialogFragment.java
new file mode 100644
index 00000000..5028e8f3
--- /dev/null
+++ b/app/src/main/java/org/torproject/android/ui/v3onionservice/DeleteOnionServiceDialogFragment.java
@@ -0,0 +1,41 @@
+package org.torproject.android.ui.v3onionservice;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
+
+import org.torproject.android.R;
+import org.torproject.android.core.DiskUtils;
+import org.torproject.android.service.TorServiceConstants;
+import org.torproject.android.ui.hiddenservices.HiddenServicesActivity;
+
+import java.io.File;
+
+public class DeleteOnionServiceDialogFragment extends DialogFragment {
+ DeleteOnionServiceDialogFragment(Bundle arguments) {
+ super();
+ setArguments(arguments);
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+ return new AlertDialog.Builder(getContext())
+ .setTitle(R.string.confirm_service_deletion)
+ .setPositiveButton(android.R.string.ok, (dialog, which) -> doDelete(getArguments(), getContext()))
+ .setNegativeButton(android.R.string.cancel, (dialog, which) -> dialog.cancel())
+ .create();
+ }
+
+ private void doDelete(Bundle arguments, Context context) {
+ context.getContentResolver().delete(OnionServiceContentProvider.CONTENT_URI, OnionServiceContentProvider.OnionService._ID + '=' + arguments.getInt(OnionServicesActivity.BUNDLE_KEY_ID), null);
+ String base = context.getFilesDir().getAbsolutePath() + "/" + TorServiceConstants.ONION_SERVICES_DIR;
+ DiskUtils.recursivelyDeleteDirectory(new File(base, "v3" + arguments.getString(OnionServicesActivity.BUNDLE_KEY_PORT)));
+ }
+
+}
diff --git a/app/src/main/java/org/torproject/android/ui/v3onionservice/NewOnionServiceDialogFragment.java b/app/src/main/java/org/torproject/android/ui/v3onionservice/NewOnionServiceDialogFragment.java
new file mode 100644
index 00000000..1929eb72
--- /dev/null
+++ b/app/src/main/java/org/torproject/android/ui/v3onionservice/NewOnionServiceDialogFragment.java
@@ -0,0 +1,98 @@
+package org.torproject.android.ui.v3onionservice;
+
+import android.app.Dialog;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
+
+import org.torproject.android.R;
+
+public class NewOnionServiceDialogFragment extends DialogFragment {
+
+ private EditText etServer, etLocalPort, etOnionPort;
+ private TextWatcher inputValidator;
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ inputValidator.afterTextChanged(null); // initially disable positive button
+ }
+
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final View dialogView = getActivity().getLayoutInflater().inflate(R.layout.layout_hs_data_dialog, null);
+ dialogView.findViewById(R.id.hsAuth).setVisibility(View.GONE);
+ etServer = dialogView.findViewById(R.id.hsName);
+ etLocalPort = dialogView.findViewById(R.id.hsLocalPort);
+ etOnionPort = dialogView.findViewById(R.id.hsOnionPort);
+
+ AlertDialog alertDialog = new AlertDialog.Builder(getActivity())
+ .setTitle(R.string.hidden_services)
+ .setNegativeButton(android.R.string.cancel, (dialog, which) -> dialog.cancel())
+ .setPositiveButton(R.string.save, (dialog, which) -> doSave(getContext()))
+ .setView(dialogView)
+ .create();
+
+
+ inputValidator = new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) { // no-op
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) { //no-op
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ Button btn = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
+ try {
+ int localPort = Integer.parseInt(etLocalPort.getText().toString());
+ int onionPort = Integer.parseInt(etOnionPort.getText().toString());
+ btn.setEnabled(checkInput(localPort, onionPort));
+ } catch (NumberFormatException nfe) {
+ btn.setEnabled(false);
+ }
+ }
+ };
+
+ etServer.addTextChangedListener(inputValidator);
+ etLocalPort.addTextChangedListener(inputValidator);
+ etOnionPort.addTextChangedListener(inputValidator);
+ return alertDialog;
+ }
+
+ private boolean checkInput(int local, int remote) {
+ if ((local < 1 || local > 65535) || (remote < 1 || remote > 65535)) return false;
+ return !TextUtils.isEmpty(etServer.getText().toString().trim());
+ }
+
+ private void doSave(Context context) {
+ String serverName = etServer.getText().toString().trim();
+ int localPort = Integer.parseInt(etLocalPort.getText().toString());
+ int onionPort = Integer.parseInt(etOnionPort.getText().toString());
+ ContentValues fields = new ContentValues();
+ fields.put(OnionServiceContentProvider.OnionService.NAME, serverName);
+ fields.put(OnionServiceContentProvider.OnionService.PORT, localPort);
+ fields.put(OnionServiceContentProvider.OnionService.ONION_PORT, onionPort);
+ fields.put(OnionServiceContentProvider.OnionService.CREATED_BY_USER, 1);
+ ContentResolver cr = getContext().getContentResolver();
+ cr.insert(OnionServiceContentProvider.CONTENT_URI, fields);
+ Toast.makeText(context, R.string.please_restart_Orbot_to_enable_the_changes, Toast.LENGTH_LONG).show();
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServiceActionsDialogFragment.java b/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServiceActionsDialogFragment.java
new file mode 100644
index 00000000..822a45f2
--- /dev/null
+++ b/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServiceActionsDialogFragment.java
@@ -0,0 +1,93 @@
+package org.torproject.android.ui.v3onionservice;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
+
+import org.torproject.android.R;
+import org.torproject.android.core.ClipboardUtils;
+import org.torproject.android.core.DiskUtils;
+import org.torproject.android.ui.hiddenservices.backup.BackupUtils;
+
+import java.io.File;
+
+public class OnionServiceActionsDialogFragment extends DialogFragment {
+
+ private static final int REQUEST_CODE_WRITE_FILE = 343;
+
+ OnionServiceActionsDialogFragment(Bundle arguments) {
+ super();
+ setArguments(arguments);
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ Bundle arguments = getArguments();
+ AlertDialog ad = new AlertDialog.Builder(getActivity())
+ .setItems(new CharSequence[]{
+ getString(R.string.copy_address_to_clipboard),
+ getString(R.string.backup_service),
+ getString(R.string.delete_service)}, null)
+ .setNegativeButton(android.R.string.cancel, (dialog, which) -> dialog.dismiss())
+ .setTitle(R.string.hidden_services)
+ .create();
+
+ // done this way so we can startActivityForResult on backup without the dialog vanishing
+ ad.getListView().setOnItemClickListener((parent, view, position, id) -> {
+ if (position == 0) doCopy(arguments, getContext());
+ else if (position == 1) doBackup(arguments, getContext());
+ else if (position == 2)
+ new DeleteOnionServiceDialogFragment(arguments).show(getFragmentManager(), DeleteOnionServiceDialogFragment.class.getSimpleName());
+ if (position != 1) dismiss();
+ });
+ return ad;
+ }
+
+ private void doCopy(Bundle arguments, Context context) {
+ String onion = arguments.getString(OnionServicesActivity.BUNDLE_KEY_DOMAIN);
+ if (onion == null)
+ Toast.makeText(context, R.string.please_restart_Orbot_to_enable_the_changes, Toast.LENGTH_LONG).show();
+ else
+ ClipboardUtils.copyToClipboard("onion", onion, getString(R.string.done), context);
+ }
+
+ private void doBackup(Bundle arguments, Context context) {
+ String filename = "onion_service" + arguments.getInt(OnionServicesActivity.BUNDLE_KEY_PORT) + ".zip";
+ if (arguments.getString(OnionServicesActivity.BUNDLE_KEY_DOMAIN) == null) {
+ Toast.makeText(context, R.string.please_restart_Orbot_to_enable_the_changes, Toast.LENGTH_LONG).show();
+ return;
+ }
+ if (DiskUtils.supportsStorageAccessFramework()) {
+ Intent createFileIntent = DiskUtils.createWriteFileIntent(filename, "application/zip");
+ startActivityForResult(createFileIntent, REQUEST_CODE_WRITE_FILE);
+ } else { // APIs 16, 17, 18
+ attemptToWriteBackup(Uri.fromFile(new File(DiskUtils.getOrCreateLegacyBackupDir(), filename)));
+ }
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == REQUEST_CODE_WRITE_FILE && resultCode == Activity.RESULT_OK) {
+ if (data != null) {
+ attemptToWriteBackup(data.getData());
+ }
+ }
+ }
+
+ private void attemptToWriteBackup(Uri outputFile) {
+ BackupUtils backupUtils = new BackupUtils(getContext());
+// String backup = backupUtils.createZipBackup(port, outputFile); TODO need to break apart backup logic for v2 and v3 onions
+ Toast.makeText(getContext(), backup != null ? R.string.backup_saved_at_external_storage : R.string.error, Toast.LENGTH_LONG).show();
+ dismiss();
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServiceContentProvider.java b/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServiceContentProvider.java
new file mode 100644
index 00000000..d61f7935
--- /dev/null
+++ b/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServiceContentProvider.java
@@ -0,0 +1,117 @@
+package org.torproject.android.ui.v3onionservice;
+
+import android.content.ContentProvider;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.UriMatcher;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.net.Uri;
+import android.provider.BaseColumns;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+public class OnionServiceContentProvider extends ContentProvider {
+
+ public static final String[] PROJECTION = {
+ OnionService._ID,
+ OnionService.NAME,
+ OnionService.PORT,
+ OnionService.DOMAIN,
+ OnionService.ONION_PORT,
+ OnionService.CREATED_BY_USER,
+ OnionService.ENABLED
+ };
+
+ private static final int ONIONS = 1, ONION_ID = 2;
+ private static final String AUTH = "org.torproject.android.ui.v3onionservice";
+ public static final Uri CONTENT_URI = Uri.parse("content://" + AUTH + "/v3");
+ private static final UriMatcher uriMatcher;
+
+ static {
+ uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+ uriMatcher.addURI(AUTH, "v3", ONIONS);
+ uriMatcher.addURI(AUTH, "v3/#", ONION_ID);
+ }
+
+ private OnionServiceDatabase mDatabase;
+
+ @Override
+ public boolean onCreate() {
+ mDatabase = new OnionServiceDatabase(getContext());
+ return true;
+ }
+
+ @Nullable
+ @Override
+ public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
+ String where = selection;
+ if (uriMatcher.match(uri) == ONION_ID) {
+ where = "_id=" + uri.getLastPathSegment();
+ }
+
+ SQLiteDatabase db = mDatabase.getReadableDatabase();
+ return db.query(OnionServiceDatabase.ONION_SERVICE_TABLE_NAME, projection, where, selectionArgs, null, null, sortOrder);
+ }
+
+ @Nullable
+ @Override
+ public String getType(@NonNull Uri uri) {
+ int match = uriMatcher.match(uri);
+ switch (match) {
+ case ONIONS:
+ return "vnd.android.cursor.dir/vnd.torproject.onions";
+ case ONION_ID:
+ return "vnd.android.cursor.item/vnd.torproject.onion";
+ default:
+ return null;
+ }
+ }
+
+ @Nullable
+ @Override
+ public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
+ SQLiteDatabase db = mDatabase.getWritableDatabase();
+ long regId = db.insert(OnionServiceDatabase.ONION_SERVICE_TABLE_NAME, null, values);
+ getContext().getContentResolver().notifyChange(CONTENT_URI, null);
+ return ContentUris.withAppendedId(CONTENT_URI, regId);
+ }
+
+ @Override
+ public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
+ if (uriMatcher.match(uri) == ONION_ID) {
+ selection = "_id=" + uri.getLastPathSegment();
+ }
+ SQLiteDatabase db = mDatabase.getWritableDatabase();
+ int rows = db.delete(OnionServiceDatabase.ONION_SERVICE_TABLE_NAME, selection, selectionArgs);
+ getContext().getContentResolver().notifyChange(CONTENT_URI, null);
+ return rows;
+ }
+
+ @Override
+ public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
+ SQLiteDatabase db = mDatabase.getWritableDatabase();
+ String where = selection;
+ if (uriMatcher.match(uri) == ONION_ID) {
+ where = "_id=" + uri.getLastPathSegment();
+ }
+
+ int rows = db.update(OnionServiceDatabase.ONION_SERVICE_TABLE_NAME, values, where, null);
+ getContext().getContentResolver().notifyChange(CONTENT_URI, null);
+ return rows;
+ }
+
+ public static final class OnionService implements BaseColumns {
+ public static final String NAME = "name";
+ public static final String PORT = "port";
+ public static final String ONION_PORT = "onion_port";
+ public static final String DOMAIN = "domain";
+ public static final String CREATED_BY_USER = "created_by_user";
+ public static final String ENABLED = "enabled";
+
+ private OnionService() { // no-op
+ }
+ }
+
+}
diff --git a/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServiceDatabase.java b/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServiceDatabase.java
new file mode 100644
index 00000000..f2a812e8
--- /dev/null
+++ b/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServiceDatabase.java
@@ -0,0 +1,38 @@
+package org.torproject.android.ui.v3onionservice;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+
+public class OnionServiceDatabase extends SQLiteOpenHelper {
+
+ static final String DATABASE_NAME = "onion_service",
+ ONION_SERVICE_TABLE_NAME = "onion_services";
+ private static final int DATABASE_VERSION = 1;
+
+ private static final String ONION_SERVICES_CREATE_SQL =
+ "CREATE TABLE " + ONION_SERVICE_TABLE_NAME + " (" +
+ "_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
+ "name TEXT, " +
+ "domain TEXT, " +
+ "onion_port INTEGER, " +
+ "created_by_user INTEGER DEFAULT 0, " +
+ "enabled INTEGER DEFAULT 1, " +
+ "port INTEGER);";
+
+ public OnionServiceDatabase(Context context) {
+ super(context, DATABASE_NAME, null, DATABASE_VERSION);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ db.execSQL(ONION_SERVICES_CREATE_SQL);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+
+ }
+
+
+}
diff --git a/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServicesActivity.java b/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServicesActivity.java
new file mode 100644
index 00000000..3be04731
--- /dev/null
+++ b/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServicesActivity.java
@@ -0,0 +1,98 @@
+package org.torproject.android.ui.v3onionservice;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.ListView;
+import android.widget.RadioButton;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+
+import com.google.android.material.floatingactionbutton.FloatingActionButton;
+
+import org.torproject.android.R;
+import org.torproject.android.core.DiskUtils;
+import org.torproject.android.core.LocaleHelper;
+
+public class OnionServicesActivity extends AppCompatActivity {
+
+ static final String BUNDLE_KEY_ID = "id", BUNDLE_KEY_PORT = "port", BUNDLE_KEY_DOMAIN = "domain";
+ private static final String WHERE_SELECTION_CLAUSE = OnionServiceContentProvider.OnionService.CREATED_BY_USER + "=1";
+ private RadioButton radioShowUserServices, radioShowAppServices;
+ private FloatingActionButton fab;
+ private ContentResolver mContentResolver;
+ private OnionV3ListAdapter mAdapter;
+
+ @Override
+ public void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
+ setContentView(R.layout.layout_hs_list_view);
+
+ Toolbar toolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+ fab = findViewById(R.id.fab);
+ fab.setOnClickListener(v -> new NewOnionServiceDialogFragment().show(getSupportFragmentManager(), "NewOnionServiceDialogFragment"));
+
+ mContentResolver = getContentResolver();
+ mAdapter = new OnionV3ListAdapter(this, mContentResolver.query(OnionServiceContentProvider.CONTENT_URI, OnionServiceContentProvider.PROJECTION, WHERE_SELECTION_CLAUSE, null, null), 0);
+ mContentResolver.registerContentObserver(OnionServiceContentProvider.CONTENT_URI, true, new OnionServiceObserver(new Handler()));
+
+ ListView onionList = findViewById(R.id.onion_list);
+ onionList.setAdapter(mAdapter);
+ onionList.setOnItemClickListener((parent, view, position, id) -> {
+ Cursor item = (Cursor) parent.getItemAtPosition(position);
+ Bundle arguments = new Bundle();
+ arguments.putInt(BUNDLE_KEY_ID, item.getInt(item.getColumnIndex(OnionServiceContentProvider.OnionService._ID)));
+ arguments.putString(BUNDLE_KEY_PORT, item.getString(item.getColumnIndex(OnionServiceContentProvider.OnionService.PORT)));
+ arguments.putString(BUNDLE_KEY_DOMAIN, item.getString(item.getColumnIndex(OnionServiceContentProvider.OnionService.DOMAIN)));
+ OnionServiceActionsDialogFragment dialog = new OnionServiceActionsDialogFragment(arguments);
+ dialog.show(getSupportFragmentManager(), OnionServiceActionsDialogFragment.class.getSimpleName());
+ });
+ }
+
+ @Override
+ protected void attachBaseContext(Context base) {
+ super.attachBaseContext(LocaleHelper.onAttach(base));
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.hs_menu, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == R.id.menu_restore_backup) {
+ if (DiskUtils.supportsStorageAccessFramework()) {
+
+ } else { // 16, 17, 18
+
+ }
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ private class OnionServiceObserver extends ContentObserver {
+
+ OnionServiceObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ mAdapter.changeCursor(mContentResolver.query(OnionServiceContentProvider.CONTENT_URI, OnionServiceContentProvider.PROJECTION, WHERE_SELECTION_CLAUSE, null, null));
+ // todo battery optimization stuff if lollipop or higher and running onion services
+ }
+ }
+
+
+}
diff --git a/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionV3ListAdapter.java b/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionV3ListAdapter.java
new file mode 100644
index 00000000..c0489d3c
--- /dev/null
+++ b/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionV3ListAdapter.java
@@ -0,0 +1,54 @@
+package org.torproject.android.ui.v3onionservice;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CursorAdapter;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.appcompat.widget.SwitchCompat;
+
+import org.torproject.android.R;
+import org.torproject.android.ui.hiddenservices.providers.HSContentProvider;
+
+public class OnionV3ListAdapter extends CursorAdapter {
+
+ private final LayoutInflater mLayoutInflater;
+
+ OnionV3ListAdapter(Context context, Cursor cursor, int flags) {
+ super(context, cursor, flags);
+ mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ return mLayoutInflater.inflate(R.layout.layout_hs_list_item, parent, false);
+ }
+
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ int id = cursor.getInt(cursor.getColumnIndex(OnionServiceContentProvider.OnionService._ID));
+ final String where = OnionServiceContentProvider.OnionService._ID + "=" + id;
+ TextView port = view.findViewById(R.id.hs_port);
+ port.setText(cursor.getString(cursor.getColumnIndex(OnionServiceContentProvider.OnionService.PORT)));
+ TextView name = view.findViewById(R.id.hs_name);
+ name.setText(cursor.getString(cursor.getColumnIndex(OnionServiceContentProvider.OnionService.NAME)));
+ TextView domain = view.findViewById(R.id.hs_onion);
+ domain.setText(cursor.getString(cursor.getColumnIndex(OnionServiceContentProvider.OnionService.DOMAIN)));
+
+ SwitchCompat enabled = view.findViewById(R.id.hs_switch);
+ enabled.setChecked(cursor.getInt(cursor.getColumnIndex(OnionServiceContentProvider.OnionService.ENABLED)) == 1);
+ enabled.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ ContentResolver resolver = context.getContentResolver();
+ ContentValues fields = new ContentValues();
+ fields.put(OnionServiceContentProvider.OnionService.ENABLED, isChecked);
+ resolver.update(OnionServiceContentProvider.CONTENT_URI, fields, where, null);
+ Toast.makeText(context, R.string.please_restart_Orbot_to_enable_the_changes, Toast.LENGTH_LONG).show();
+ });
+ }
+}
diff --git a/app/src/main/res/menu/orbot_main.xml b/app/src/main/res/menu/orbot_main.xml
index 6359ebdc..2fb0ad4e 100644
--- a/app/src/main/res/menu/orbot_main.xml
+++ b/app/src/main/res/menu/orbot_main.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
/*
* Copyright (C) 2008 Esmertec AG.
* Copyright (C) 2008 The Android Open Source Project
@@ -18,77 +17,83 @@
*/
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:yourapp="http://schemas.android.com/apk/res-auto"
- >
+ xmlns:yourapp="http://schemas.android.com/apk/res-auto">
- <item android:id="@+id/menu_newnym"
- android:title="@string/menu_new_identity"
+ <item
+ android:id="@+id/menu_newnym"
android:icon="@drawable/ic_refresh_white_24dp"
- yourapp:showAsAction="always"
- />
+ android:title="@string/menu_new_identity"
+ yourapp:showAsAction="always" />
- <item android:id="@+id/menu_settings"
+ <item
+ android:id="@+id/menu_settings"
+ android:icon="@drawable/ic_action_settings"
android:title="@string/menu_settings"
- android:icon="@drawable/ic_action_settings"
- yourapp:showAsAction="never"
- />
+ yourapp:showAsAction="never" />
- <item
+ <item
android:title="@string/menu_qr"
- yourapp:showAsAction="never"
- >
- <menu>
- <item android:id="@+id/menu_scan"
- android:title="@string/menu_scan"
- yourapp:showAsAction="never"
- />
-
- <item android:id="@+id/menu_share_bridge"
- android:title="@string/menu_share_bridge"
- yourapp:showAsAction="never"
- />
- </menu>
- </item>
+ yourapp:showAsAction="never">
+ <menu>
+ <item
+ android:id="@+id/menu_scan"
+ android:title="@string/menu_scan"
+ yourapp:showAsAction="never" />
+
+ <item
+ android:id="@+id/menu_share_bridge"
+ android:title="@string/menu_share_bridge"
+ yourapp:showAsAction="never" />
+ </menu>
+ </item>
<item
android:title="@string/menu_hidden_services"
yourapp:showAsAction="never">
- <menu>
- <item android:id="@+id/menu_hidden_services"
- android:title="@string/hosted_services"
- yourapp:showAsAction="never"
- />
-
- <item android:id="@+id/menu_client_cookies"
- android:title="@string/client_cookies"
- yourapp:showAsAction="never"
- />
- </menu>
+ <menu>
+
+ <item
+ android:id="@+id/menu_v3_onion_services"
+ android:title="@string/hidden_services"
+ yourapp:showAsAction="never" />
+
+ <item
+ android:id="@+id/menu_hidden_services"
+ android:title="@string/hosted_services"
+ yourapp:showAsAction="never" />
+
+ <item
+ android:id="@+id/menu_client_cookies"
+ android:title="@string/client_cookies"
+ yourapp:showAsAction="never" />
+ </menu>
</item>
-
- <!--
- <item android:id="@+id/menu_promo_apps"
- android:title="@string/menu_promo_apps"
- android:icon="@drawable/ic_menu_goto"
- yourapp:showAsAction="never"
-
- />
- -->
-
- <item android:id="@+id/menu_about"
+
+ <!--
+ <item android:id="@+id/menu_promo_apps"
+ android:title="@string/menu_promo_apps"
+ android:icon="@drawable/ic_menu_goto"
+ yourapp:showAsAction="never"
+
+ />
+ -->
+
+ <item
+ android:id="@+id/menu_about"
+ android:icon="@drawable/ic_menu_about"
android:title="@string/menu_about"
- android:icon="@drawable/ic_menu_about"
- yourapp:showAsAction="never"
-
- />
-
- <item android:id="@+id/menu_exit"
+ yourapp:showAsAction="never"
+
+ />
+
+ <item
+ android:id="@+id/menu_exit"
+ android:icon="@drawable/ic_menu_exit"
android:title="@string/menu_exit"
- android:icon="@drawable/ic_menu_exit"
- yourapp:showAsAction="never"
-
- />
-
+ yourapp:showAsAction="never"
+
+ />
+
</menu>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index c9fc00a6..0501adf8 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -101,6 +101,8 @@
<string name="obfsproxy_version">Obfs4proxy: https://github.com/Yawning/obfs4</string>
<string name="openssl_version">OpenSSL: http://www.openssl.org</string>
<string name="hidden_service_request">An app wants to open onion server port %1$s to the Tor network. This is safe if you trust the app.</string>
+ <string name="allow">Allow</string>
+ <string name="deny">Deny</string>
<string name="found_existing_tor_process">found existing Tor process…</string>
<string name="something_bad_happened">Something bad happened. Check the log</string>
<string name="unable_to_read_hidden_service_name">unable to read onion service name</string>
diff --git a/appcore/src/main/java/org/torproject/android/core/DiskUtils.kt b/appcore/src/main/java/org/torproject/android/core/DiskUtils.kt
index 7e741695..be74aa4e 100644
--- a/appcore/src/main/java/org/torproject/android/core/DiskUtils.kt
+++ b/appcore/src/main/java/org/torproject/android/core/DiskUtils.kt
@@ -68,9 +68,15 @@ object DiskUtils {
@JvmStatic
fun getOrCreateLegacyBackupDir(): File? {
if (Environment.MEDIA_MOUNTED != Environment.getExternalStorageState()) return null
- val dir = File(Environment.getExternalStorageDirectory(), "Orbot")
+ val dir = File(Environment.getExternalStorageDirectory(), )
return if (!dir.isDirectory && !dir.mkdirs()) null else dir
}
+ @JvmStatic
+ fun recursivelyDeleteDirectory(directory: File) : Boolean {
+ val contents = directory.listFiles()
+ contents?.forEach { recursivelyDeleteDirectory(it) }
+ return directory.delete()
+ }
}
\ No newline at end of file
diff --git a/orbotservice/src/main/java/org/torproject/android/service/OrbotService.java b/orbotservice/src/main/java/org/torproject/android/service/OrbotService.java
index 36dcb0ae..10acf5de 100644
--- a/orbotservice/src/main/java/org/torproject/android/service/OrbotService.java
+++ b/orbotservice/src/main/java/org/torproject/android/service/OrbotService.java
@@ -39,7 +39,6 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.jaredrummler.android.shell.CommandResult;
-import net.freehaven.tor.control.ConfigEntry;
import net.freehaven.tor.control.TorControlCommands;
import net.freehaven.tor.control.TorControlConnection;
@@ -72,7 +71,6 @@ import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
-import java.util.List;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.concurrent.ExecutorService;
@@ -84,14 +82,36 @@ import IPtProxy.IPtProxy;
public class OrbotService extends VpnService implements TorServiceConstants, OrbotConstants {
public final static String BINARY_TOR_VERSION = org.torproject.android.binary.TorServiceConstants.BINARY_TOR_VERSION;
- private final static int CONTROL_SOCKET_TIMEOUT = 60000;
static final int NOTIFY_ID = 1;
+ private final static int CONTROL_SOCKET_TIMEOUT = 60000;
private static final int ERROR_NOTIFY_ID = 3;
private static final int HS_NOTIFY_ID = 4;
- private static final Uri HS_CONTENT_URI = Uri.parse("content://org.torproject.android.ui.hiddenservices.providers/hs");
+ private static final Uri V2_HS_CONTENT_URI = Uri.parse("content://org.torproject.android.ui.hiddenservices.providers/hs");
+ private static final Uri V3_ONION_SERVICES_CONTENT_URI = Uri.parse("content://org.torproject.android.ui.v3onionservice/v3");
private static final Uri COOKIE_CONTENT_URI = Uri.parse("content://org.torproject.android.ui.hiddenservices.providers.cookie/cookie");
private final static String NOTIFICATION_CHANNEL_ID = "orbot_channel_1";
- private final static String RESET_STRING = "=\"\"";
+ private static final String[] LEGACY_V2_ONION_SERVICE_PROJECTION = new String[]{
+ OnionService._ID,
+ OnionService.NAME,
+ OnionService.DOMAIN,
+ OnionService.PORT,
+ OnionService.AUTH_COOKIE,
+ OnionService.AUTH_COOKIE_VALUE,
+ OnionService.ONION_PORT,
+ OnionService.ENABLED};
+ private static final String[] V3_ONION_SERVICE_PROJECTION = new String[]{
+ OnionService._ID,
+ OnionService.NAME,
+ OnionService.DOMAIN,
+ OnionService.PORT,
+ OnionService.ONION_PORT,
+ OnionService.ENABLED,
+ };
+ private static final String[] LEGACY_COOKIE_PROJECTION = new String[]{
+ ClientCookie._ID,
+ ClientCookie.DOMAIN,
+ ClientCookie.AUTH_COOKIE_VALUE,
+ ClientCookie.ENABLED};
public static int mPortSOCKS = -1;
public static int mPortHTTP = -1;
public static int mPortDns = TOR_DNS_PORT_DEFAULT;
@@ -100,6 +120,7 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
public static File appCacheHome;
public static File fileTor;
public static File fileTorRc;
+ private final ExecutorService mExecutor = Executors.newCachedThreadPool();
boolean mIsLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
TorEventHandler mEventHandler;
OrbotVpnManager mVpnManager;
@@ -110,29 +131,12 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
private String mCurrentStatus = STATUS_OFF;
private TorControlConnection conn = null;
private int mLastProcessId = -1;
- private ArrayList<String> configBuffer = null;
- private ArrayList<String> resetBuffer = null;
private File fileControlPort, filePid;
private NotificationManager mNotificationManager = null;
private NotificationCompat.Builder mNotifyBuilder;
private boolean mNotificationShowing = false;
- private final ExecutorService mExecutor = Executors.newCachedThreadPool();
- private File mHSBasePath;
+ private File mHSBasePath, mV3OnionBasePath;
private ArrayList<Bridge> alBridges = null;
- private final String[] hsProjection = new String[]{
- HiddenService._ID,
- HiddenService.NAME,
- HiddenService.DOMAIN,
- HiddenService.PORT,
- HiddenService.AUTH_COOKIE,
- HiddenService.AUTH_COOKIE_VALUE,
- HiddenService.ONION_PORT,
- HiddenService.ENABLED};
- private final String[] cookieProjection = new String[]{
- ClientCookie._ID,
- ClientCookie.DOMAIN,
- ClientCookie.AUTH_COOKIE_VALUE,
- ClientCookie.ENABLED};
/**
* @param bridgeList bridges that were manually entered into Orbot settings
@@ -144,13 +148,16 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
return bridgeList.split("\\n");
}
- public void debug(String msg) {
+ private static boolean useIPtProxy() {
+ String bridgeList = Prefs.getBridgesList();
+ return bridgeList.contains("obfs3") || bridgeList.contains("obfs4") || bridgeList.contains("meek");
+ }
+ public void debug(String msg) {
Log.d(OrbotConstants.TAG, msg);
if (Prefs.useDebugLogging()) {
sendCallbackLogMessage(msg);
-
}
}
@@ -264,7 +271,6 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
}
public int onStartCommand(Intent intent, int flags, int startId) {
-
showToolbarNotification("", NOTIFY_ID, R.drawable.ic_stat_tor);
if (intent != null)
@@ -347,7 +353,6 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
/**
* if someone stops during startup, we may have to wait for the conn port to be setup, so we can properly shutdown tor
- * @throws Exception
*/
private void stopTorDaemon(boolean waitForConnection) throws Exception {
@@ -372,7 +377,10 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
if (!waitForConnection)
break;
- try { Thread.sleep(3000);}catch (Exception e){}
+ try {
+ Thread.sleep(3000);
+ } catch (Exception e) {
+ }
}
}
@@ -384,13 +392,6 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
} catch (IOException e) {
e.printStackTrace();
}
- /**
- // if that fails, try again using native utils
- try {
- killProcess(fileTor, "-1"); // this is -HUP
- } catch (Exception e) {
- e.printStackTrace();
- }**/
}
protected void logNotice(String msg) {
@@ -439,14 +440,14 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
fileControlPort = new File(getFilesDir(), TOR_CONTROL_PORT_FILE);
filePid = new File(getFilesDir(), TOR_PID_FILE);
- mHSBasePath = new File(
- getFilesDir().getAbsolutePath(),
- TorServiceConstants.HIDDEN_SERVICES_DIR
- );
-
+ mHSBasePath = new File(getFilesDir().getAbsolutePath(), TorServiceConstants.HIDDEN_SERVICES_DIR);
if (!mHSBasePath.isDirectory())
mHSBasePath.mkdirs();
+ mV3OnionBasePath = new File(getFilesDir().getAbsolutePath(), TorServiceConstants.ONION_SERVICES_DIR);
+ if (!mV3OnionBasePath.isDirectory())
+ mV3OnionBasePath.mkdirs();
+
mEventHandler = new TorEventHandler(this);
if (mNotificationManager == null) {
@@ -501,12 +502,12 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
private boolean pluggableTransportInstall() {
- File fileCacheDir = new File(getCacheDir(),"pt");
+ File fileCacheDir = new File(getCacheDir(), "pt");
if (!fileCacheDir.exists())
fileCacheDir.mkdir();
IPtProxy.setStateLocation(fileCacheDir.getAbsolutePath());
String fileTestState = IPtProxy.getStateLocation();
- debug ("IPtProxy state: " + fileTestState);
+ debug("IPtProxy state: " + fileTestState);
return false;
}
@@ -657,13 +658,10 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
if (isPortUsed) //the specified port is not available, so let Tor find one instead
port++;
}
-
-
return port + "";
}
return portString;
-
}
public boolean updateTorConfigCustom(File fileTorRcCustom, String extraLines) throws IOException, TimeoutException {
@@ -710,8 +708,6 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
* The entire process for starting tor and related services is run from this method.
*/
private void startTor() {
-
-
try {
// STATUS_STARTING is set in onCreate()
@@ -734,9 +730,8 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
String torProcId = conn.getInfo("process/pid");
if (!TextUtils.isEmpty(torProcId))
mLastProcessId = Integer.parseInt(torProcId);
- }
- else {
- if (fileControlPort!=null && fileControlPort.exists())
+ } else {
+ if (fileControlPort != null && fileControlPort.exists())
findExistingTorDaemon();
}
@@ -765,9 +760,14 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
if (success) {
try {
- updateOnionNames();
+ updateLegacyV2OnionNames();
+ } catch (SecurityException se) {
+ logNotice("unable to upload legacy v2 onion names");
+ }
+ try {
+ updateV3OnionNames();
} catch (SecurityException se) {
- logNotice("unable to upload onion names");
+ logNotice("unable to upload v3 onion names");
}
}
@@ -777,21 +777,48 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
showToolbarNotification(
getString(R.string.unable_to_start_tor) + ": " + e.getMessage(),
ERROR_NOTIFY_ID, R.drawable.ic_stat_notifyerr);
+ }
+ }
+ private void updateV3OnionNames() throws SecurityException {
+ ContentResolver contentResolver = getApplicationContext().getContentResolver();
+ Cursor onionServices = contentResolver.query(V3_ONION_SERVICES_CONTENT_URI, null, null, null, null);
+ if (onionServices != null) {
+ try {
+ while (onionServices.moveToNext()) {
+ String domain = onionServices.getString(onionServices.getColumnIndex(OnionService.DOMAIN));
+ int localPort = onionServices.getInt(onionServices.getColumnIndex(OnionService.PORT));
+
+ if (domain == null || TextUtils.isEmpty(domain)) {
+ String v3OnionDirPath = new File(mV3OnionBasePath.getAbsolutePath(), "v3" + localPort).getCanonicalPath();
+ File hostname = new File(v3OnionDirPath, "hostname");
+ if (hostname.exists()) {
+ domain = Utils.readString(new FileInputStream(hostname)).trim();
+ ContentValues fields = new ContentValues();
+ fields.put(OnionService.DOMAIN, domain);
+ contentResolver.update(V3_ONION_SERVICES_CONTENT_URI, fields, "port=" + localPort, null);
+ }
+ }
+
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ onionServices.close();
}
}
- private void updateOnionNames() throws SecurityException {
+ private void updateLegacyV2OnionNames() throws SecurityException {
// Tor is running, update new .onion names at db
ContentResolver mCR = getApplicationContext().getContentResolver();
- Cursor hidden_services = mCR.query(HS_CONTENT_URI, hsProjection, null, null, null);
+ Cursor hidden_services = mCR.query(V2_HS_CONTENT_URI, LEGACY_V2_ONION_SERVICE_PROJECTION, null, null, null);
if (hidden_services != null) {
try {
while (hidden_services.moveToNext()) {
- String HSDomain = hidden_services.getString(hidden_services.getColumnIndex(HiddenService.DOMAIN));
- Integer HSLocalPort = hidden_services.getInt(hidden_services.getColumnIndex(HiddenService.PORT));
- Integer HSAuthCookie = hidden_services.getInt(hidden_services.getColumnIndex(HiddenService.AUTH_COOKIE));
- String HSAuthCookieValue = hidden_services.getString(hidden_services.getColumnIndex(HiddenService.AUTH_COOKIE_VALUE));
+ String HSDomain = hidden_services.getString(hidden_services.getColumnIndex(OnionService.DOMAIN));
+ Integer HSLocalPort = hidden_services.getInt(hidden_services.getColumnIndex(OnionService.PORT));
+ Integer HSAuthCookie = hidden_services.getInt(hidden_services.getColumnIndex(OnionService.AUTH_COOKIE));
+ String HSAuthCookieValue = hidden_services.getString(hidden_services.getColumnIndex(OnionService.AUTH_COOKIE_VALUE));
// Update only new domains or restored from backup with auth cookie
if ((HSDomain == null || HSDomain.length() < 1) || (HSAuthCookie == 1 && (HSAuthCookieValue == null || HSAuthCookieValue.length() < 1))) {
@@ -806,10 +833,10 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
if (HSAuthCookie == 1) {
String[] aux = onionHostname.split(" ");
onionHostname = aux[0];
- fields.put(HiddenService.AUTH_COOKIE_VALUE, aux[1]);
+ fields.put(OnionService.AUTH_COOKIE_VALUE, aux[1]);
}
- fields.put(HiddenService.DOMAIN, onionHostname);
- mCR.update(HS_CONTENT_URI, fields, "port=" + HSLocalPort, null);
+ fields.put(OnionService.DOMAIN, onionHostname);
+ mCR.update(V2_HS_CONTENT_URI, fields, "port=" + HSLocalPort, null);
} catch (FileNotFoundException e) {
logException("unable to read onion hostname file", e);
showToolbarNotification(getString(R.string.unable_to_read_hidden_service_name), HS_NOTIFY_ID, R.drawable.ic_stat_notifyerr);
@@ -832,8 +859,6 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
}
private boolean runTorShellCmd() throws Exception {
- boolean result = true;
-
File fileTorrcCustom = updateTorrcCustomFile();
//make sure Tor exists and we can execute it
@@ -868,9 +893,7 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
exitCode = exec(torCmdString, false);
} catch (Exception e) {
logNotice("Tor was unable to start: " + e.getMessage());
-
throw new Exception("Tor was unable to start: " + e.getMessage());
-
}
if (exitCode != 0) {
@@ -885,13 +908,11 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
logNotice(getString(R.string.couldn_t_start_tor_process_) + "; exit=" + exitCode);
throw new Exception(getString(R.string.couldn_t_start_tor_process_) + "; exit=" + exitCode);
} else {
-
logNotice("Tor started; process id=" + mLastProcessId);
- result = true;
}
}
- return result;
+ return true;
}
protected void exec(Runnable runn) {
@@ -918,23 +939,17 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
while (conn == null && attempt++ < maxTries && (mCurrentStatus != STATUS_OFF)) {
try {
-
controlPort = getControlPort();
-
if (controlPort != -1) {
logNotice(getString(R.string.connecting_to_control_port) + controlPort);
-
-
break;
}
} catch (Exception ce) {
conn = null;
// logException( "Error connecting to Tor local control port: " + ce.getMessage(),ce);
-
}
-
try {
// logNotice("waiting...");
Thread.sleep(2000);
@@ -942,27 +957,19 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
}
}
-
if (controlPort != -1) {
Socket torConnSocket = new Socket(IP_LOCALHOST, controlPort);
torConnSocket.setSoTimeout(CONTROL_SOCKET_TIMEOUT);
-
conn = new TorControlConnection(torConnSocket);
-
conn.launchThread(true);//is daemon
-
}
if (conn != null) {
-
logNotice("SUCCESS connected to Tor control port.");
File fileCookie = new File(appCacheHome, TOR_CONTROL_COOKIE);
if (fileCookie.exists()) {
-
- // We extend NullEventHandler so that we don't need to provide empty
- // implementations for all the events we don't care about.
logNotice("adding control port event handler");
conn.setEventHandler(mEventHandler);
@@ -1019,7 +1026,6 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
}
sendCallbackPorts(mPortSOCKS, mPortHTTP, mPortDns, mPortTrans);
-
setTorNetworkEnabled(true);
return Integer.parseInt(torProcId);
@@ -1066,20 +1072,6 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
return result;
}
- /**
- * Returns the port number that the HTTP proxy is running on
- */
- public int getHTTPPort() {
- return mPortHTTP;
- }
-
- /**
- * Returns the port number that the HTTP proxy is running on
- */
- public int getSOCKSPort() {
- return mPortSOCKS;
- }
-
public String getInfo(String key) {
try {
if (conn != null) {
@@ -1092,71 +1084,11 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
return null;
}
- public String getConfiguration(String name) {
- try {
- if (conn != null) {
- StringBuffer result = new StringBuffer();
-
- List<ConfigEntry> listCe = conn.getConf(name);
-
- Iterator<ConfigEntry> itCe = listCe.iterator();
- ConfigEntry ce;
-
-
- while (itCe.hasNext()) {
- ce = itCe.next();
-
- result.append(ce.key);
- result.append(' ');
- result.append(ce.value);
- result.append('\n');
- }
-
- return result.toString();
- }
- } catch (Exception ioe) {
-
- logException("Unable to get Tor configuration: " + ioe.getMessage(), ioe);
- }
-
- return null;
- }
-
- /**
- * Set configuration
- **/
- public boolean updateConfiguration(String name, String value, boolean saveToDisk) {
-
-
- if (configBuffer == null)
- configBuffer = new ArrayList<>();
-
- if (resetBuffer == null)
- resetBuffer = new ArrayList<>();
-
- if (value == null || value.length() == 0) {
- resetBuffer.add(name + RESET_STRING);
-
- } else {
-
- String sbConf = name +
- ' ' +
- value;
- configBuffer.add(sbConf);
- }
-
- return false;
- }
-
-
public void setTorNetworkEnabled(final boolean isEnabled) throws IOException {
-
- //it is possible to not have a connection yet, and someone might try to newnym
- if (conn != null) {
+ if (conn != null) { // it is possible to not have a connection yet, and someone might try to newnym
new Thread() {
public void run() {
try {
-
final String newValue = isEnabled ? "0" : "1";
conn.setConf("DisableNetwork", newValue);
} catch (Exception ioe) {
@@ -1165,7 +1097,6 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
}
}.start();
}
-
}
public void sendSignalActive() {
@@ -1179,8 +1110,7 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
}
public void newIdentity() {
- //it is possible to not have a connection yet, and someone might try to newnym
- if (conn != null) {
+ if (conn != null) { // it is possible to not have a connection yet, and someone might try to newnym
new Thread() {
public void run() {
try {
@@ -1199,49 +1129,6 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
}
}
- public boolean saveConfiguration() {
- try {
- if (conn != null) {
-
- if (resetBuffer != null && resetBuffer.size() > 0) {
- for (String value : configBuffer) {
-
- // debug("removing torrc conf: " + value);
-
-
- }
-
- // conn.resetConf(resetBuffer);
- resetBuffer = null;
- }
-
- if (configBuffer != null && configBuffer.size() > 0) {
-
- for (String value : configBuffer) {
-
- debug("Setting torrc conf: " + value);
-
-
- }
-
- conn.setConf(configBuffer);
-
- configBuffer = null;
- }
-
- // Flush the configuration to disk.
- //this is doing bad things right now NF 22/07/10
- //conn.saveConf();
-
- return true;
- }
- } catch (Exception ioe) {
- logException("Unable to update Tor configuration: " + ioe.getMessage(), ioe);
- }
-
- return false;
- }
-
protected void sendCallbackBandwidth(long upload, long download, long written, long read) {
Intent intent = new Intent(LOCAL_ACTION_BANDWIDTH);
@@ -1255,11 +1142,8 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
}
private void sendCallbackLogMessage(final String logMessage) {
-
mHandler.post(() -> {
-
- Intent intent = new Intent(LOCAL_ACTION_LOG);
- // You can also include some extra data.
+ Intent intent = new Intent(LOCAL_ACTION_LOG); // You can also include some extra data.
intent.putExtra(LOCAL_EXTRA_LOG, logMessage);
intent.putExtra(EXTRA_STATUS, mCurrentStatus);
@@ -1269,9 +1153,7 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
}
private void sendCallbackPorts(int socksPort, int httpPort, int dnsPort, int transPort) {
-
- Intent intent = new Intent(LOCAL_ACTION_PORTS);
- // You can also include some extra data.
+ Intent intent = new Intent(LOCAL_ACTION_PORTS); // You can also include some extra data.
intent.putExtra(EXTRA_SOCKS_PROXY_PORT, socksPort);
intent.putExtra(EXTRA_HTTP_PROXY_PORT, httpPort);
intent.putExtra(EXTRA_DNS_PORT, dnsPort);
@@ -1355,26 +1237,19 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
private StringBuffer processSettingsImpl(StringBuffer extraLines) throws IOException {
logNotice(getString(R.string.updating_settings_in_tor_service));
-
SharedPreferences prefs = Prefs.getSharedPrefs(getApplicationContext());
boolean useBridges = Prefs.bridgesEnabled();
-
boolean becomeRelay = prefs.getBoolean(OrbotConstants.PREF_OR, false);
boolean ReachableAddresses = prefs.getBoolean(OrbotConstants.PREF_REACHABLE_ADDRESSES, false);
-
boolean enableStrictNodes = prefs.getBoolean("pref_strict_nodes", false);
String entranceNodes = prefs.getString("pref_entrance_nodes", "");
String exitNodes = prefs.getString("pref_exit_nodes", "");
String excludeNodes = prefs.getString("pref_exclude_nodes", "");
if (!useBridges) {
-
extraLines.append("UseBridges 0").append('\n');
-
- if (Prefs.useVpn()) //set the proxy here if we aren't using a bridge
- {
-
+ if (Prefs.useVpn()) { //set the proxy here if we aren't using a bridge
if (!mIsLollipop) {
String proxyType = "socks5";
extraLines.append(proxyType + "Proxy" + ' ' + OrbotVpnManager.sSocksProxyLocalhost + ':' + OrbotVpnManager.sSocksProxyServerPort).append('\n');
@@ -1400,15 +1275,12 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
} else if (proxyPass != null)
extraLines.append(proxyType + "ProxyAuthenticator" + ' ' + proxyUser + ':' + proxyPort).append('\n');
-
-
}
}
}
} else {
loadBridgeDefaults();
-
extraLines.append("UseBridges 1").append('\n');
// extraLines.append("UpdateBridgesFromAuthority 1").append('\n');
@@ -1445,12 +1317,9 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
extraLines.append("Bridge ");
extraLines.append(bridgeLine);
extraLines.append("\n");
-
}
-
}
-
//only apply GeoIP if you need it
File fileGeoIP = new File(appBinHome, GEOIP_ASSET_KEY);
File fileGeoIP6 = new File(appBinHome, GEOIP6_ASSET_KEY);
@@ -1473,16 +1342,12 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
try {
if (ReachableAddresses) {
- String ReachableAddressesPorts =
- prefs.getString(OrbotConstants.PREF_REACHABLE_ADDRESSES_PORTS, "*:80,*:443");
-
+ String ReachableAddressesPorts = prefs.getString(OrbotConstants.PREF_REACHABLE_ADDRESSES_PORTS, "*:80,*:443");
extraLines.append("ReachableAddresses" + ' ' + ReachableAddressesPorts).append('\n');
-
}
} catch (Exception e) {
showToolbarNotification(getString(R.string.your_reachableaddresses_settings_caused_an_exception_), ERROR_NOTIFY_ID, R.drawable.ic_stat_notifyerr);
-
return null;
}
@@ -1490,7 +1355,6 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
if (becomeRelay && (!useBridges) && (!ReachableAddresses)) {
int ORPort = Integer.parseInt(prefs.getString(OrbotConstants.PREF_OR_PORT, "9001"));
String nickname = prefs.getString(OrbotConstants.PREF_OR_NICKNAME, "Orbot");
-
String dnsFile = writeDNSFile();
extraLines.append("ServerDNSResolvConfFile" + ' ' + dnsFile).append('\n');
@@ -1501,33 +1365,56 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
}
} catch (Exception e) {
showToolbarNotification(getString(R.string.your_relay_settings_caused_an_exception_), ERROR_NOTIFY_ID, R.drawable.ic_stat_notifyerr);
-
-
return null;
}
- ContentResolver mCR = getApplicationContext().getContentResolver();
+ ContentResolver contentResolver = getApplicationContext().getContentResolver();
+ addV3OnionServicesToTorrc(extraLines, contentResolver);
+// addV2HiddenServicesToTorrc(extraLines, contentResolver);
+// addV2ClientCookiesToTorrc(extraLines, contentResolver);
+ return extraLines;
+ }
+ private void addV3OnionServicesToTorrc(StringBuffer torrc, ContentResolver contentResolver) {
try {
- /* ---- Hidden Services ---- */
- Cursor hidden_services = mCR.query(HS_CONTENT_URI, hsProjection, HiddenService.ENABLED + "=1", null, null);
+ Cursor onionServices = contentResolver.query(V3_ONION_SERVICES_CONTENT_URI, V3_ONION_SERVICE_PROJECTION, OnionService.ENABLED + "=1", null, null);
+ if (onionServices != null) {
+ while (onionServices.moveToNext()) {
+ int localPort = onionServices.getInt(onionServices.getColumnIndex(OnionService.PORT));
+ int onionPort = onionServices.getInt(onionServices.getColumnIndex(OnionService.ONION_PORT));
+ String v3DirPath = new File(mV3OnionBasePath.getAbsolutePath(), "v3" + localPort).getCanonicalPath();
+ torrc.append("HiddenServiceDir ").append(v3DirPath).append("\n");
+ torrc.append("HiddenServiceVersion 3").append("\n");
+ torrc.append("HiddenServicePort ").append(onionPort).append(" 127.0.0.1:").append(localPort).append("\n");
+ }
+ onionServices.close();
+ }
+ } catch (Exception e) {
+ Log.e(TAG, e.getLocalizedMessage());
+ }
+ }
+
+ // todo needs modifications to set hidden service version back after doing v3 stuff...
+ private void addV2HiddenServicesToTorrc(StringBuffer torrc, ContentResolver contentResolver) {
+ try {
+ Cursor hidden_services = contentResolver.query(V2_HS_CONTENT_URI, LEGACY_V2_ONION_SERVICE_PROJECTION, OnionService.ENABLED + "=1", null, null);
if (hidden_services != null) {
try {
while (hidden_services.moveToNext()) {
- String HSname = hidden_services.getString(hidden_services.getColumnIndex(HiddenService.NAME));
- Integer HSLocalPort = hidden_services.getInt(hidden_services.getColumnIndex(HiddenService.PORT));
- Integer HSOnionPort = hidden_services.getInt(hidden_services.getColumnIndex(HiddenService.ONION_PORT));
- Integer HSAuthCookie = hidden_services.getInt(hidden_services.getColumnIndex(HiddenService.AUTH_COOKIE));
+ String HSname = hidden_services.getString(hidden_services.getColumnIndex(OnionService.NAME));
+ int HSLocalPort = hidden_services.getInt(hidden_services.getColumnIndex(OnionService.PORT));
+ int HSOnionPort = hidden_services.getInt(hidden_services.getColumnIndex(OnionService.ONION_PORT));
+ int HSAuthCookie = hidden_services.getInt(hidden_services.getColumnIndex(OnionService.AUTH_COOKIE));
String hsDirPath = new File(mHSBasePath.getAbsolutePath(), "hs" + HSLocalPort).getCanonicalPath();
debug("Adding hidden service on port: " + HSLocalPort);
- extraLines.append("HiddenServiceDir" + ' ' + hsDirPath).append('\n');
- extraLines.append("HiddenServicePort" + ' ' + HSOnionPort + " 127.0.0.1:" + HSLocalPort).append('\n');
- extraLines.append("HiddenServiceVersion 2").append('\n');
+ torrc.append("HiddenServiceDir" + ' ' + hsDirPath).append('\n');
+ torrc.append("HiddenServicePort" + ' ' + HSOnionPort + " 127.0.0.1:" + HSLocalPort).append('\n');
+ torrc.append("HiddenServiceVersion 2").append('\n');
if (HSAuthCookie == 1)
- extraLines.append("HiddenServiceAuthorizeClient stealth " + HSname).append('\n');
+ torrc.append("HiddenServiceAuthorizeClient stealth " + HSname).append('\n');
}
} catch (NumberFormatException e) {
Log.e(OrbotConstants.TAG, "error parsing hsport", e);
@@ -1539,28 +1426,25 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
}
} catch (SecurityException se) {
}
+ }
+ private void addV2ClientCookiesToTorrc(StringBuffer torrc, ContentResolver contentResolver) {
try {
-
- /* ---- Client Cookies ---- */
- Cursor client_cookies = mCR.query(COOKIE_CONTENT_URI, cookieProjection, ClientCookie.ENABLED + "=1", null, null);
+ Cursor client_cookies = contentResolver.query(COOKIE_CONTENT_URI, LEGACY_COOKIE_PROJECTION, ClientCookie.ENABLED + "=1", null, null);
if (client_cookies != null) {
try {
while (client_cookies.moveToNext()) {
String domain = client_cookies.getString(client_cookies.getColumnIndex(ClientCookie.DOMAIN));
String cookie = client_cookies.getString(client_cookies.getColumnIndex(ClientCookie.AUTH_COOKIE_VALUE));
- extraLines.append("HidServAuth" + ' ' + domain + ' ' + cookie).append('\n');
+ torrc.append("HidServAuth" + ' ' + domain + ' ' + cookie).append('\n');
}
} catch (Exception e) {
Log.e(OrbotConstants.TAG, "error starting share server", e);
}
-
client_cookies.close();
}
} catch (SecurityException se) {
}
-
- return extraLines;
}
//using Google DNS for now as the public DNS server
@@ -1614,7 +1498,6 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
@Override
public IBinder onBind(Intent intent) {
Log.e(TAG, "onBind");
- //do nothing here
return super.onBind(intent); // invoking super class will call onRevoke() when appropriate
}
@@ -1676,8 +1559,7 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
alBridges = new ArrayList<>();
try {
- BufferedReader in =
- new BufferedReader(new InputStreamReader(getResources().openRawResource(R.raw.bridges), "UTF-8"));
+ BufferedReader in = new BufferedReader(new InputStreamReader(getResources().openRawResource(R.raw.bridges), "UTF-8"));
String str;
while ((str = in.readLine()) != null) {
@@ -1692,9 +1574,7 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
sbConfig.append(st.nextToken()).append(' ');
b.config = sbConfig.toString().trim();
-
alBridges.add(b);
-
}
in.close();
@@ -1702,7 +1582,6 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
e.printStackTrace();
}
}
-
}
private void getBridges(String type, StringBuffer extraLines) {
@@ -1728,20 +1607,18 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
break;
}
}
-
}
- public static final class HiddenService implements BaseColumns {
+ public static final class OnionService implements BaseColumns {
public static final String NAME = "name";
public static final String PORT = "port";
public static final String ONION_PORT = "onion_port";
public static final String DOMAIN = "domain";
public static final String AUTH_COOKIE = "auth_cookie";
public static final String AUTH_COOKIE_VALUE = "auth_cookie_value";
- public static final String CREATED_BY_USER = "created_by_user";
public static final String ENABLED = "enabled";
- private HiddenService() {
+ private OnionService() {
}
}
@@ -1768,7 +1645,6 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
}
public void run() {
-
String action = mIntent.getAction();
if (!TextUtils.isEmpty(action)) {
@@ -1804,11 +1680,8 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
if (mVpnManager != null && (!mVpnManager.isStarted())) {
//start VPN here
Intent vpnIntent = VpnService.prepare(OrbotService.this);
- if (vpnIntent == null) //then we can run the VPN
- {
+ if (vpnIntent == null) { //then we can run the VPN
mVpnManager.handleIntent(new Builder(), mIntent);
-
-
}
}
@@ -1828,9 +1701,7 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
} else if (action.equals(CMD_ACTIVE)) {
sendSignalActive();
} else if (action.equals(CMD_SET_EXIT)) {
-
setExitNode(mIntent.getStringExtra("exit"));
-
} else {
Log.w(OrbotConstants.TAG, "unhandled OrbotService Intent: " + action);
}
@@ -1852,5 +1723,4 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
}
}
}
-
}
diff --git a/orbotservice/src/main/java/org/torproject/android/service/TorServiceConstants.java b/orbotservice/src/main/java/org/torproject/android/service/TorServiceConstants.java
index f1769687..915f149d 100644
--- a/orbotservice/src/main/java/org/torproject/android/service/TorServiceConstants.java
+++ b/orbotservice/src/main/java/org/torproject/android/service/TorServiceConstants.java
@@ -112,6 +112,6 @@ public interface TorServiceConstants {
String OBFSCLIENT_ASSET_KEY = "obfs4proxy";
String HIDDEN_SERVICES_DIR = "hidden_services";
-
+ String ONION_SERVICES_DIR = "v3_onion_services";
}
1
0

[orbot/master] V3 UI Cleanup, Deprecated Stuff Under Menu + filtering of v3 user/app services
by n8fr8@torproject.org 22 Dec '21
by n8fr8@torproject.org 22 Dec '21
22 Dec '21
commit ec11d9db387c19c7ca6b385d44a5fcc1fed79659
Author: bim <dsnake(a)protonmail.com>
Date: Sat Nov 28 12:35:03 2020 -0500
V3 UI Cleanup, Deprecated Stuff Under Menu + filtering of v3 user/app services
---
.../ui/hiddenservices/HiddenServicesActivity.java | 14 +++--
.../ui/hiddenservices/backup/BackupUtils.java | 30 ++++-------
.../backup/{ZipIt.java => ZipUtilities.java} | 14 +++--
.../ui/v3onionservice/OnionServicesActivity.java | 52 ++++++++++++++++---
app/src/main/res/menu/orbot_main.xml | 59 +++++++---------------
app/src/main/res/values/strings.xml | 1 +
.../java/org/torproject/android/core/DiskUtils.kt | 1 -
7 files changed, 89 insertions(+), 82 deletions(-)
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java
index 886bd27d..7436eb91 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java
@@ -25,6 +25,7 @@ import org.torproject.android.core.DiskUtils;
import org.torproject.android.core.LocaleHelper;
import org.torproject.android.ui.hiddenservices.adapters.OnionListAdapter;
import org.torproject.android.ui.hiddenservices.backup.BackupUtils;
+import org.torproject.android.ui.hiddenservices.backup.ZipUtilities;
import org.torproject.android.ui.hiddenservices.dialogs.HSActionsDialog;
import org.torproject.android.ui.hiddenservices.dialogs.HSDataDialog;
import org.torproject.android.ui.hiddenservices.permissions.PermissionManager;
@@ -43,7 +44,7 @@ public class HiddenServicesActivity extends AppCompatActivity {
private static final String BUNDLE_KEY_SHOW_USER_SERVICES = "show_user_services";
private ContentResolver mResolver;
private OnionListAdapter mAdapter;
- private RadioButton radioShowUserServices, radioShowAppServices;
+ private RadioButton radioShowUserServices;
private FloatingActionButton fab;
private String mWhere = HSContentProvider.HiddenService.CREATED_BY_USER + "=1";
@@ -52,7 +53,7 @@ public class HiddenServicesActivity extends AppCompatActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_hs_list_view);
radioShowUserServices = findViewById(R.id.radioUserServices);
- radioShowAppServices = findViewById(R.id.radioAppServices);
+ RadioButton radioShowAppServices = findViewById(R.id.radioAppServices);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
@@ -61,7 +62,7 @@ public class HiddenServicesActivity extends AppCompatActivity {
mResolver = getContentResolver();
fab = findViewById(R.id.fab);
- fab.setOnClickListener(view -> new HSDataDialog().show(getSupportFragmentManager(), "HSDataDialog"));
+ fab.setOnClickListener(view -> new HSDataDialog().show(getSupportFragmentManager(), HSDataDialog.class.getSimpleName()));
mAdapter = new OnionListAdapter(this, mResolver.query(HSContentProvider.CONTENT_URI, HSContentProvider.PROJECTION, mWhere, null, null), 0);
mResolver.registerContentObserver(HSContentProvider.CONTENT_URI, true, new HSObserver(new Handler()));
@@ -108,7 +109,7 @@ public class HiddenServicesActivity extends AppCompatActivity {
private void doRestoreLegacy() { // API 16, 17, 18
File backupDir = DiskUtils.getOrCreateLegacyBackupDir(getString(R.string.app_name));
- File[] files = backupDir.listFiles((dir, name) -> name.toLowerCase().endsWith(".zip"));
+ File[] files = backupDir.listFiles(ZipUtilities.FILTER_ZIP_FILES);
if (files != null) {
if (files.length == 0) {
Toast.makeText(this, R.string.create_a_backup_first, Toast.LENGTH_LONG).show();
@@ -140,7 +141,7 @@ public class HiddenServicesActivity extends AppCompatActivity {
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.menu_restore_backup) {
if (DiskUtils.supportsStorageAccessFramework()) {
- Intent readFile = DiskUtils.createReadFileIntent("application/zip");
+ Intent readFile = DiskUtils.createReadFileIntent(ZipUtilities.ZIP_MIME_TYPE);
startActivityForResult(readFile, REQUEST_CODE_READ_ZIP_BACKUP);
} else { // API 16, 17, 18
doRestoreLegacy();
@@ -177,12 +178,9 @@ public class HiddenServicesActivity extends AppCompatActivity {
@Override
public void onChange(boolean selfChange) {
mAdapter.changeCursor(mResolver.query(HSContentProvider.CONTENT_URI, HSContentProvider.PROJECTION, mWhere, null, null));
-
if (!PermissionManager.isLollipopOrHigher()) return;
Cursor active = mResolver.query(HSContentProvider.CONTENT_URI, HSContentProvider.PROJECTION, HSContentProvider.HiddenService.ENABLED + "=1", null, null);
-
if (active == null) return;
-
if (active.getCount() > 0) // Call only if there running services
PermissionManager.requestBatteryPermissions(HiddenServicesActivity.this, getApplicationContext());
else // Drop whe not needed
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/backup/BackupUtils.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/backup/BackupUtils.java
index e81f73a9..1dbad3cb 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/backup/BackupUtils.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/backup/BackupUtils.java
@@ -30,8 +30,8 @@ import java.nio.charset.Charset;
public class BackupUtils {
private static final String configFileName = "config.json";
- private Context mContext;
- private ContentResolver mResolver;
+ private final Context mContext;
+ private final ContentResolver mResolver;
public BackupUtils(Context context) {
mContext = context;
@@ -44,14 +44,14 @@ public class BackupUtils {
public String createV3ZipBackup(String port, Uri zipFile) {
String[] files = createFilesForZippingV3(port);
- ZipIt zip = new ZipIt(files, zipFile, mResolver);
+ ZipUtilities zip = new ZipUtilities(files, zipFile, mResolver);
if (!zip.zip()) return null;
return zipFile.getPath();
}
public String createV2ZipBackup(int port, Uri zipFile) {
String[] files = createFilesForZippingV2(port);
- ZipIt zip = new ZipIt(files, zipFile, mResolver);
+ ZipUtilities zip = new ZipUtilities(files, zipFile, mResolver);
if (!zip.zip())
return null;
@@ -84,17 +84,12 @@ public class BackupUtils {
config.put(OnionServiceContentProvider.OnionService.CREATED_BY_USER, portData.getString(portData.getColumnIndex(OnionServiceContentProvider.OnionService.CREATED_BY_USER)));
config.put(OnionServiceContentProvider.OnionService.ENABLED, portData.getString(portData.getColumnIndex(OnionServiceContentProvider.OnionService.ENABLED)));
- } catch (JSONException jsone) {
- jsone.printStackTrace();
- return null;
- }
- portData.close();
+ portData.close();
- try {
FileWriter fileWriter = new FileWriter(configFilePath);
fileWriter.write(config.toString());
fileWriter.close();
- } catch (IOException ioe) {
+ } catch (JSONException | IOException ioe) {
ioe.printStackTrace();
return null;
}
@@ -131,10 +126,7 @@ public class BackupUtils {
config.put(HSContentProvider.HiddenService.AUTH_COOKIE_VALUE, portData.getString(portData.getColumnIndex(HSContentProvider.HiddenService.AUTH_COOKIE_VALUE)));
config.put(HSContentProvider.HiddenService.CREATED_BY_USER, portData.getInt(portData.getColumnIndex(HSContentProvider.HiddenService.CREATED_BY_USER)));
config.put(HSContentProvider.HiddenService.ENABLED, portData.getInt(portData.getColumnIndex(HSContentProvider.HiddenService.ENABLED)));
- } catch (JSONException e) {
- e.printStackTrace();
- return null;
- } catch (NullPointerException e) {
+ } catch (JSONException | NullPointerException e) {
e.printStackTrace();
return null;
}
@@ -261,7 +253,7 @@ public class BackupUtils {
public void restoreZipBackupV2Legacy(File zipFile) {
String backupName = zipFile.getName();
- ZipIt zip = new ZipIt(null, null, mResolver);
+ ZipUtilities zip = new ZipUtilities(null, null, mResolver);
String hsDir = backupName.substring(0, backupName.lastIndexOf('.'));
File hsPath = new File(getHSBasePath().getAbsolutePath(), hsDir);
if (zip.unzipLegacy(hsPath.getAbsolutePath(), zipFile))
@@ -272,7 +264,7 @@ public class BackupUtils {
public void restoreZipBackupV3Legacy(File zipFile) {
String backupName = zipFile.getName();
- ZipIt zip = new ZipIt(null, null, mResolver);
+ ZipUtilities zip = new ZipUtilities(null, null, mResolver);
String v3Dir = backupName.substring(0, backupName.lastIndexOf('.'));
File v3Path = new File(getV3BasePath().getAbsolutePath(), v3Dir);
if (zip.unzipLegacy(v3Path.getAbsolutePath(), zipFile))
@@ -291,7 +283,7 @@ public class BackupUtils {
String hsDir = backupName.substring(0, backupName.lastIndexOf('.'));
File hsPath = new File(getHSBasePath().getAbsolutePath(), hsDir);
- if (new ZipIt(null, zipUri, mResolver).unzip(hsPath.getAbsolutePath()))
+ if (new ZipUtilities(null, zipUri, mResolver).unzip(hsPath.getAbsolutePath()))
extractConfigFromUnzippedBackupV2(backupName);
else
Toast.makeText(mContext, R.string.error, Toast.LENGTH_LONG).show();
@@ -306,7 +298,7 @@ public class BackupUtils {
String v3Dir = backupName.substring(0, backupName.lastIndexOf('.'));
File v3Paath = new File(getV3BasePath().getAbsolutePath(), v3Dir);
- if (new ZipIt(null, zipUri, mResolver).unzip(v3Paath.getAbsolutePath()))
+ if (new ZipUtilities(null, zipUri, mResolver).unzip(v3Paath.getAbsolutePath()))
extractConfigFromUnzippedBackupV3(backupName);
else
Toast.makeText(mContext, R.string.error, Toast.LENGTH_LONG).show();
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/backup/ZipIt.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/backup/ZipUtilities.java
similarity index 88%
rename from app/src/main/java/org/torproject/android/ui/hiddenservices/backup/ZipIt.java
rename to app/src/main/java/org/torproject/android/ui/hiddenservices/backup/ZipUtilities.java
index 5c264b8e..11fd1743 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/backup/ZipIt.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/backup/ZipUtilities.java
@@ -10,22 +10,26 @@ import androidx.annotation.Nullable;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
+import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
+import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
-public class ZipIt {
+public class ZipUtilities {
private static final int BUFFER = 2048;
+ public static final String ZIP_MIME_TYPE = "application/zip";
+ public static final FilenameFilter FILTER_ZIP_FILES = (dir, name) -> name.toLowerCase().endsWith(".zip");
- private String[] files;
- private Uri zipFile;
- private ContentResolver contentResolver;
+ private final String[] files;
+ private final Uri zipFile;
+ private final ContentResolver contentResolver;
- public ZipIt(@Nullable String[] files, @NonNull Uri zipFile, @NonNull ContentResolver contentResolver) {
+ public ZipUtilities(@Nullable String[] files, @NonNull Uri zipFile, @NonNull ContentResolver contentResolver) {
this.files = files;
this.zipFile = zipFile;
this.contentResolver = contentResolver;
diff --git a/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServicesActivity.java b/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServicesActivity.java
index a51ef37c..ba06b7c0 100644
--- a/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServicesActivity.java
+++ b/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServicesActivity.java
@@ -9,10 +9,12 @@ import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;
+import android.view.View;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.Toast;
+import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
@@ -23,15 +25,17 @@ 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;
public class OnionServicesActivity extends AppCompatActivity {
static final String BUNDLE_KEY_ID = "id", BUNDLE_KEY_PORT = "port", BUNDLE_KEY_DOMAIN = "domain";
- private static final String WHERE_SELECTION_CLAUSE = OnionServiceContentProvider.OnionService.CREATED_BY_USER + "=1";
+ private static final String BASE_WHERE_SELECTION_CLAUSE = OnionServiceContentProvider.OnionService.CREATED_BY_USER + "=";
+ private static final String BUNDLE_KEY_SHOW_USER_SERVICES = "show_user_key";
private static final int REQUEST_CODE_READ_ZIP_BACKUP = 347;
- private RadioButton radioShowUserServices, radioShowAppServices;
+ private RadioButton radioShowUserServices;
private FloatingActionButton fab;
private ContentResolver mContentResolver;
private OnionV3ListAdapter mAdapter;
@@ -46,13 +50,20 @@ public class OnionServicesActivity extends AppCompatActivity {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
fab = findViewById(R.id.fab);
- fab.setOnClickListener(v -> new NewOnionServiceDialogFragment().show(getSupportFragmentManager(), "NewOnionServiceDialogFragment"));
+ fab.setOnClickListener(v -> new NewOnionServiceDialogFragment().show(getSupportFragmentManager(), NewOnionServiceDialogFragment.class.getSimpleName()));
mContentResolver = getContentResolver();
- mAdapter = new OnionV3ListAdapter(this, mContentResolver.query(OnionServiceContentProvider.CONTENT_URI, OnionServiceContentProvider.PROJECTION, WHERE_SELECTION_CLAUSE, null, null), 0);
+ mAdapter = new OnionV3ListAdapter(this, mContentResolver.query(OnionServiceContentProvider.CONTENT_URI, OnionServiceContentProvider.PROJECTION, BASE_WHERE_SELECTION_CLAUSE + '1', null, null), 0);
mContentResolver.registerContentObserver(OnionServiceContentProvider.CONTENT_URI, true, new OnionServiceObserver(new Handler()));
ListView onionList = findViewById(R.id.onion_list);
+
+ radioShowUserServices = findViewById(R.id.radioUserServices);
+ RadioButton radioShowAppServices = findViewById(R.id.radioAppServices);
+ boolean showUserServices = radioShowAppServices.isChecked() || bundle == null || bundle.getBoolean(BUNDLE_KEY_SHOW_USER_SERVICES, false);
+ if (showUserServices) radioShowUserServices.setChecked(true);
+ else radioShowAppServices.setChecked(true);
+ filterServices(showUserServices);
onionList.setAdapter(mAdapter);
onionList.setOnItemClickListener((parent, view, position, id) -> {
Cursor item = (Cursor) parent.getItemAtPosition(position);
@@ -65,6 +76,19 @@ public class OnionServicesActivity extends AppCompatActivity {
});
}
+ private void filterServices(boolean showUserServices) {
+ String predicate;
+ if (showUserServices) {
+ predicate = "1";
+ fab.show();
+ } else {
+ predicate = "0";
+ fab.hide();
+ }
+ mAdapter.changeCursor(mContentResolver.query(OnionServiceContentProvider.CONTENT_URI, OnionServiceContentProvider.PROJECTION,
+ BASE_WHERE_SELECTION_CLAUSE + predicate, null, null));
+ }
+
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(LocaleHelper.onAttach(base));
@@ -76,11 +100,17 @@ public class OnionServicesActivity extends AppCompatActivity {
return true;
}
+ @Override
+ protected void onSaveInstanceState(@NonNull Bundle icicle) {
+ super.onSaveInstanceState(icicle);
+ icicle.putBoolean(BUNDLE_KEY_SHOW_USER_SERVICES, radioShowUserServices.isChecked());
+ }
+
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.menu_restore_backup) {
if (DiskUtils.supportsStorageAccessFramework()) {
- Intent readFileIntent = DiskUtils.createReadFileIntent("application/zip");
+ Intent readFileIntent = DiskUtils.createReadFileIntent(ZipUtilities.ZIP_MIME_TYPE);
startActivityForResult(readFileIntent, REQUEST_CODE_READ_ZIP_BACKUP);
} else { // APIs 16, 17, 18
doRestoreLegacy();
@@ -91,7 +121,7 @@ public class OnionServicesActivity extends AppCompatActivity {
private void doRestoreLegacy() { // APIs 16, 17, 18
File backupDir = DiskUtils.getOrCreateLegacyBackupDir(getString(R.string.app_name));
- File[] files = backupDir.listFiles((dir, name) -> name.toLowerCase().endsWith(".zip"));
+ File[] files = backupDir.listFiles(ZipUtilities.FILTER_ZIP_FILES);
if (files == null) return;
if (files.length == 0) {
Toast.makeText(this, R.string.create_a_backup_first, Toast.LENGTH_LONG).show();
@@ -115,6 +145,14 @@ public class OnionServicesActivity extends AppCompatActivity {
}
}
+ public void onRadioButtonClick(View view) {
+ int id = view.getId();
+ if (id == R.id.radioUserServices)
+ filterServices(true);
+ else if (id == R.id.radioAppServices)
+ filterServices(false);
+ }
+
private class OnionServiceObserver extends ContentObserver {
OnionServiceObserver(Handler handler) {
@@ -123,7 +161,7 @@ public class OnionServicesActivity extends AppCompatActivity {
@Override
public void onChange(boolean selfChange) {
- mAdapter.changeCursor(mContentResolver.query(OnionServiceContentProvider.CONTENT_URI, OnionServiceContentProvider.PROJECTION, WHERE_SELECTION_CLAUSE, null, null));
+ mAdapter.changeCursor(mContentResolver.query(OnionServiceContentProvider.CONTENT_URI, OnionServiceContentProvider.PROJECTION, BASE_WHERE_SELECTION_CLAUSE + '1', null, null));
// todo battery optimization stuff if lollipop or higher and running onion services
}
}
diff --git a/app/src/main/res/menu/orbot_main.xml b/app/src/main/res/menu/orbot_main.xml
index 2fb0ad4e..c0133d44 100644
--- a/app/src/main/res/menu/orbot_main.xml
+++ b/app/src/main/res/menu/orbot_main.xml
@@ -1,25 +1,7 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-/*
- * Copyright (C) 2008 Esmertec AG.
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
+<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:yourapp="http://schemas.android.com/apk/res-auto">
-
<item
android:id="@+id/menu_newnym"
android:icon="@drawable/ic_refresh_white_24dp"
@@ -56,44 +38,37 @@
<item
android:id="@+id/menu_v3_onion_services"
- android:title="@string/hidden_services"
- yourapp:showAsAction="never" />
-
- <item
- android:id="@+id/menu_hidden_services"
android:title="@string/hosted_services"
yourapp:showAsAction="never" />
<item
- android:id="@+id/menu_client_cookies"
- android:title="@string/client_cookies"
- yourapp:showAsAction="never" />
+ android:title="@string/v2_hidden_services"
+ yourapp:showAsAction="never">
+ <menu>
+ <item
+ android:id="@+id/menu_hidden_services"
+ android:title="@string/hosted_services"
+ yourapp:showAsAction="never" />
+
+ <item
+ android:id="@+id/menu_client_cookies"
+ android:title="@string/client_cookies"
+ yourapp:showAsAction="never" />
+ </menu>
+ </item>
</menu>
</item>
- <!--
- <item android:id="@+id/menu_promo_apps"
- android:title="@string/menu_promo_apps"
- android:icon="@drawable/ic_menu_goto"
- yourapp:showAsAction="never"
-
- />
- -->
-
<item
android:id="@+id/menu_about"
android:icon="@drawable/ic_menu_about"
android:title="@string/menu_about"
- yourapp:showAsAction="never"
-
- />
+ yourapp:showAsAction="never" />
<item
android:id="@+id/menu_exit"
android:icon="@drawable/ic_menu_exit"
android:title="@string/menu_exit"
- yourapp:showAsAction="never"
-
- />
+ yourapp:showAsAction="never" />
</menu>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 0501adf8..ef8d918f 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -169,6 +169,7 @@
<string name="vpn_default_world">Global (Auto)</string>
<string name="hidden_services">Onion Services</string>
+ <string name="v2_hidden_services">V2 Onion Services (Deprecated)</string>
<string name="title_activity_hidden_services">Onion Services</string>
<string name="menu_hidden_services">Onion Services</string>
<string name="save">Save</string>
diff --git a/appcore/src/main/java/org/torproject/android/core/DiskUtils.kt b/appcore/src/main/java/org/torproject/android/core/DiskUtils.kt
index 1a9551b5..8ac067b7 100644
--- a/appcore/src/main/java/org/torproject/android/core/DiskUtils.kt
+++ b/appcore/src/main/java/org/torproject/android/core/DiskUtils.kt
@@ -21,7 +21,6 @@ object DiskUtils {
@Throws(IOException::class)
fun readFileFromAssets(assetFilename: String, context: Context): String {
val reader = BufferedReader(InputStreamReader(context.assets.open(assetFilename)))
- // do reading, usually loop until end of file reading
val sb = StringBuilder()
var mLine = reader.readLine()
while (mLine != null) {
1
0

[orbot/master] V3 Backup and Restore working with Storage Access Framework
by n8fr8@torproject.org 22 Dec '21
by n8fr8@torproject.org 22 Dec '21
22 Dec '21
commit 30e1442f80a2b36f71b9cbf07140de06bf87e024
Author: bim <dsnake(a)protonmail.com>
Date: Fri Nov 27 13:10:25 2020 -0500
V3 Backup and Restore working with Storage Access Framework
---
.../ui/hiddenservices/ClientCookiesActivity.java | 2 +-
.../ui/hiddenservices/HiddenServicesActivity.java | 8 +-
.../ui/hiddenservices/backup/BackupUtils.java | 128 +++++++++++++++++++--
.../dialogs/CookieActionsDialog.java | 2 +-
.../ui/hiddenservices/dialogs/HSActionsDialog.java | 4 +-
.../OnionServiceActionsDialogFragment.java | 6 +-
.../ui/v3onionservice/OnionServicesActivity.java | 14 ++-
.../java/org/torproject/android/core/DiskUtils.kt | 4 +-
8 files changed, 144 insertions(+), 24 deletions(-)
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/ClientCookiesActivity.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/ClientCookiesActivity.java
index 4c43d897..93443678 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/ClientCookiesActivity.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/ClientCookiesActivity.java
@@ -113,7 +113,7 @@ public class ClientCookiesActivity extends AppCompatActivity {
}
private void restoreBackupLegacy() {
- File backupDir = DiskUtils.getOrCreateLegacyBackupDir();
+ File backupDir = DiskUtils.getOrCreateLegacyBackupDir(getString(R.string.app_name));
try {
File[] files = backupDir.listFiles((dir, name) -> name.toLowerCase(Locale.ENGLISH).endsWith(".json"));
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java
index d7429181..7a943093 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java
@@ -107,8 +107,8 @@ public class HiddenServicesActivity extends AppCompatActivity {
}
private void doRestoreLegacy() { // API 16, 17, 18
- File backupDir = DiskUtils.getOrCreateLegacyBackupDir();
- File[] files = backupDir.listFiles((dir, name) -> name.toLowerCase(Locale.ENGLISH).endsWith(".zip"));
+ File backupDir = DiskUtils.getOrCreateLegacyBackupDir(getString(R.string.app_name));
+ File[] files = backupDir.listFiles((dir, name) -> name.toLowerCase().endsWith(".zip"));
if (files != null) {
if (files.length == 0) {
Toast.makeText(this, R.string.create_a_backup_first, Toast.LENGTH_LONG).show();
@@ -120,7 +120,7 @@ public class HiddenServicesActivity extends AppCompatActivity {
new AlertDialog.Builder(this)
.setTitle(R.string.restore_backup)
- .setItems(fileNames, (dialog, which) -> new BackupUtils(HiddenServicesActivity.this).restoreZipBackupLegacy(files[which]))
+ .setItems(fileNames, (dialog, which) -> new BackupUtils(HiddenServicesActivity.this).restoreZipBackupV2Legacy(files[which]))
.show();
}
@@ -132,7 +132,7 @@ public class HiddenServicesActivity extends AppCompatActivity {
if (request == REQUEST_CODE_READ_ZIP_BACKUP) {
if (response != RESULT_OK) return;
BackupUtils backupUtils = new BackupUtils(this);
- backupUtils.restoreZipBackup(data.getData());
+ backupUtils.restoreZipBackupV2(data.getData());
}
}
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/backup/BackupUtils.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/backup/BackupUtils.java
index a10dd7ff..96ffdf5c 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/backup/BackupUtils.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/backup/BackupUtils.java
@@ -15,6 +15,7 @@ import org.torproject.android.R;
import org.torproject.android.service.TorServiceConstants;
import org.torproject.android.ui.hiddenservices.providers.CookieContentProvider;
import org.torproject.android.ui.hiddenservices.providers.HSContentProvider;
+import org.torproject.android.ui.v3onionservice.OnionServiceContentProvider;
import java.io.File;
import java.io.FileInputStream;
@@ -37,8 +38,19 @@ public class BackupUtils {
mResolver = mContext.getContentResolver();
}
- public String createZipBackup(int port, Uri zipFile) {
- String[] files = createFilesForZipping(port);
+ public static boolean isV2OnionAddressValid(String onionToTest) {
+ return onionToTest.matches("([a-z0-9]{16}).onion");
+ }
+
+ public String createV3ZipBackup(String port, Uri zipFile) {
+ String[] files = createFilesForZippingV3(port);
+ ZipIt zip = new ZipIt(files, zipFile, mResolver);
+ if (!zip.zip()) return null;
+ return zipFile.getPath();
+ }
+
+ public String createV2ZipBackup(int port, Uri zipFile) {
+ String[] files = createFilesForZippingV2(port);
ZipIt zip = new ZipIt(files, zipFile, mResolver);
if (!zip.zip())
@@ -47,11 +59,50 @@ public class BackupUtils {
return zipFile.getPath();
}
- public static boolean isV2OnionAddressValid(String onionToTest) {
- return onionToTest.matches("([a-z0-9]{16}).onion");
+ // todo also write out authorized clients...
+ private String[] createFilesForZippingV3(String port) {
+ final String v3BasePath = getV3BasePath() + "/v3" + port + "/";
+ final String hostnamePath = v3BasePath + "hostname",
+ configFilePath = v3BasePath + configFileName,
+ privKeyPath = v3BasePath + "hs_ed25519_secret_key",
+ pubKeyPath = v3BasePath + "hs_ed25519_public_key";
+
+ Cursor portData = mResolver.query(OnionServiceContentProvider.CONTENT_URI, OnionServiceContentProvider.PROJECTION,
+ OnionServiceContentProvider.OnionService.PORT + "=" + port, null, null);
+
+ JSONObject config = new JSONObject();
+ try {
+ if (portData == null || portData.getCount() != 1)
+ return null;
+ portData.moveToNext();
+
+
+ config.put(OnionServiceContentProvider.OnionService.NAME, portData.getString(portData.getColumnIndex(OnionServiceContentProvider.OnionService.NAME)));
+ config.put(OnionServiceContentProvider.OnionService.PORT, portData.getString(portData.getColumnIndex(OnionServiceContentProvider.OnionService.PORT)));
+ config.put(OnionServiceContentProvider.OnionService.ONION_PORT, portData.getString(portData.getColumnIndex(OnionServiceContentProvider.OnionService.ONION_PORT)));
+ config.put(OnionServiceContentProvider.OnionService.DOMAIN, portData.getString(portData.getColumnIndex(OnionServiceContentProvider.OnionService.DOMAIN)));
+ config.put(OnionServiceContentProvider.OnionService.CREATED_BY_USER, portData.getString(portData.getColumnIndex(OnionServiceContentProvider.OnionService.CREATED_BY_USER)));
+ config.put(OnionServiceContentProvider.OnionService.ENABLED, portData.getString(portData.getColumnIndex(OnionServiceContentProvider.OnionService.ENABLED)));
+
+ } catch (JSONException jsone) {
+ jsone.printStackTrace();
+ return null;
+ }
+ portData.close();
+
+ try {
+ FileWriter fileWriter = new FileWriter(configFilePath);
+ fileWriter.write(config.toString());
+ fileWriter.close();
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ return null;
+ }
+
+ return new String[]{hostnamePath, configFilePath, privKeyPath, pubKeyPath};
}
- private String[] createFilesForZipping(int port) {
+ private String[] createFilesForZippingV2(int port) {
File hsBasePath = getHSBasePath();
String configFilePath = hsBasePath + "/hs" + port + "/" + configFileName;
String hostnameFilePath = hsBasePath + "/hs" + port + "/hostname";
@@ -101,7 +152,45 @@ public class BackupUtils {
return new String[]{hostnameFilePath, keyFilePath, configFilePath};
}
- private void extractConfigFromUnzippedBackup(String backupName) {
+ private void extractConfigFromUnzippedBackupV3(String backupName) {
+ File v3BasePath = getV3BasePath();
+ String v3Dir = backupName.substring(0, backupName.lastIndexOf('.'));
+ String configFilePath = v3BasePath + "/" + v3Dir + "/" + configFileName;
+ File v3Path = new File(v3BasePath.getAbsolutePath(), v3Dir);
+ if (!v3Path.isDirectory()) v3Path.mkdirs();
+
+ File configFile = new File(configFilePath);
+ try {
+ FileInputStream fis = new FileInputStream(configFile);
+ FileChannel fc = fis.getChannel();
+ MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
+ String jsonString = Charset.defaultCharset().decode(bb).toString();
+ JSONObject savedValues = new JSONObject(jsonString);
+ ContentValues fields = new ContentValues();
+
+ int port = savedValues.getInt(OnionServiceContentProvider.OnionService.PORT);
+ fields.put(OnionServiceContentProvider.OnionService.PORT, port);
+ fields.put(OnionServiceContentProvider.OnionService.NAME, savedValues.getString(OnionServiceContentProvider.OnionService.NAME));
+ fields.put(OnionServiceContentProvider.OnionService.ONION_PORT, savedValues.getInt(OnionServiceContentProvider.OnionService.ONION_PORT));
+ fields.put(OnionServiceContentProvider.OnionService.DOMAIN, savedValues.getString(OnionServiceContentProvider.OnionService.DOMAIN));
+ fields.put(OnionServiceContentProvider.OnionService.CREATED_BY_USER, savedValues.getInt(OnionServiceContentProvider.OnionService.CREATED_BY_USER));
+ fields.put(OnionServiceContentProvider.OnionService.ENABLED, savedValues.getInt(OnionServiceContentProvider.OnionService.ENABLED));
+
+ Cursor dbService = mResolver.query(OnionServiceContentProvider.CONTENT_URI, OnionServiceContentProvider.PROJECTION,
+ OnionServiceContentProvider.OnionService.PORT + "=" + port, null, null);
+ if (dbService == null || dbService.getCount() == 0)
+ mResolver.insert(OnionServiceContentProvider.CONTENT_URI, fields);
+ else
+ mResolver.update(OnionServiceContentProvider.CONTENT_URI, fields, OnionServiceContentProvider.OnionService.PORT + "=" + port, null);
+ dbService.close();
+ Toast.makeText(mContext, R.string.backup_restored, Toast.LENGTH_LONG).show();
+ } catch (IOException | JSONException e) {
+ e.printStackTrace();
+ Toast.makeText(mContext, R.string.error, Toast.LENGTH_LONG).show();
+ }
+ }
+
+ private void extractConfigFromUnzippedBackupV2(String backupName) {
File mHSBasePath = getHSBasePath();
int port;
String hsDir = backupName.substring(0, backupName.lastIndexOf('.'));
@@ -166,18 +255,22 @@ public class BackupUtils {
return new File(mContext.getFilesDir().getAbsolutePath(), TorServiceConstants.HIDDEN_SERVICES_DIR);
}
- public void restoreZipBackupLegacy(File zipFile) {
+ private File getV3BasePath() {
+ return new File(mContext.getFilesDir().getAbsolutePath(), TorServiceConstants.ONION_SERVICES_DIR);
+ }
+
+ public void restoreZipBackupV2Legacy(File zipFile) {
String backupName = zipFile.getName();
ZipIt zip = new ZipIt(null, null, mResolver);
String hsDir = backupName.substring(0, backupName.lastIndexOf('.'));
File hsPath = new File(getHSBasePath().getAbsolutePath(), hsDir);
if (zip.unzipLegacy(hsPath.getAbsolutePath(), zipFile))
- extractConfigFromUnzippedBackup(backupName);
+ extractConfigFromUnzippedBackupV2(backupName);
else
Toast.makeText(mContext, R.string.error, Toast.LENGTH_LONG).show();
}
- public void restoreZipBackup(Uri zipUri) {
+ public void restoreZipBackupV2(Uri zipUri) {
Cursor returnCursor = mResolver.query(zipUri, null, null, null, null);
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
returnCursor.moveToFirst();
@@ -187,12 +280,27 @@ public class BackupUtils {
String hsDir = backupName.substring(0, backupName.lastIndexOf('.'));
File hsPath = new File(getHSBasePath().getAbsolutePath(), hsDir);
if (new ZipIt(null, zipUri, mResolver).unzip(hsPath.getAbsolutePath()))
- extractConfigFromUnzippedBackup(backupName);
+ extractConfigFromUnzippedBackupV2(backupName);
else
Toast.makeText(mContext, R.string.error, Toast.LENGTH_LONG).show();
+ }
+ public void restoreZipBackupV3(Uri zipUri) {
+ Cursor returnCursor = mResolver.query(zipUri, null, null, null, null);
+ int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
+ returnCursor.moveToFirst();
+ String backupName = returnCursor.getString(nameIndex);
+ returnCursor.close();
+
+ String v3Dir = backupName.substring(0, backupName.lastIndexOf('.'));
+ File v3Paath = new File(getV3BasePath().getAbsolutePath(), v3Dir);
+ if (new ZipIt(null, zipUri, mResolver).unzip(v3Paath.getAbsolutePath()))
+ extractConfigFromUnzippedBackupV3(backupName);
+ else
+ Toast.makeText(mContext, R.string.error, Toast.LENGTH_LONG).show();
}
+
public void restoreKeyBackup(int hsPort, Uri hsKeyPath) {
File mHSBasePath = new File(
mContext.getFilesDir().getAbsolutePath(),
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/CookieActionsDialog.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/CookieActionsDialog.java
index 8c5ef304..d3286ab1 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/CookieActionsDialog.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/CookieActionsDialog.java
@@ -73,7 +73,7 @@ public class CookieActionsDialog extends DialogFragment {
} else { // API 16, 17, and 18
int msg = R.string.backup_saved_at_external_storage;
try {
- File externalStorage = DiskUtils.getOrCreateLegacyBackupDir();
+ File externalStorage = DiskUtils.getOrCreateLegacyBackupDir(getString(R.string.app_name));
String backupFile = externalStorage.getAbsolutePath() + "/" + filename;
String data = createBackupData();
FileWriter writer = new FileWriter(backupFile);
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSActionsDialog.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSActionsDialog.java
index 76932c88..1d2e7844 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSActionsDialog.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSActionsDialog.java
@@ -92,7 +92,7 @@ public class HSActionsDialog extends DialogFragment {
Intent createFile = DiskUtils.createWriteFileIntent(filename, "application/zip");
startActivityForResult(createFile, REQUEST_CODE_WRITE_FILE);
} else { // API 16, 17, 18
- attemptToWriteBackup(Uri.fromFile(new File(DiskUtils.getOrCreateLegacyBackupDir(), filename)));
+ attemptToWriteBackup(Uri.fromFile(new File(DiskUtils.getOrCreateLegacyBackupDir(getString(R.string.app_name)), filename)));
}
}
@@ -107,7 +107,7 @@ public class HSActionsDialog extends DialogFragment {
private void attemptToWriteBackup(Uri outputFile) {
BackupUtils backupUtils = new BackupUtils(getContext());
- String backup = backupUtils.createZipBackup(port, outputFile);
+ String backup = backupUtils.createV2ZipBackup(port, outputFile);
Toast.makeText(getContext(), backup != null ? R.string.backup_saved_at_external_storage : R.string.error, Toast.LENGTH_LONG).show();
dismiss();
}
diff --git a/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServiceActionsDialogFragment.java b/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServiceActionsDialogFragment.java
index 822a45f2..4d26270d 100644
--- a/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServiceActionsDialogFragment.java
+++ b/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServiceActionsDialogFragment.java
@@ -61,7 +61,7 @@ public class OnionServiceActionsDialogFragment extends DialogFragment {
}
private void doBackup(Bundle arguments, Context context) {
- String filename = "onion_service" + arguments.getInt(OnionServicesActivity.BUNDLE_KEY_PORT) + ".zip";
+ String filename = "onion_service" + arguments.getString(OnionServicesActivity.BUNDLE_KEY_PORT) + ".zip";
if (arguments.getString(OnionServicesActivity.BUNDLE_KEY_DOMAIN) == null) {
Toast.makeText(context, R.string.please_restart_Orbot_to_enable_the_changes, Toast.LENGTH_LONG).show();
return;
@@ -70,7 +70,7 @@ public class OnionServiceActionsDialogFragment extends DialogFragment {
Intent createFileIntent = DiskUtils.createWriteFileIntent(filename, "application/zip");
startActivityForResult(createFileIntent, REQUEST_CODE_WRITE_FILE);
} else { // APIs 16, 17, 18
- attemptToWriteBackup(Uri.fromFile(new File(DiskUtils.getOrCreateLegacyBackupDir(), filename)));
+ attemptToWriteBackup(Uri.fromFile(new File(DiskUtils.getOrCreateLegacyBackupDir(getString(R.string.app_name)), filename)));
}
}
@@ -85,7 +85,7 @@ public class OnionServiceActionsDialogFragment extends DialogFragment {
private void attemptToWriteBackup(Uri outputFile) {
BackupUtils backupUtils = new BackupUtils(getContext());
-// String backup = backupUtils.createZipBackup(port, outputFile); TODO need to break apart backup logic for v2 and v3 onions
+ String backup = backupUtils.createV3ZipBackup(getArguments().getString(OnionServicesActivity.BUNDLE_KEY_PORT), outputFile);
Toast.makeText(getContext(), backup != null ? R.string.backup_saved_at_external_storage : R.string.error, Toast.LENGTH_LONG).show();
dismiss();
}
diff --git a/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServicesActivity.java b/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServicesActivity.java
index 3be04731..eed43a71 100644
--- a/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServicesActivity.java
+++ b/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServicesActivity.java
@@ -2,6 +2,7 @@ package org.torproject.android.ui.v3onionservice;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.Intent;
import android.database.ContentObserver;
import android.database.Cursor;
import android.os.Bundle;
@@ -19,11 +20,13 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton;
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;
public class OnionServicesActivity extends AppCompatActivity {
static final String BUNDLE_KEY_ID = "id", BUNDLE_KEY_PORT = "port", BUNDLE_KEY_DOMAIN = "domain";
private static final String WHERE_SELECTION_CLAUSE = OnionServiceContentProvider.OnionService.CREATED_BY_USER + "=1";
+ private static final int REQUEST_CODE_READ_ZIP_BACKUP = 347;
private RadioButton radioShowUserServices, radioShowAppServices;
private FloatingActionButton fab;
private ContentResolver mContentResolver;
@@ -73,7 +76,8 @@ public class OnionServicesActivity extends AppCompatActivity {
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.menu_restore_backup) {
if (DiskUtils.supportsStorageAccessFramework()) {
-
+ Intent readFileIntent = DiskUtils.createReadFileIntent("application/zip");
+ startActivityForResult(readFileIntent, REQUEST_CODE_READ_ZIP_BACKUP);
} else { // 16, 17, 18
}
@@ -81,6 +85,14 @@ public class OnionServicesActivity extends AppCompatActivity {
return super.onOptionsItemSelected(item);
}
+ @Override
+ protected void onActivityResult(int requestCode, int result, Intent data) {
+ super.onActivityResult(requestCode, result, data);
+ if (requestCode == REQUEST_CODE_READ_ZIP_BACKUP && result == RESULT_OK) {
+ new BackupUtils(this).restoreZipBackupV3(data.getData());
+ }
+ }
+
private class OnionServiceObserver extends ContentObserver {
OnionServiceObserver(Handler handler) {
diff --git a/appcore/src/main/java/org/torproject/android/core/DiskUtils.kt b/appcore/src/main/java/org/torproject/android/core/DiskUtils.kt
index be74aa4e..1a9551b5 100644
--- a/appcore/src/main/java/org/torproject/android/core/DiskUtils.kt
+++ b/appcore/src/main/java/org/torproject/android/core/DiskUtils.kt
@@ -66,9 +66,9 @@ object DiskUtils {
fun readFile(contentResolver: ContentResolver, file: File): String = readFileFromInputStream(contentResolver, Uri.fromFile(file))
@JvmStatic
- fun getOrCreateLegacyBackupDir(): File? {
+ fun getOrCreateLegacyBackupDir(directoryName: String): File? {
if (Environment.MEDIA_MOUNTED != Environment.getExternalStorageState()) return null
- val dir = File(Environment.getExternalStorageDirectory(), )
+ val dir = File(Environment.getExternalStorageDirectory(), directoryName)
return if (!dir.isDirectory && !dir.mkdirs()) null else dir
}
1
0
commit feb3de3b4b907bcbd9c78522197027355036965b
Author: bim <dsnake(a)protonmail.com>
Date: Sat Nov 28 12:55:46 2020 -0500
removed unused interface
---
.../main/java/org/torproject/android/MainConstants.java | 15 ---------------
.../java/org/torproject/android/OrbotMainActivity.java | 5 +++--
.../android/ui/onboarding/CustomBridgesActivity.java | 6 +++---
3 files changed, 6 insertions(+), 20 deletions(-)
diff --git a/app/src/main/java/org/torproject/android/MainConstants.java b/app/src/main/java/org/torproject/android/MainConstants.java
deleted file mode 100644
index e08f4e4b..00000000
--- a/app/src/main/java/org/torproject/android/MainConstants.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.torproject.android;
-
-public interface MainConstants {
-
- //EXIT COUNTRY CODES
- String[] COUNTRY_CODES = {"DE", "AT", "SE", "CH", "IS", "CA", "US", "ES", "FR", "BG", "PL", "AU", "BR", "CZ", "DK", "FI", "GB", "HU", "NL", "JP", "RO", "RU", "SG", "SK"};
-
- //path to check Tor against
- String URL_TOR_CHECK = "https://check.torproject.org";
-
- String URL_TOR_BRIDGES = "https://bridges.torproject.org/bridges";
-
- String EMAIL_TOR_BRIDGES = "bridges(a)torproject.org";
-
-}
diff --git a/app/src/main/java/org/torproject/android/OrbotMainActivity.java b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
index abc87cc0..83f321e9 100644
--- a/app/src/main/java/org/torproject/android/OrbotMainActivity.java
+++ b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
@@ -90,8 +90,6 @@ import java.util.StringTokenizer;
import pl.bclogic.pulsator4droid.library.PulsatorLayout;
import static androidx.core.content.FileProvider.getUriForFile;
-import static org.torproject.android.MainConstants.COUNTRY_CODES;
-import static org.torproject.android.MainConstants.URL_TOR_CHECK;
import static org.torproject.android.service.TorServiceConstants.ACTION_START;
import static org.torproject.android.service.TorServiceConstants.ACTION_START_VPN;
import static org.torproject.android.service.TorServiceConstants.ACTION_STOP_VPN;
@@ -115,6 +113,9 @@ public class OrbotMainActivity extends AppCompatActivity implements OrbotConstan
private static final int MESSAGE_PORTS = 3;
private static final float ROTATE_FROM = 0.0f;
private static final float ROTATE_TO = 360.0f * 4f;// 3.141592654f * 32.0f;
+ private static final String[] COUNTRY_CODES = {"DE", "AT", "SE", "CH", "IS", "CA", "US", "ES", "FR", "BG", "PL", "AU", "BR", "CZ", "DK", "FI", "GB", "HU", "NL", "JP", "RO", "RU", "SG", "SK"};
+ private static final String URL_TOR_CHECK = "https://check.torproject.org";
+ ;
// this is what takes messages or values from the callback threads or other non-mainUI threads
// and passes them back into the main UI thread for display to the user
private final Handler mStatusUpdateHandler = new MainActivityStatusUpdateHandler(this);
diff --git a/app/src/main/java/org/torproject/android/ui/onboarding/CustomBridgesActivity.java b/app/src/main/java/org/torproject/android/ui/onboarding/CustomBridgesActivity.java
index 6fce9852..f20ba4ff 100644
--- a/app/src/main/java/org/torproject/android/ui/onboarding/CustomBridgesActivity.java
+++ b/app/src/main/java/org/torproject/android/ui/onboarding/CustomBridgesActivity.java
@@ -37,11 +37,11 @@ import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
-import static org.torproject.android.MainConstants.EMAIL_TOR_BRIDGES;
-import static org.torproject.android.MainConstants.URL_TOR_BRIDGES;
-
public class CustomBridgesActivity extends AppCompatActivity implements TextWatcher {
+ private static final String EMAIL_TOR_BRIDGES = "bridges(a)torproject.org";
+ private static final String URL_TOR_BRIDGES = "https://bridges.torproject.org/bridges";
+
private EditText mEtPastedBridges;
// configures an EditText we assume to be multiline and nested in a ScrollView to be independently scrollable
1
0

[orbot/master] V3 and V2 onions can coexist, Orbot ready to receive V3s from netcipher
by n8fr8@torproject.org 22 Dec '21
by n8fr8@torproject.org 22 Dec '21
22 Dec '21
commit a26c18e1c95a488213467a937d0ba96fce2b1d63
Author: bim <dsnake(a)protonmail.com>
Date: Sat Nov 28 23:56:12 2020 -0500
V3 and V2 onions can coexist, Orbot ready to receive V3s from netcipher
---
.../org/torproject/android/OrbotMainActivity.java | 124 ++++++++++++---------
app/src/main/res/values/strings.xml | 2 +-
.../torproject/android/service/OrbotService.java | 4 +-
3 files changed, 75 insertions(+), 55 deletions(-)
diff --git a/app/src/main/java/org/torproject/android/OrbotMainActivity.java b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
index 83f321e9..a2922af7 100644
--- a/app/src/main/java/org/torproject/android/OrbotMainActivity.java
+++ b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
@@ -10,7 +10,6 @@ import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
@@ -74,6 +73,7 @@ import org.torproject.android.ui.hiddenservices.permissions.PermissionManager;
import org.torproject.android.ui.hiddenservices.providers.HSContentProvider;
import org.torproject.android.ui.onboarding.BridgeWizardActivity;
import org.torproject.android.ui.onboarding.OnboardingActivity;
+import org.torproject.android.ui.v3onionservice.OnionServiceContentProvider;
import org.torproject.android.ui.v3onionservice.OnionServicesActivity;
import java.io.File;
@@ -102,13 +102,14 @@ import static org.torproject.android.service.vpn.VpnPrefs.PREFS_KEY_TORIFIED;
public class OrbotMainActivity extends AppCompatActivity implements OrbotConstants {
- public final static String INTENT_ACTION_REQUEST_HIDDEN_SERVICE = "org.torproject.android.REQUEST_HS_PORT";
- public final static String INTENT_ACTION_REQUEST_START_TOR = "org.torproject.android.START_TOR";
- private final static int REQUEST_VPN = 8888;
- private final static int REQUEST_SETTINGS = 0x9874;
- private final static int REQUEST_VPN_APPS_SELECT = 8889;
+ private static final String INTENT_ACTION_REQUEST_HIDDEN_SERVICE = "org.torproject.android.REQUEST_HS_PORT";
+ private static final String INTENT_ACTION_REQUEST_V3_ONION_SERVICE = "org.torproject.android.REQUEST_V3_ONION_SERVICE";
+ private static final String INTENT_ACTION_REQUEST_START_TOR = "org.torproject.android.START_TOR";
+ private static final int REQUEST_VPN = 8888;
+ private static final int REQUEST_SETTINGS = 0x9874;
+ private static final int REQUEST_VPN_APPS_SELECT = 8889;
// message types for mStatusUpdateHandler
- private final static int STATUS_UPDATE = 1;
+ private static final int STATUS_UPDATE = 1;
private static final int MESSAGE_TRAFFIC_COUNT = 2;
private static final int MESSAGE_PORTS = 3;
private static final float ROTATE_FROM = 0.0f;
@@ -120,18 +121,18 @@ public class OrbotMainActivity extends AppCompatActivity implements OrbotConstan
// and passes them back into the main UI thread for display to the user
private final Handler mStatusUpdateHandler = new MainActivityStatusUpdateHandler(this);
PulsatorLayout mPulsator;
- AlertDialog aDialog = null;
+ AlertDialog aDialog;
/* Useful UI bits */
- private TextView lblStatus = null; //the main text display widget
- private TextView lblPorts = null;
- private ImageView imgStatus = null; //the main touchable image for activating Orbot
- private TextView downloadText = null;
- private TextView uploadText = null;
- private TextView mTxtOrbotLog = null;
- private Button mBtnStart = null;
- private SwitchCompat mBtnVPN = null;
- private SwitchCompat mBtnBridges = null;
- private Spinner spnCountries = null;
+ private TextView lblStatus; //the main text display widget
+ private TextView lblPorts;
+ private ImageView imgStatus; //the main touchable image for activating Orbot
+ private TextView downloadText;
+ private TextView uploadText;
+ private TextView mTxtOrbotLog;
+ private Button mBtnStart;
+ private SwitchCompat mBtnVPN;
+ private SwitchCompat mBtnBridges;
+ private Spinner spnCountries;
private DrawerLayout mDrawer;
/* Some tracking bits */
private String torStatus = null; //latest status reported from the tor service
@@ -538,8 +539,30 @@ public class OrbotMainActivity extends AppCompatActivity implements OrbotConstan
sendIntentToService(ACTION_START_VPN);
}
- private void enableHiddenServicePort(String hsName, final int hsPort, int hsRemotePort,
- final String backupToPackage, final Uri hsKeyPath, final Boolean authCookie) {
+ private void enableV3OnionServiceOnV3(int localPort, int onionPort, String name) {
+ ContentValues fields = new ContentValues();
+ fields.put(OnionServiceContentProvider.OnionService.PORT, localPort);
+ fields.put(OrbotService.OnionService.NAME, name);
+ fields.put(OnionServiceContentProvider.OnionService.PORT, onionPort);
+ fields.put(OnionServiceContentProvider.OnionService.ENABLED, 1);
+ fields.put(OnionServiceContentProvider.OnionService.CREATED_BY_USER, 0);
+
+ ContentResolver contentResolver = getContentResolver();
+ contentResolver.insert(OnionServiceContentProvider.CONTENT_URI, fields);
+
+ if (torStatus.equals(TorServiceConstants.STATUS_OFF)) {
+ startTor();
+ } else {
+ stopTor();
+ Toast.makeText(this, R.string.start_tor_again_for_finish_the_process, Toast.LENGTH_LONG).show();
+ }
+
+
+
+ }
+
+ private void enableHiddenServicePortV2(String hsName, final int hsPort, int hsRemotePort,
+ final String backupToPackage, final Uri hsKeyPath, final Boolean authCookie) {
String onionHostname = null;
if (hsName == null)
@@ -582,9 +605,7 @@ public class OrbotMainActivity extends AppCompatActivity implements OrbotConstan
startTor();
} else {
stopTor();
- Toast.makeText(
- this, R.string.start_tor_again_for_finish_the_process, Toast.LENGTH_LONG
- ).show();
+ Toast.makeText(this, R.string.start_tor_again_for_finish_the_process, Toast.LENGTH_LONG).show();
}
new Thread() {
@@ -668,41 +689,44 @@ public class OrbotMainActivity extends AppCompatActivity implements OrbotConstan
return;
switch (action) {
- case INTENT_ACTION_REQUEST_HIDDEN_SERVICE:
- final int hiddenServicePort = intent.getIntExtra("hs_port", -1);
- final int hiddenServiceRemotePort = intent.getIntExtra("hs_onion_port", -1);
- final String hiddenServiceName = intent.getStringExtra("hs_name");
- final String backupToPackage = intent.getStringExtra("hs_backup_to_package");
- final Boolean authCookie = intent.getBooleanExtra("hs_auth_cookie", false);
- final Uri mKeyUri = intent.getData();
-
- DialogInterface.OnClickListener dialogClickListener = (dialog, which) -> {
- if (which == DialogInterface.BUTTON_POSITIVE) {
- enableHiddenServicePort(
- hiddenServiceName, hiddenServicePort,
- hiddenServiceRemotePort, backupToPackage,
- mKeyUri, authCookie
- );
- }
- };
-
- String requestMsg = getString(R.string.hidden_service_request, String.valueOf(hiddenServicePort));
- new AlertDialog.Builder(this).setMessage(requestMsg)
- .setPositiveButton(R.string.allow, dialogClickListener)
- .setNegativeButton(R.string.deny, dialogClickListener).show();
+ case INTENT_ACTION_REQUEST_V3_ONION_SERVICE:
+ final int v3LocalPort = intent.getIntExtra("localPort", -1);
+ final int v3onionPort = intent.getIntExtra("onionPort", v3LocalPort);
+ String name = intent.getStringExtra("name") ;
+ if (name == null) name = "v3" + v3LocalPort;
+ final String finalName = name;
+ new AlertDialog.Builder(this)
+ .setMessage(getString(R.string.hidden_service_request, String.valueOf(v3LocalPort)))
+ .setPositiveButton(R.string.allow, (d, w) -> enableV3OnionServiceOnV3(v3LocalPort, v3onionPort, finalName))
+ .setNegativeButton(R.string.deny, (d, w) -> d.dismiss())
+ .show();
+ return;
+ case INTENT_ACTION_REQUEST_HIDDEN_SERVICE:
+ final int v2hiddenServicePort = intent.getIntExtra("hs_port", -1);
+ final int v2hiddenServiceRemotePort = intent.getIntExtra("hs_onion_port", -1);
+ final String v2hiddenServiceName = intent.getStringExtra("hs_name");
+ final String v2backupToPackage = intent.getStringExtra("hs_backup_to_package");
+ final Boolean v2authCookie = intent.getBooleanExtra("hs_auth_cookie", false);
+ final Uri v2KeyUri = intent.getData();
+
+ String v2RequestMsg = getString(R.string.hidden_service_request, String.valueOf(v2hiddenServicePort));
+ new AlertDialog.Builder(this).setMessage(v2RequestMsg)
+ .setPositiveButton(R.string.allow, (dialog, which) -> enableHiddenServicePortV2(
+ v2hiddenServiceName, v2hiddenServicePort,
+ v2hiddenServiceRemotePort, v2backupToPackage,
+ v2KeyUri, v2authCookie))
+ .setNegativeButton(R.string.deny, (d, w) -> d.dismiss()).show();
return; //don't null the setIntent() as we need it later
case INTENT_ACTION_REQUEST_START_TOR:
autoStartFromIntent = true;
startTor();
-
break;
+
case Intent.ACTION_VIEW:
String urlString = intent.getDataString();
-
if (urlString != null) {
-
if (urlString.toLowerCase(Locale.ENGLISH).startsWith("bridge://")) {
String newBridgeValue = urlString.substring(9); //remove the bridge protocol piece
try {
@@ -712,17 +736,13 @@ public class OrbotMainActivity extends AppCompatActivity implements OrbotConstan
}
showAlert(getString(R.string.bridges_updated), getString(R.string.restart_orbot_to_use_this_bridge_) + newBridgeValue, false);
-
setNewBridges(newBridgeValue);
}
}
break;
}
-
updateStatus(null, torStatus);
-
setIntent(null);
-
}
private void setNewBridges(String newBridgeValue) {
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index ef8d918f..c888c856 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -100,7 +100,7 @@
<string name="libevent_version">LibEvent: http://www.monkey.org/~provos/libevent/</string>
<string name="obfsproxy_version">Obfs4proxy: https://github.com/Yawning/obfs4</string>
<string name="openssl_version">OpenSSL: http://www.openssl.org</string>
- <string name="hidden_service_request">An app wants to open onion server port %1$s to the Tor network. This is safe if you trust the app.</string>
+ <string name="hidden_service_request">An app wants to open onion server on port %1$s to the Tor network. This is safe if you trust the app.</string>
<string name="allow">Allow</string>
<string name="deny">Deny</string>
<string name="found_existing_tor_process">found existing Tor process…</string>
diff --git a/orbotservice/src/main/java/org/torproject/android/service/OrbotService.java b/orbotservice/src/main/java/org/torproject/android/service/OrbotService.java
index 10acf5de..b9dd34a1 100644
--- a/orbotservice/src/main/java/org/torproject/android/service/OrbotService.java
+++ b/orbotservice/src/main/java/org/torproject/android/service/OrbotService.java
@@ -1370,8 +1370,8 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
ContentResolver contentResolver = getApplicationContext().getContentResolver();
addV3OnionServicesToTorrc(extraLines, contentResolver);
-// addV2HiddenServicesToTorrc(extraLines, contentResolver);
-// addV2ClientCookiesToTorrc(extraLines, contentResolver);
+ addV2HiddenServicesToTorrc(extraLines, contentResolver);
+ addV2ClientCookiesToTorrc(extraLines, contentResolver);
return extraLines;
}
1
0

[orbot/master] generate nonsense named auth_privates locally when OrbotService is running
by n8fr8@torproject.org 22 Dec '21
by n8fr8@torproject.org 22 Dec '21
22 Dec '21
commit f13b53b8384eff025501efcb187c45ad3140e801
Author: bim <dsnake(a)protonmail.com>
Date: Thu Jan 28 16:04:26 2021 -0500
generate nonsense named auth_privates locally when OrbotService is running
---
.../src/main/java/org/torproject/android/service/OrbotService.java | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/orbotservice/src/main/java/org/torproject/android/service/OrbotService.java b/orbotservice/src/main/java/org/torproject/android/service/OrbotService.java
index 9a401ac6..7f6612a9 100644
--- a/orbotservice/src/main/java/org/torproject/android/service/OrbotService.java
+++ b/orbotservice/src/main/java/org/torproject/android/service/OrbotService.java
@@ -1452,10 +1452,11 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
}
torrc.append("ClientOnionAuthDir " + mV3AuthBasePath.getAbsolutePath()).append('\n');
try {
+ int i = 0;
while (v3auths.moveToNext()) {
String domain = v3auths.getString(v3auths.getColumnIndex(V3ClientAuth.DOMAIN));
String hash = v3auths.getString(v3auths.getColumnIndex(V3ClientAuth.HASH));
- File authFile = new File(mV3AuthBasePath, domain + ".auth_private");
+ File authFile = new File(mV3AuthBasePath, (i++) + ".auth_private");
authFile.createNewFile();
FileOutputStream fos = new FileOutputStream(authFile);
fos.write(buildV3ClientAuthFile(domain, hash).getBytes());
1
0
commit 23b86e518fc269eb180f931d7d08308ad654a1ce
Author: bim <dsnake(a)protonmail.com>
Date: Sun Dec 13 14:13:32 2020 -0500
missing netcipher integration stuff
---
app/src/main/AndroidManifest.xml | 6 ++++--
app/src/main/java/org/torproject/android/OrbotMainActivity.java | 6 +++---
2 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 7b81951f..0f69c722 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -39,7 +39,6 @@
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
-
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
@@ -52,9 +51,12 @@
</intent-filter>
<intent-filter>
<action android:name="org.torproject.android.REQUEST_HS_PORT" />
-
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
+ <intent-filter>
+ <action android:name="org.torproject.android.REQUEST_V3_ONION_SERVICE"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ </intent-filter>
<intent-filter>
<action android:name="org.torproject.android.START_TOR" />
diff --git a/app/src/main/java/org/torproject/android/OrbotMainActivity.java b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
index a2922af7..773c7fa6 100644
--- a/app/src/main/java/org/torproject/android/OrbotMainActivity.java
+++ b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
@@ -539,11 +539,11 @@ public class OrbotMainActivity extends AppCompatActivity implements OrbotConstan
sendIntentToService(ACTION_START_VPN);
}
- private void enableV3OnionServiceOnV3(int localPort, int onionPort, String name) {
+ private void enableV3OnionService(int localPort, int onionPort, String name) {
ContentValues fields = new ContentValues();
fields.put(OnionServiceContentProvider.OnionService.PORT, localPort);
fields.put(OrbotService.OnionService.NAME, name);
- fields.put(OnionServiceContentProvider.OnionService.PORT, onionPort);
+ fields.put(OnionServiceContentProvider.OnionService.ONION_PORT, onionPort);
fields.put(OnionServiceContentProvider.OnionService.ENABLED, 1);
fields.put(OnionServiceContentProvider.OnionService.CREATED_BY_USER, 0);
@@ -697,7 +697,7 @@ public class OrbotMainActivity extends AppCompatActivity implements OrbotConstan
final String finalName = name;
new AlertDialog.Builder(this)
.setMessage(getString(R.string.hidden_service_request, String.valueOf(v3LocalPort)))
- .setPositiveButton(R.string.allow, (d, w) -> enableV3OnionServiceOnV3(v3LocalPort, v3onionPort, finalName))
+ .setPositiveButton(R.string.allow, (d, w) -> enableV3OnionService(v3LocalPort, v3onionPort, finalName))
.setNegativeButton(R.string.deny, (d, w) -> d.dismiss())
.show();
return;
1
0

[orbot/master] removed bridge config from barebones orbot XML settings, bridges can be configured with more ease from our own interface
by n8fr8@torproject.org 22 Dec '21
by n8fr8@torproject.org 22 Dec '21
22 Dec '21
commit 80e037095c1dd32ca7fbfcc40fd7a3e9219b5b63
Author: bim <dsnake(a)protonmail.com>
Date: Wed Feb 3 10:17:52 2021 -0500
removed bridge config from barebones orbot XML settings, bridges can be configured with more ease from our own interface
---
app/src/main/res/values-ar/strings.xml | 2 --
app/src/main/res/values-ay/strings.xml | 3 ---
app/src/main/res/values-az/strings.xml | 2 --
app/src/main/res/values-be/strings.xml | 3 ---
app/src/main/res/values-bg/strings.xml | 2 --
app/src/main/res/values-ca/strings.xml | 3 ---
app/src/main/res/values-cs-rCZ/strings.xml | 2 --
app/src/main/res/values-da/strings.xml | 2 --
app/src/main/res/values-de/strings.xml | 3 ---
app/src/main/res/values-el/strings.xml | 3 ---
app/src/main/res/values-eo/strings.xml | 3 +--
app/src/main/res/values-es-rAR/strings.xml | 3 ---
app/src/main/res/values-es/strings.xml | 3 ---
app/src/main/res/values-et/strings.xml | 2 --
app/src/main/res/values-eu/strings.xml | 3 ---
app/src/main/res/values-fa/strings.xml | 3 ---
app/src/main/res/values-fi/strings.xml | 3 ---
app/src/main/res/values-fr-rFR/strings.xml | 3 ---
app/src/main/res/values-fr/strings.xml | 3 ---
app/src/main/res/values-gl/strings.xml | 3 ---
app/src/main/res/values-he/strings.xml | 3 ---
app/src/main/res/values-hi/strings.xml | 3 ---
app/src/main/res/values-hr/strings.xml | 2 --
app/src/main/res/values-hu/strings.xml | 3 ---
app/src/main/res/values-id/strings.xml | 2 --
app/src/main/res/values-in-rID/strings.xml | 2 --
app/src/main/res/values-is/strings.xml | 3 ---
app/src/main/res/values-it/strings.xml | 3 ---
app/src/main/res/values-iw/strings.xml | 2 --
app/src/main/res/values-ja/strings.xml | 3 ---
app/src/main/res/values-ko/strings.xml | 2 --
app/src/main/res/values-lv/strings.xml | 2 --
app/src/main/res/values-mk/strings.xml | 3 ---
app/src/main/res/values-ms-rMY/strings.xml | 2 --
app/src/main/res/values-ms/strings.xml | 2 --
app/src/main/res/values-nb/strings.xml | 3 ---
app/src/main/res/values-nl/strings.xml | 3 ---
app/src/main/res/values-pl/strings.xml | 3 ---
app/src/main/res/values-pt-rBR/strings.xml | 3 ---
app/src/main/res/values-pt-rPT/strings.xml | 3 ---
app/src/main/res/values-pt/strings.xml | 3 ---
app/src/main/res/values-ro/strings.xml | 2 --
app/src/main/res/values-ru/strings.xml | 3 ---
app/src/main/res/values-si-rLK/strings.xml | 2 --
app/src/main/res/values-sk/strings.xml | 2 --
app/src/main/res/values-sr/strings.xml | 3 ---
app/src/main/res/values-sv/strings.xml | 3 ---
app/src/main/res/values-th/strings.xml | 3 ---
app/src/main/res/values-tl/strings.xml | 2 --
app/src/main/res/values-tr/strings.xml | 3 ---
app/src/main/res/values-uk/strings.xml | 3 ---
app/src/main/res/values-vi/strings.xml | 2 --
app/src/main/res/values-zh-rCN/strings.xml | 3 ---
app/src/main/res/values-zh-rTW/strings.xml | 3 ---
app/src/main/res/values/strings.xml | 3 ---
app/src/main/res/xml/preferences.xml | 16 ----------------
56 files changed, 1 insertion(+), 161 deletions(-)
diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml
index ecc01ea3..55d46f5c 100644
--- a/app/src/main/res/values-ar/strings.xml
+++ b/app/src/main/res/values-ar/strings.xml
@@ -66,8 +66,6 @@
<string name="use_only_these_specified_nodes">استخدم فقط تلك النقاط المحددة</string>
<string name="bridges">الجسور</string>
<string name="use_bridges">استخدم الجسور</string>
- <string name="ip_address_and_port_of_bridges">عنوان الانترنت و المنفذ للجسور</string>
- <string name="enter_bridge_addresses">أدخل عناوين الجسور</string>
<string name="relays">المرحلات</string>
<string name="relaying">يرحل</string>
<string name="enable_your_device_to_be_a_non_exit_relay">اسمح لجهازك ليكون مرحل غير نهائي</string>
diff --git a/app/src/main/res/values-ay/strings.xml b/app/src/main/res/values-ay/strings.xml
index 4345c554..94f23307 100644
--- a/app/src/main/res/values-ay/strings.xml
+++ b/app/src/main/res/values-ay/strings.xml
@@ -67,9 +67,6 @@
<string name="use_only_these_specified_nodes">Aka sutiñchat puriñawjanakak apnaqam</string>
<string name="bridges">Jalakipañanaka</string>
<string name="use_bridges">Jalakipañanak apnaqaña</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Tor llika manqhan yaqha mantañanak qhantayaña</string>
- <string name="ip_address_and_port_of_bridges">IP ukanakamp jalakipañ apayañ thakhinakampi</string>
- <string name="enter_bridge_addresses">Jalakipañanakan chiqawjanakap qillqantam</string>
<string name="relays">Ch\'iqiyirinaka</string>
<string name="relaying">Apayat ch\'iqiyaña</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Jan uñstir ch\'iqiyirïñapatak dispositivo aqtayam</string>
diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml
index 6d9dfc8c..81e8a670 100644
--- a/app/src/main/res/values-az/strings.xml
+++ b/app/src/main/res/values-az/strings.xml
@@ -66,8 +66,6 @@
<string name="use_only_these_specified_nodes">*Yalnız* bu xüsusi kəsişmələri istifadə et</string>
<string name="bridges">Körpülər</string>
<string name="use_bridges">Körpü İstifadə Et</string>
- <string name="ip_address_and_port_of_bridges">Körpülərin IP ünvanı və portu</string>
- <string name="enter_bridge_addresses">Körpü Ünvanlarını Daxil et</string>
<string name="relays">Keçidlər</string>
<string name="relaying">Keçidləmə</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Cihazının son-keçid funksiyasını aktivləşdir</string>
diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml
index 4e45235e..db227e13 100644
--- a/app/src/main/res/values-be/strings.xml
+++ b/app/src/main/res/values-be/strings.xml
@@ -67,9 +67,6 @@
<string name="use_only_these_specified_nodes">Выкарыстоўваць *толькі* гэтыя зададзеныя вузлы</string>
<string name="bridges">Масты</string>
<string name="use_bridges">Выкарыстоўваць масты</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Уключыць альтэрнатыўныя ўваходныя вузлы ў сетку Tor</string>
- <string name="ip_address_and_port_of_bridges">IP-адрасы і парты мастоў</string>
- <string name="enter_bridge_addresses">Увядзіце адрасы мастоў</string>
<string name="relays">Рэтранслятары</string>
<string name="relaying">Рэтрансляцыя</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Дазволіць вашай прыладзе быць невыходным рэтранслятарам</string>
diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml
index 843911ce..6892262d 100644
--- a/app/src/main/res/values-bg/strings.xml
+++ b/app/src/main/res/values-bg/strings.xml
@@ -66,8 +66,6 @@
<string name="use_only_these_specified_nodes">Използвай *само* изброените node-ве</string>
<string name="bridges">Бриджове</string>
<string name="use_bridges">Използвай Бриджове</string>
- <string name="ip_address_and_port_of_bridges">IP адрес и порт на бриджове</string>
- <string name="enter_bridge_addresses">Въведи адреси на бриджове</string>
<string name="relays">Препращачи(Relays)</string>
<string name="relaying">Препращане</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Разреши устройството ти да бъде не изходен препращач</string>
diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml
index 734b1619..01e1b3a4 100644
--- a/app/src/main/res/values-ca/strings.xml
+++ b/app/src/main/res/values-ca/strings.xml
@@ -67,9 +67,6 @@
<string name="use_only_these_specified_nodes">Utilitza *només* aquests nodes especificats</string>
<string name="bridges">Ponts</string>
<string name="use_bridges">Utilitza ponts</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Activar entrades alternes a la xarxa Tor</string>
- <string name="ip_address_and_port_of_bridges">Adreça IP i port dels ponts</string>
- <string name="enter_bridge_addresses">Introduïu les adreces del pont</string>
<string name="relays">Reemissors</string>
<string name="relaying">Reemissió</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Activa el vostre dispositiu per ser un reemissor sense sortida</string>
diff --git a/app/src/main/res/values-cs-rCZ/strings.xml b/app/src/main/res/values-cs-rCZ/strings.xml
index 74ee8ca1..88f17543 100644
--- a/app/src/main/res/values-cs-rCZ/strings.xml
+++ b/app/src/main/res/values-cs-rCZ/strings.xml
@@ -66,8 +66,6 @@
<string name="use_only_these_specified_nodes">Použít *pouze* tyto specifické nody</string>
<string name="bridges">Bridge</string>
<string name="use_bridges">Použít bridge</string>
- <string name="ip_address_and_port_of_bridges">IP adresy a porty bridgů</string>
- <string name="enter_bridge_addresses">Zadejte adresy bridgů</string>
<string name="relays">Relé</string>
<string name="relaying">Používání relé</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Spuštění zařízení jako neodchozího relé</string>
diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml
index b80d5735..3d77ae62 100644
--- a/app/src/main/res/values-da/strings.xml
+++ b/app/src/main/res/values-da/strings.xml
@@ -65,8 +65,6 @@
<string name="use_only_these_specified_nodes">Brug *kun* disse specificerede punkter</string>
<string name="bridges">Broer</string>
<string name="use_bridges">Brug broer</string>
- <string name="ip_address_and_port_of_bridges">IP adresser og porte på broer</string>
- <string name="enter_bridge_addresses">Indtast bro-adresser</string>
<string name="relays">Relæer</string>
<string name="relaying">Relæfunktion</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Lad denne enhed være et ikke-udgangs relæ</string>
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index 1cfaf26f..06fb7220 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -67,9 +67,6 @@
<string name="use_only_these_specified_nodes">*Nur* diese angegebenen Netzknoten nutzen</string>
<string name="bridges">Brücken</string>
<string name="use_bridges">Brücken benutzen</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Alternative Zugangswege ins Tor-Netzwerk aktivieren</string>
- <string name="ip_address_and_port_of_bridges">IP-Adresse und Port der Brücken</string>
- <string name="enter_bridge_addresses">Brückenadressen eingeben</string>
<string name="relays">Relais</string>
<string name="relaying">Weiterleitung</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Ihr Gerät als Nichtausgangsrelais aktivieren</string>
diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml
index 92e1fbf7..617fa00e 100644
--- a/app/src/main/res/values-el/strings.xml
+++ b/app/src/main/res/values-el/strings.xml
@@ -67,9 +67,6 @@
<string name="use_only_these_specified_nodes">Χρήση *μόνον* αυτών των συγκεκριμένων κόμβων</string>
<string name="bridges">Γέφυρες</string>
<string name="use_bridges">Χρήση γεφυρών</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Ενεργοποίηση εναλλακτικών κόμβων εισόδου στο δίκτυο Tor</string>
- <string name="ip_address_and_port_of_bridges">Διεύθυνση ΙΡ και θύρα των γεφυρών</string>
- <string name="enter_bridge_addresses">Εισάγετε την διεύθυνση της γέφυρας</string>
<string name="relays">Αναμεταδότες</string>
<string name="relaying">Γίνεται αναμετάδοση</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Μετατρέψτε την συσκευή σας σε ένα αναμεταδότη μη-εξόδου</string>
diff --git a/app/src/main/res/values-eo/strings.xml b/app/src/main/res/values-eo/strings.xml
index 4dd26485..c543030c 100644
--- a/app/src/main/res/values-eo/strings.xml
+++ b/app/src/main/res/values-eo/strings.xml
@@ -55,8 +55,7 @@
<string name="use_only_these_specified_nodes">Uzi *nur* tiujn ĉi nodojn</string>
<string name="bridges">Pontoj</string>
<string name="use_bridges">Uzi Pontojn</string>
- <string name="ip_address_and_port_of_bridges">IP-adresoj kaj pordoj de pontoj</string>
- <string name="enter_or_port">Entajpu OR-pordon</string>
+ <string name="enter_or_port">Entajpu OR-pordon</string>
<string name="relay_nickname">Kaŝnomo de la relajso</string>
<string name="the_nickname_for_your_tor_relay">Kaŝnomo por via Tor-relajso</string>
<string name="enter_a_custom_relay_nickname">Entajpu propran kaŝnomon de la relajso</string>
diff --git a/app/src/main/res/values-es-rAR/strings.xml b/app/src/main/res/values-es-rAR/strings.xml
index ad1fbc05..b3f1e95a 100644
--- a/app/src/main/res/values-es-rAR/strings.xml
+++ b/app/src/main/res/values-es-rAR/strings.xml
@@ -67,9 +67,6 @@
<string name="use_only_these_specified_nodes">utilice *solo* estos nodos especificos </string>
<string name="bridges">puentes</string>
<string name="use_bridges">usar puentes</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Habilitar entradas alternativas en la red de Tor</string>
- <string name="ip_address_and_port_of_bridges">direccion IP y puerto de puentes</string>
- <string name="enter_bridge_addresses">introduzca las direcciones de puente</string>
<string name="relays">retransmitir</string>
<string name="relaying">retransmision </string>
<string name="enable_your_device_to_be_a_non_exit_relay">Habilite su dispositivo para que sea retransmision sin salida</string>
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index d1ada60e..3a040826 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -67,9 +67,6 @@
<string name="use_only_these_specified_nodes">Usar *sólo* estos nodos especificados</string>
<string name="bridges">Bridges (repetidores puente) </string>
<string name="use_bridges">Usar bridges</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Habilitar entradas alternativas hacia el interior de la red Tor</string>
- <string name="ip_address_and_port_of_bridges">Direcciones IP y puertos de los bridges</string>
- <string name="enter_bridge_addresses">Introduzca direcciones de bridge</string>
<string name="relays">Repetidores</string>
<string name="relaying">Repetición de tráfico</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Habilitar que su dispositivo no sea repetidor de salida (de la red Tor) </string>
diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml
index 22cadc69..a718a5a1 100644
--- a/app/src/main/res/values-et/strings.xml
+++ b/app/src/main/res/values-et/strings.xml
@@ -62,8 +62,6 @@
<string name="use_only_these_specified_nodes">Kasuta *ainult* neid märgitud sõlmi</string>
<string name="bridges">Sillad</string>
<string name="use_bridges">Kasuta sildu</string>
- <string name="ip_address_and_port_of_bridges">Sildade IP aadressid ja pordinumbrid</string>
- <string name="enter_bridge_addresses">Sisestage silla aadressid</string>
<string name="relays">Edastajad</string>
<string name="relaying">Edastamine</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Luba oma seadmel hakata mitte-väljund edastajaks</string>
diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml
index 49653869..8ae44b68 100644
--- a/app/src/main/res/values-eu/strings.xml
+++ b/app/src/main/res/values-eu/strings.xml
@@ -67,9 +67,6 @@
<string name="use_only_these_specified_nodes">Erabili *bakarrik* zehaztutako nodo hauek</string>
<string name="bridges">Zubiak</string>
<string name="use_bridges">Erabili zubiak</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Gaitu ordezko sarrerak Tor sarera</string>
- <string name="ip_address_and_port_of_bridges">Zubien IP helbidea eta ataka</string>
- <string name="enter_bridge_addresses">Sartu zubien helbideak</string>
<string name="relays">Erreleak</string>
<string name="relaying">Erreleatzea</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Gaitu zure gailua ez-irteerako errelea izatea</string>
diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml
index a3d49674..2131daba 100644
--- a/app/src/main/res/values-fa/strings.xml
+++ b/app/src/main/res/values-fa/strings.xml
@@ -67,9 +67,6 @@
<string name="use_only_these_specified_nodes">فقط * از این گره های مشخص شده استفاده کنید* </string>
<string name="bridges">Bridges</string>
<string name="use_bridges">از پل Bridges کن</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">ورودیهای جایگزین به شبکه تور را فعال کن</string>
- <string name="ip_address_and_port_of_bridges">آدرس آی پی و پورتِ پل ها</string>
- <string name="enter_bridge_addresses">آدرس Bridges را وارد کنید</string>
<string name="relays">بازپخش کننده ها</string>
<string name="relaying">درحال بازپخش</string>
<string name="enable_your_device_to_be_a_non_exit_relay">دستگاه خود را برای یک بازپخش کننده غیر-خروجی فعال کنید</string>
diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml
index ead60538..035935e7 100644
--- a/app/src/main/res/values-fi/strings.xml
+++ b/app/src/main/res/values-fi/strings.xml
@@ -66,8 +66,6 @@
<string name="use_only_these_specified_nodes">Käytä *vain* näitä solmuja</string>
<string name="bridges">Sillat</string>
<string name="use_bridges">Käytä siltoja</string>
- <string name="ip_address_and_port_of_bridges">Siltojen IP-osoitteet ja portit</string>
- <string name="enter_bridge_addresses">Kirjoita siltaosoitteet</string>
<string name="relays">Releet</string>
<string name="relaying">Releytys</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Ota laitteesi käyttöön välireleenä</string>
@@ -128,7 +126,6 @@
<string name="disable">Poista käytöstä</string>
<string name="enable">Ota käyttöön</string>
<string name="wizard_details_msg">Orbot on avoimen lähdekoodin sovellus, joka sisältää Tor, Obfs4Proxy, BadVPN Tun2Socks, LibEvent ja Polipo. Se tarjoaa paikallisen HTTP-välityspalvelimen (8118) ja SOCKS-välityspalvelimen (9050) Tor-verkkoon. Orbotilla on myös ominaisuus, rootattulla laitteella, lähettää kaiken Internet-liikenteen Torin kautta.</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Ota käyttöön vaihtoehtoiset sisäänkäynnit Tor-verkkoon</string>
<string name="obfsproxy_version">Obfs4proxy: https://github.com/Yawning/obfs4</string>
<string name="openssl_version">OpenSSL: http://www.openssl.org</string>
<string name="hidden_service_request">Sovellus haluaa avata sipulipalvelimen portin %1$s Tor-verkkoon. Tämä on turvallista, jos luotat sovellukseen.</string>
diff --git a/app/src/main/res/values-fr-rFR/strings.xml b/app/src/main/res/values-fr-rFR/strings.xml
index 6f65958b..fe90952a 100644
--- a/app/src/main/res/values-fr-rFR/strings.xml
+++ b/app/src/main/res/values-fr-rFR/strings.xml
@@ -66,8 +66,6 @@
<string name="use_only_these_specified_nodes">N’utiliser *que* ces nœuds précis</string>
<string name="bridges">Ponts</string>
<string name="use_bridges">Utiliser des ponts</string>
- <string name="ip_address_and_port_of_bridges">Adresse IP et port des ponts</string>
- <string name="enter_bridge_addresses">Saisir les adresses des ponts</string>
<string name="relays">Relais</string>
<string name="relaying">Relais</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Faire de votre appareil un relais de non-sortie</string>
@@ -122,7 +120,6 @@
<string name="name">Name</string>
<string name="please_restart_Orbot_to_enable_the_changes">Veuillez redémarrer Orbot pour activer les changements</string>
<string name="wizard_details_msg">Orbot est une application à code source ouvert qui comprend Tor, Obfs4Proxy, BadVPN Tun2Socks et LibEvent. Elle fournit un mandataire HTTP local (8118) et un mandataire SOCKS (9050) vers le réseau Tor. Sur un appareil débridé, Orbot peut aussi faire passer tout le trafic Internet par Tor.</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Activer les entrées auxiliaires vers le réseau Tor</string>
<string name="obfsproxy_version">Obfs4proxy : https://github.com/Yawning/obfs4</string>
<string name="openssl_version">OpenSSL : http://www.openssl.org</string>
<string name="hidden_service_request">Une appli veut ouvrir le port %1$s du serveur onion vers le réseau Tor. Cette action est sûre si vous faites confiance à cette appli.</string>
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index dbc39e3f..0b59592f 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -67,9 +67,6 @@
<string name="use_only_these_specified_nodes">Utiliser *uniquement * ces nœuds spécifiés</string>
<string name="bridges">Ponts</string>
<string name="use_bridges">Utiliser des ponts</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Activer les entrées de remplacement vers le réseau Tor</string>
- <string name="ip_address_and_port_of_bridges">Adresse IP et port des ponts</string>
- <string name="enter_bridge_addresses">Saisir les adresses des ponts</string>
<string name="relays">Relais</string>
<string name="relaying">Relais</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Configurez votre appareil pour être un relais de non-sortie</string>
diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml
index 03e4e8c0..07e7bf3b 100644
--- a/app/src/main/res/values-gl/strings.xml
+++ b/app/src/main/res/values-gl/strings.xml
@@ -67,9 +67,6 @@
<string name="use_only_these_specified_nodes">Usar *só* este nodos específicos</string>
<string name="bridges">Pontes</string>
<string name="use_bridges">Usar Pontes</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Activar entradas alternativas a rede Tor</string>
- <string name="ip_address_and_port_of_bridges">Dirección IP e porto das pontes</string>
- <string name="enter_bridge_addresses">Introduza Direccións das Pontes</string>
<string name="relays">Reenvíos</string>
<string name="relaying">Reenvío</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Habilite o seu dispositivo para ser un reenvío non de saída</string>
diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml
index 253b2b4e..4706ce98 100644
--- a/app/src/main/res/values-he/strings.xml
+++ b/app/src/main/res/values-he/strings.xml
@@ -67,9 +67,6 @@
<string name="use_only_these_specified_nodes">השתמש *רק* בצמתים מצוינים אלו</string>
<string name="bridges">גשרים</string>
<string name="use_bridges">השתמש בגשרים</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">אפשר כניסות חלופיות לתוך רשת Tor</string>
- <string name="ip_address_and_port_of_bridges">כתובת IP ופתחה של גשרים</string>
- <string name="enter_bridge_addresses">הכנס כתובות גשר</string>
<string name="relays">ממסרים</string>
<string name="relaying">ממסור</string>
<string name="enable_your_device_to_be_a_non_exit_relay">אפשר למכשיר שלך להיות תחנת ממסר שאיננה יציאה</string>
diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml
index 79e4af38..2290a2b9 100644
--- a/app/src/main/res/values-hi/strings.xml
+++ b/app/src/main/res/values-hi/strings.xml
@@ -68,9 +68,6 @@
<string name="use_only_these_specified_nodes">* केवल * इन निर्दिष्ट नोड्स का उपयोग करें</string>
<string name="bridges">पुल</string>
<string name="use_bridges">पुल का उपयोग करें</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">टोरी नेटवर्क में वैकल्पिक प्रवेश द्वार सक्षम करें</string>
- <string name="ip_address_and_port_of_bridges">आईपी पता और पुल का बंदरगाह</string>
- <string name="enter_bridge_addresses">ब्रिज पते दर्ज करें</string>
<string name="relays">रिले</string>
<string name="relaying">रिलेइंग</string>
<string name="enable_your_device_to_be_a_non_exit_relay">अपने डिवाइस को गैर-बाहर निकलें रिले होने के लिए सक्षम करें</string>
diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml
index 2299594f..ecd7321e 100644
--- a/app/src/main/res/values-hr/strings.xml
+++ b/app/src/main/res/values-hr/strings.xml
@@ -66,8 +66,6 @@
<string name="use_only_these_specified_nodes">Koristi *samo* ove navedene čvorove</string>
<string name="bridges">Mostovi</string>
<string name="use_bridges">Koristi Mostove</string>
- <string name="ip_address_and_port_of_bridges">IP adresa i port mostova</string>
- <string name="enter_bridge_addresses">Unesi Adrese Mostova</string>
<string name="relays">Releji</string>
<string name="relaying">Prenošenje</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Omogućite svom uređaju da bude ne-izlazni relej</string>
diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml
index afd3a737..b567a4f2 100644
--- a/app/src/main/res/values-hu/strings.xml
+++ b/app/src/main/res/values-hu/strings.xml
@@ -67,9 +67,6 @@
<string name="use_only_these_specified_nodes">*Csak* ezeknek a megadott csomópontoknak a használata</string>
<string name="bridges">Hidak</string>
<string name="use_bridges">Hidak használata</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">A Tor hálózat bejáratok váltogatásának engedélyezése </string>
- <string name="ip_address_and_port_of_bridges">A hidak IP címe és portja</string>
- <string name="enter_bridge_addresses">Add meg a híd címeit</string>
<string name="relays">Átjátszók</string>
<string name="relaying">Átjátszás</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Engedélyezd az eszközödnek, hogy nem-átjátszó elosztó legyen</string>
diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml
index 161b3590..550517cc 100644
--- a/app/src/main/res/values-id/strings.xml
+++ b/app/src/main/res/values-id/strings.xml
@@ -66,8 +66,6 @@
<string name="use_only_these_specified_nodes">Pakai *hanya* spesifik node</string>
<string name="bridges">Bridges</string>
<string name="use_bridges">Pakai Bridges</string>
- <string name="ip_address_and_port_of_bridges">Alamat IP dan port bridges</string>
- <string name="enter_bridge_addresses">Memasuki Alamat Bridge</string>
<string name="relays">Relays</string>
<string name="relaying">Sedang me-Relay</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Nyalakan perangkat anda menjadi non-exit relay</string>
diff --git a/app/src/main/res/values-in-rID/strings.xml b/app/src/main/res/values-in-rID/strings.xml
index ec6674b7..e77dfaf1 100644
--- a/app/src/main/res/values-in-rID/strings.xml
+++ b/app/src/main/res/values-in-rID/strings.xml
@@ -66,8 +66,6 @@
<string name="use_only_these_specified_nodes">Pakai *hanya* spesifik node</string>
<string name="bridges">Bridges</string>
<string name="use_bridges">Pakai Bridges</string>
- <string name="ip_address_and_port_of_bridges">Alamat IP dan port bridges</string>
- <string name="enter_bridge_addresses">Memasuki Alamat Bridge</string>
<string name="relays">Relays</string>
<string name="relaying">Sedang me-Relay</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Nyalakan perangkat anda menjadi non-exit relay</string>
diff --git a/app/src/main/res/values-is/strings.xml b/app/src/main/res/values-is/strings.xml
index 929f15ae..a3577a1c 100644
--- a/app/src/main/res/values-is/strings.xml
+++ b/app/src/main/res/values-is/strings.xml
@@ -67,9 +67,6 @@
<string name="use_only_these_specified_nodes">Nota *aðeins* þessa tilteknu punkta</string>
<string name="bridges">Brýr</string>
<string name="use_bridges">Nota brýr</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Virkjaðu varaleiðir inn á Tor-netið</string>
- <string name="ip_address_and_port_of_bridges">IP-vistfang og brúargáttir</string>
- <string name="enter_bridge_addresses">Settu inn vistföng fyrir brýr</string>
<string name="relays">Endurvarpar</string>
<string name="relaying">Endurvörpun</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Leyfa tækinu þínu að vera útgangslaus endurvarpi</string>
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index 93a4c0e9..a63a8086 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -67,9 +67,6 @@
<string name="use_only_these_specified_nodes">Utilizza *solo* i nodi specificati</string>
<string name="bridges">Bridge</string>
<string name="use_bridges">Utilizza i bridge</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Attiva entrate alternate nella rete Tor</string>
- <string name="ip_address_and_port_of_bridges">Indirizzo IP e porta dei bridge</string>
- <string name="enter_bridge_addresses">Inserire gli indirizzi dei bridge</string>
<string name="relays">Relays (Inoltratori)</string>
<string name="relaying">Relaying (Inoltro)</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Abilita il tuo dispositivo per essere un relay non di uscita</string>
diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml
index c772f2b7..b71b379e 100644
--- a/app/src/main/res/values-iw/strings.xml
+++ b/app/src/main/res/values-iw/strings.xml
@@ -59,8 +59,6 @@
<string name="use_only_these_specified_nodes">השתמש *רק* בצמתים מצוינים אלו</string>
<string name="bridges">גשרים</string>
<string name="use_bridges">השתמש בגשרים</string>
- <string name="ip_address_and_port_of_bridges">כתובת ה-IP ויציאה של הגשרים</string>
- <string name="enter_bridge_addresses">הכנס כתובות גשר</string>
<string name="relays">ממסרים</string>
<string name="relaying">ממסור</string>
<string name="enable_your_device_to_be_a_non_exit_relay">אפשר למכשיר שלך להיות תחנת ממסר שאיננה יציאה</string>
diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml
index 7e9d6f8f..df9a15a0 100644
--- a/app/src/main/res/values-ja/strings.xml
+++ b/app/src/main/res/values-ja/strings.xml
@@ -67,9 +67,6 @@
<string name="use_only_these_specified_nodes">ここに指定したノードのみを使用</string>
<string name="bridges">ブリッジ</string>
<string name="use_bridges">ブリッジを使う</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Torネットワークへの代替入口を有効化</string>
- <string name="ip_address_and_port_of_bridges">ブリッジのIPアドレスとポート</string>
- <string name="enter_bridge_addresses">ブリッジのアドレスを入力</string>
<string name="relays">リレー</string>
<string name="relaying">リレー中</string>
<string name="enable_your_device_to_be_a_non_exit_relay">この端末を非出口リレーにする</string>
diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml
index 3d169dcd..75fb06bd 100644
--- a/app/src/main/res/values-ko/strings.xml
+++ b/app/src/main/res/values-ko/strings.xml
@@ -66,8 +66,6 @@
<string name="use_only_these_specified_nodes">이 특정한 노드*만* 사용합니다.</string>
<string name="bridges">중계서버</string>
<string name="use_bridges">중계서버 사용</string>
- <string name="ip_address_and_port_of_bridges">중계서버의 IP 주소와 </string>
- <string name="enter_bridge_addresses">중게서버 주소 입력</string>
<string name="relays">중계서버</string>
<string name="relaying">중계</string>
<string name="enable_your_device_to_be_a_non_exit_relay">귀하의 장치를 출구가 아닌 중계서버로 활성화</string>
diff --git a/app/src/main/res/values-lv/strings.xml b/app/src/main/res/values-lv/strings.xml
index 04117f3e..a28009ce 100644
--- a/app/src/main/res/values-lv/strings.xml
+++ b/app/src/main/res/values-lv/strings.xml
@@ -66,8 +66,6 @@
<string name="use_only_these_specified_nodes">Izmantojiet *vienīgi* šos norādītos mezglus</string>
<string name="bridges">Tilti</string>
<string name="use_bridges">Lietot tiltus</string>
- <string name="ip_address_and_port_of_bridges">Tiltu ports un IP addrese</string>
- <string name="enter_bridge_addresses">Ievadiet tiltu adreses</string>
<string name="relays">Retranslatori</string>
<string name="relaying">Retranslēšana</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Iespējot Jūsu iekārtu par bezapstājas retranslatoru</string>
diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml
index b8371e62..39c4a3ed 100644
--- a/app/src/main/res/values-mk/strings.xml
+++ b/app/src/main/res/values-mk/strings.xml
@@ -67,9 +67,6 @@
<string name="use_only_these_specified_nodes">Користете ги *само* овие наведени јазли</string>
<string name="bridges">Мостови</string>
<string name="use_bridges">Користи мостови</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Овозможи алтернативен влезови на Tor мрежата</string>
- <string name="ip_address_and_port_of_bridges">IP-адреса и порта на мостовите</string>
- <string name="enter_bridge_addresses">Внесете адреси на мостовите</string>
<string name="relays">Релеи</string>
<string name="relaying">Препраќање</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Овозможи го уредот да биде реле без излез</string>
diff --git a/app/src/main/res/values-ms-rMY/strings.xml b/app/src/main/res/values-ms-rMY/strings.xml
index e6a87012..0a0ce49b 100644
--- a/app/src/main/res/values-ms-rMY/strings.xml
+++ b/app/src/main/res/values-ms-rMY/strings.xml
@@ -60,8 +60,6 @@
<string name="use_only_these_specified_nodes">Guna *hanya* nod-nod ini</string>
<string name="bridges">Jambatan</string>
<string name="use_bridges">Guna Jambatan</string>
- <string name="ip_address_and_port_of_bridges">Alamat IP dan pelabuhan jambatan</string>
- <string name="enter_bridge_addresses">Masukkan Alamat Jambatan</string>
<string name="relays">Relays</string>
<string name="relaying">Relaying</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Membolehkan peranti anda untuk menjadi geganti bukan keluar</string>
diff --git a/app/src/main/res/values-ms/strings.xml b/app/src/main/res/values-ms/strings.xml
index d018f812..01d411b4 100644
--- a/app/src/main/res/values-ms/strings.xml
+++ b/app/src/main/res/values-ms/strings.xml
@@ -52,8 +52,6 @@
<string name="use_only_these_specified_nodes">Guna *hanya* nod-nod ini</string>
<string name="bridges">Jambatan</string>
<string name="use_bridges">Guna Jambatan</string>
- <string name="ip_address_and_port_of_bridges">Alamat IP dan pelabuhan jambatan</string>
- <string name="enter_bridge_addresses">Masukkan Alamat Jambatan</string>
<string name="relays">Relays</string>
<string name="relaying">Relaying</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Membolehkan peranti anda untuk menjadi geganti bukan keluar</string>
diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml
index b4b00835..22bfbb5f 100644
--- a/app/src/main/res/values-nb/strings.xml
+++ b/app/src/main/res/values-nb/strings.xml
@@ -66,8 +66,6 @@
<string name="use_only_these_specified_nodes">Bruk *bare* disse angitte nodene</string>
<string name="bridges">Broer</string>
<string name="use_bridges">Bruk broer</string>
- <string name="ip_address_and_port_of_bridges">IP-adresser og broporter</string>
- <string name="enter_bridge_addresses">Skriv inn broadresser</string>
<string name="relays">Reléer</string>
<string name="relaying">Videresending</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Aktiver enheten din som et rutingsstafettoppsett uten utgående trafikk</string>
@@ -155,7 +153,6 @@
<string name="full_device_vpn">VPN for hele enheten</string>
<string name="vpn_disabled">VPN Deaktivert</string>
<string name="wizard_details_msg">Orbot er et fritt program som inneholder Tor, Obfs4Proxy, BadVPN Tun2Socks, LibEvent og Polipo. Den gir en lokal HTTP-proxy (8118) og en SOCKS-mellomtjener (9050) inn i Tor-nettverket. Orbot har også muligheten til å sende all Internett-trafikk gjennom Tor på enheter med superbrukertilgang.</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Aktiver alternative innganger til Tor-nettverket</string>
<string name="hidden_service_request">Et program ønsker å åpne løktjenerport %1$s til Tor-nettverket. Dette er trygt såfremt du stoler på programmet.</string>
<string name="pref_open_proxy_on_all_interfaces_title">Åpne proxy på alle grensesnitt</string>
<string name="pref_http_title">Tor HTTP</string>
diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml
index 68ab5930..53dec601 100644
--- a/app/src/main/res/values-nl/strings.xml
+++ b/app/src/main/res/values-nl/strings.xml
@@ -67,9 +67,6 @@
<string name="use_only_these_specified_nodes">Gebruik *enkel* deze opgegeven nodes</string>
<string name="bridges">Bridges</string>
<string name="use_bridges">Gebruik bridges</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Alternatieve toegangen tot het Tor-netwerk inschakelen</string>
- <string name="ip_address_and_port_of_bridges">IP-adres en poort van bridges</string>
- <string name="enter_bridge_addresses">Voer bridge-adres in</string>
<string name="relays">Relays</string>
<string name="relaying">Relayen</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Stel je toestel in staat om een non-exit relay te zijn</string>
diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
index c1438138..7b21da06 100644
--- a/app/src/main/res/values-pl/strings.xml
+++ b/app/src/main/res/values-pl/strings.xml
@@ -66,8 +66,6 @@
<string name="use_only_these_specified_nodes">Użyj *tylko* tych określonych węzłów</string>
<string name="bridges">Mostki</string>
<string name="use_bridges">Użyj mostków</string>
- <string name="ip_address_and_port_of_bridges">Adres IP i port mostków</string>
- <string name="enter_bridge_addresses">Wpisz adresy mostków</string>
<string name="relays">Przekaźniki</string>
<string name="relaying">Przekazywanie</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Pozwól swojemu urządzeniu zostać bezwyjściowym przekaźnikiem</string>
@@ -130,7 +128,6 @@
<string name="please_restart_Orbot_to_enable_the_changes">Proszę zrestartować Orbot, aby zmiany mogły wejść w życie</string>
<string name="disable">Wyłącz</string>
<string name="enable">Włącz</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Włącz alternatywne wejścia do sieci Tor</string>
<string name="pref_open_proxy_on_all_interfaces_title">Otwórz serwer proxy na wszystkich interfejsach</string>
<string name="pref_http_dialog">Konfiguracja portu HTTP</string>
<string name="pref_http_title">Tor HTTP</string>
diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml
index 6208a885..01d46ec5 100644
--- a/app/src/main/res/values-pt-rBR/strings.xml
+++ b/app/src/main/res/values-pt-rBR/strings.xml
@@ -67,9 +67,6 @@
<string name="use_only_these_specified_nodes">Use *somente* estes nós específicos</string>
<string name="bridges">Pontes</string>
<string name="use_bridges">Usar Pontes</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Ative as entradas alternativas para a Rede Tor</string>
- <string name="ip_address_and_port_of_bridges">Endereço IP e as porta das pontes</string>
- <string name="enter_bridge_addresses">Insira os Endereços das Pontes</string>
<string name="relays">Retransmissores</string>
<string name="relaying">Retransmitindo</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Ativar o seu dispositivo para não ser um retransmissor de saída</string>
diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml
index 246c52aa..1feb7f3b 100644
--- a/app/src/main/res/values-pt-rPT/strings.xml
+++ b/app/src/main/res/values-pt-rPT/strings.xml
@@ -111,7 +111,6 @@
<string name="bridges_updated">Pontes Atualizadas</string>
<string name="pref_proxy_host_title">Anfitrião Proxy de Saída</string>
<string name="pref_proxy_host_dialog">Inserir Hospedeiro Proxy</string>
- <string name="ip_address_and_port_of_bridges">Endereço de IP e porta das pontes</string>
<string name="pref_proxy_password_summary">Senha do Proxy (Opcional)</string>
<string name="project_home">Projeto Home(s):</string>
<string name="pref_proxy_type_title">Tipo de Proxy de Saída</string>
@@ -178,8 +177,6 @@
<string name="relay_port">Porta Retransmissora</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Ativar o seu aparelho para ser um retransmissor de sem saída</string>
<string name="relaying">Retransmitindo</string>
- <string name="enter_bridge_addresses">Insira os Endereços das Pontes</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Ative as entradas alternativas para a Rede Tor</string>
<string name="strict_nodes">Nós Estritos</string>
<string name="fingerprints_nicks_countries_and_addresses_to_exclude">Impressões digitais, apelidos, países e endereços para excluir</string>
<string name="fingerprints_nicks_countries_and_addresses_for_the_last_hop">Impressões digitais, apelidos, países e endereços para a última etapa</string>
diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml
index 66764a46..c4c6cf7d 100644
--- a/app/src/main/res/values-pt/strings.xml
+++ b/app/src/main/res/values-pt/strings.xml
@@ -47,7 +47,6 @@
<string name="error">Erro</string>
<string name="bridges">Pontes</string>
<string name="use_bridges">Usar Pontes</string>
- <string name="ip_address_and_port_of_bridges">Endereço de IP e porta das pontes</string>
<string name="enter_or_port">Inserir OU porta</string>
<string name="reachable_ports">Portas alcançáveis</string>
<string name="ports_reachable_behind_a_restrictive_firewall">Portas alcançáveis por detrás de uma Firewal restritiva</string>
@@ -169,8 +168,6 @@
<string name="enable_your_device_to_be_a_non_exit_relay">Ativar o seu aparelho para ser um retransmissor de sem saída</string>
<string name="relaying">Retransmitindo</string>
<string name="relays">Retransmissores</string>
- <string name="enter_bridge_addresses">Insira os Endereços das Pontes</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Ative as entradas alternativas para a Rede Tor</string>
<string name="use_only_these_specified_nodes">Use *somente* estes nós específicos</string>
<string name="strict_nodes">Nós Estritos</string>
<string name="enter_exclude_nodes">Digite Nós Excluídos</string>
diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml
index 082f971d..e7873128 100644
--- a/app/src/main/res/values-ro/strings.xml
+++ b/app/src/main/res/values-ro/strings.xml
@@ -66,8 +66,6 @@
<string name="use_only_these_specified_nodes">Foloseste *doar* nodurile specificate</string>
<string name="bridges">Punţi</string>
<string name="use_bridges">Foloseşte punţi</string>
- <string name="ip_address_and_port_of_bridges">Adresa IP şi port pentru punţi</string>
- <string name="enter_bridge_addresses">Introdu adresa pentru punte</string>
<string name="relays">Comutatoare</string>
<string name="relaying">Comutare</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Activeaza dispozitivul sa fie un comutator fara iesire</string>
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index d07bfe88..fe3fdab2 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -67,9 +67,6 @@
<string name="use_only_these_specified_nodes">Использовать *только* эти заданные узлы</string>
<string name="bridges">Мосты</string>
<string name="use_bridges">Использовать мосты</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Включить альтернативные входные узлы в сеть Tor</string>
- <string name="ip_address_and_port_of_bridges">IP-адреса и порты мостов</string>
- <string name="enter_bridge_addresses">Введите адреса мостов</string>
<string name="relays">Ретрансляторы</string>
<string name="relaying">Ретрансляция</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Разрешить вашему устройству быть невыходным ретранслятором</string>
diff --git a/app/src/main/res/values-si-rLK/strings.xml b/app/src/main/res/values-si-rLK/strings.xml
index c9eea93d..d36c0885 100644
--- a/app/src/main/res/values-si-rLK/strings.xml
+++ b/app/src/main/res/values-si-rLK/strings.xml
@@ -55,8 +55,6 @@
<string name="use_only_these_specified_nodes">ඉහත සදහන් නොඩු *පමණක්* භාවිතා කරන්න </string>
<string name="bridges">සේතු</string>
<string name="use_bridges">සේතු භාවිතා කරන්න </string>
- <string name="ip_address_and_port_of_bridges">IP ලිපිනය හා සේතුවල පෝට</string>
- <string name="enter_bridge_addresses">සේතු ලිපිනයන් ඇතුළු කරන්න </string>
<string name="relays">ප්රතියෝජකය</string>
<string name="relaying">ප්රතියෝජනය </string>
<string name="enable_your_device_to_be_a_non_exit_relay">ඔබේ උපාංගය නික්ම-නොයන ප්රතියෝජකයක් බවට සබල කරන්න </string>
diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml
index a0dcbdeb..95117ec2 100644
--- a/app/src/main/res/values-sk/strings.xml
+++ b/app/src/main/res/values-sk/strings.xml
@@ -66,8 +66,6 @@
<string name="use_only_these_specified_nodes">Použiť *len* tieto špecifikované uzly</string>
<string name="bridges">Premostenia</string>
<string name="use_bridges">Použiť premostenia</string>
- <string name="ip_address_and_port_of_bridges">IP adresy a porty premostení</string>
- <string name="enter_bridge_addresses">Vložiť adresy premostení</string>
<string name="relays">Relé</string>
<string name="relaying">Postúpenie relé</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Povoliť, aby nebolo vaše zariadenie východiskovým relé / non-exit</string>
diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml
index 7065d1db..5361a70e 100644
--- a/app/src/main/res/values-sr/strings.xml
+++ b/app/src/main/res/values-sr/strings.xml
@@ -67,9 +67,6 @@
<string name="use_only_these_specified_nodes">Користи САМО ове наведене чворове</string>
<string name="bridges">Мостови</string>
<string name="use_bridges">Користи bridge</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Омогућите алтернативне улазе у Тор мрежу</string>
- <string name="ip_address_and_port_of_bridges">IP адреса и порт bridge-а</string>
- <string name="enter_bridge_addresses">Унесите bridge адресу </string>
<string name="relays">Релеји</string>
<string name="relaying">Релејирање</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Омогућите вашем уређају да буде релеј без излаза</string>
diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml
index e85aac53..0eca52c5 100644
--- a/app/src/main/res/values-sv/strings.xml
+++ b/app/src/main/res/values-sv/strings.xml
@@ -67,9 +67,6 @@
<string name="use_only_these_specified_nodes">Använd *enbart* dessa specificerade noder</string>
<string name="bridges">Broar</string>
<string name="use_bridges">Använd Broar</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Aktivera alternativa ingångar i Tor-nätverket</string>
- <string name="ip_address_and_port_of_bridges">IP adress och port för broar</string>
- <string name="enter_bridge_addresses">Skriv in Bro Adresser</string>
<string name="relays">Reläer</string>
<string name="relaying">Överföring</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Aktivera din enhet till att vara ett icke-utgångsrelä</string>
diff --git a/app/src/main/res/values-th/strings.xml b/app/src/main/res/values-th/strings.xml
index f4837520..f19efe27 100644
--- a/app/src/main/res/values-th/strings.xml
+++ b/app/src/main/res/values-th/strings.xml
@@ -67,9 +67,6 @@
<string name="use_only_these_specified_nodes">ใช้ *เฉพาะ* โหนดที่ระบุเหล่านี้เท่านั้น</string>
<string name="bridges">Bridges</string>
<string name="use_bridges">ใช้งาน Bridges</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">เปิดใช้งานทางเข้าอื่นเข้าสู่เครือข่าย Tor</string>
- <string name="ip_address_and_port_of_bridges">ที่อยู่ไอพีและพอร์ตของ Bridges</string>
- <string name="enter_bridge_addresses">ระบุที่อยู่ของ Bridge</string>
<string name="relays">รีเลย์</string>
<string name="relaying">การรีเลย์</string>
<string name="enable_your_device_to_be_a_non_exit_relay">ทำให้อุปกรณ์ของคุณทำงานเป็นรีเลย์แบบไม่ใช่ทางออก</string>
diff --git a/app/src/main/res/values-tl/strings.xml b/app/src/main/res/values-tl/strings.xml
index 4102384f..13709dba 100644
--- a/app/src/main/res/values-tl/strings.xml
+++ b/app/src/main/res/values-tl/strings.xml
@@ -63,8 +63,6 @@
<string name="use_only_these_specified_nodes">Gumamit ng *only* sa mga ispesipikong nodes </string>
<string name="bridges">Bridges</string>
<string name="use_bridges">Gumamit ng Bridges</string>
- <string name="ip_address_and_port_of_bridges">IP address at port ng bridges</string>
- <string name="enter_bridge_addresses">Ilagay ang Bridge Addresses</string>
<string name="relays">Relays</string>
<string name="relaying">Relaying</string>
<string name="enable_your_device_to_be_a_non_exit_relay">I-enable ang iyong device na non-exit relay</string>
diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml
index f68726b6..0fb7d35e 100644
--- a/app/src/main/res/values-tr/strings.xml
+++ b/app/src/main/res/values-tr/strings.xml
@@ -67,9 +67,6 @@
<string name="use_only_these_specified_nodes">*Yalnız* bu düğümler kullanılsın</string>
<string name="bridges">Köprüler</string>
<string name="use_bridges">Köprüleri Kullan</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Alternatif Tor ağı girişleri kullanılabilsin</string>
- <string name="ip_address_and_port_of_bridges">Köprülerin IP adresleri ve bağlantı noktaları</string>
- <string name="enter_bridge_addresses">Köprü Adreslerini Girin</string>
<string name="relays">Aktarıcılar</string>
<string name="relaying">Aktarım</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Aygıtınız çıkış yapmayan bir aktarıcı olarak kullanılsın</string>
diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml
index 282f849f..24b3c0ee 100644
--- a/app/src/main/res/values-uk/strings.xml
+++ b/app/src/main/res/values-uk/strings.xml
@@ -67,9 +67,6 @@
<string name="use_only_these_specified_nodes">Використовувати *тільки* ці задані вузли</string>
<string name="bridges">Мости</string>
<string name="use_bridges">Використати Мости</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Увімкніть альтернативні входи у мережу Tor</string>
- <string name="ip_address_and_port_of_bridges">IP адреси і порти мостів</string>
- <string name="enter_bridge_addresses">Введіть Адреси Мостів</string>
<string name="relays">Ретранслятори</string>
<string name="relaying">Ретрансляція</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Дозволити вашому пристрою бути невихідним ретранслятором</string>
diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml
index 2832e816..776c07dc 100644
--- a/app/src/main/res/values-vi/strings.xml
+++ b/app/src/main/res/values-vi/strings.xml
@@ -66,8 +66,6 @@
<string name="use_only_these_specified_nodes">*Chỉ* dùng những nút được liệt kê</string>
<string name="bridges">Bridge</string>
<string name="use_bridges">Dùng bridge</string>
- <string name="ip_address_and_port_of_bridges">Địa chỉ IP và cổng của bridge</string>
- <string name="enter_bridge_addresses">Nhập địa chỉ bridge</string>
<string name="relays">Relay</string>
<string name="relaying">Chức năng relay</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Cho phép thiết bị bạn trở thành một nút relay (không phải nút cuối)</string>
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index 18d95a37..c39790ff 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -66,8 +66,6 @@
<string name="use_only_these_specified_nodes">仅使用这些指定节点</string>
<string name="bridges">网桥</string>
<string name="use_bridges">使用网桥</string>
- <string name="ip_address_and_port_of_bridges">网桥的 IP 地址和端口</string>
- <string name="enter_bridge_addresses">输入网桥地址</string>
<string name="relays">中继</string>
<string name="relaying">中继转发</string>
<string name="enable_your_device_to_be_a_non_exit_relay">使您的设备成为非出口中继</string>
@@ -185,7 +183,6 @@
<string name="title_activity_hidden_services">洋葱服务</string>
<string name="hidden_services">洋葱服务</string>
<string name="hidden_service_request">一个应用程序想要打开洋葱服务器%1$s端口到Tor网络。如果你信任这个应用程序,这是安全的。</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">启用进入Tor网络的备用入口</string>
<string name="pref_connection_padding">连接填充</string>
<string name="hosted_services">托管的服务</string>
<string name="onion">.onion 地址</string>
diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml
index 0a67881b..27a23c4c 100644
--- a/app/src/main/res/values-zh-rTW/strings.xml
+++ b/app/src/main/res/values-zh-rTW/strings.xml
@@ -67,9 +67,6 @@
<string name="use_only_these_specified_nodes">「只」使用這些節點</string>
<string name="bridges">網橋(Bridges)</string>
<string name="use_bridges">使用網橋</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">啟動替代的入口來進入 Tor 網路</string>
- <string name="ip_address_and_port_of_bridges">網橋的 IP 位址與連接埠</string>
- <string name="enter_bridge_addresses">輸入網橋位址</string>
<string name="relays">中繼(Relays)</string>
<string name="relaying">中繼設定</string>
<string name="enable_your_device_to_be_a_non_exit_relay">啟用您的裝置成為 Tor 網路的中繼節點(非出口節點)</string>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index c9fc00a6..90dde59a 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -75,9 +75,6 @@
<string name="use_only_these_specified_nodes">Use *only* these specified nodes</string>
<string name="bridges">Bridges</string>
<string name="use_bridges">Use Bridges</string>
- <string name="enable_alternate_entrance_nodes_into_the_tor_network">Enable alternate entrances into the Tor Network</string>
- <string name="ip_address_and_port_of_bridges">IP address and port of bridges</string>
- <string name="enter_bridge_addresses">Enter Bridge Addresses</string>
<string name="relays">Relays</string>
<string name="relaying">Relaying</string>
<string name="enable_your_device_to_be_a_non_exit_relay">Enable your device to be a non-exit relay</string>
diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml
index a8c078bc..506e9d9b 100644
--- a/app/src/main/res/xml/preferences.xml
+++ b/app/src/main/res/xml/preferences.xml
@@ -115,22 +115,6 @@
android:summary="@string/use_only_these_specified_nodes"
android:title="@string/strict_nodes" />
- </PreferenceCategory>
- <PreferenceCategory android:title="@string/bridges">
-
- <CheckBoxPreference
- android:defaultValue="false"
- android:key="pref_bridges_enabled"
- android:summary="@string/enable_alternate_entrance_nodes_into_the_tor_network"
- android:title="@string/use_bridges" />
-
- <EditTextPreference
- android:dialogTitle="@string/enter_bridge_addresses"
- android:inputType="textMultiLine|textNoSuggestions"
- android:key="pref_bridges_list"
- android:summary="@string/ip_address_and_port_of_bridges"
- android:title="@string/bridges" />
-
</PreferenceCategory>
<PreferenceCategory android:title="@string/relays">
1
0