tor-commits
Threads by month
- ----- 2025 -----
- 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
March 2017
- 20 participants
- 1183 discussions
commit 9961ad0b84e261599da595418b2539c887616c73
Author: arrase <arrase(a)gmail.com>
Date: Tue Dec 6 15:03:44 2016 +0100
adds padding to the hs switch
---
app/src/main/res/layout/layout_hs_list_item.xml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/app/src/main/res/layout/layout_hs_list_item.xml b/app/src/main/res/layout/layout_hs_list_item.xml
index 44e6057..e83b874 100644
--- a/app/src/main/res/layout/layout_hs_list_item.xml
+++ b/app/src/main/res/layout/…
[View More]layout_hs_list_item.xml
@@ -51,7 +51,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false"
- android:focusableInTouchMode="false" />
+ android:focusableInTouchMode="false"
+ android:switchPadding="30dp" />
</LinearLayout>
[View Less]
1
0
commit 41ebcc50507b346e37d7aced4d6d88b49fe174be
Author: arrase <arrase(a)gmail.com>
Date: Thu Dec 8 15:22:53 2016 +0100
Deal with Doze in the less painful way
---
app/src/main/AndroidManifest.xml | 1 +
.../org/torproject/android/OrbotMainActivity.java | 5 +-
.../ui/hiddenservices/ClientCookiesActivity.java | 6 +-
.../ui/hiddenservices/HiddenServicesActivity.java | 21 ++++-
.../dialogs/CookieActionsDialog.java | 6 +-
.../ui/…
[View More]hiddenservices/dialogs/HSActionsDialog.java | 6 +-
.../permissions/PermissionManager.java | 103 +++++++++++++++++++++
.../hiddenservices/storage/PermissionManager.java | 50 ----------
app/src/main/res/values/strings.xml | 4 +
9 files changed, 137 insertions(+), 65 deletions(-)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 7dd9c1c..a713cf5 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -23,6 +23,7 @@
<uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<android:uses-permission android:name="android.permission.READ_PHONE_STATE" />
diff --git a/app/src/main/java/org/torproject/android/OrbotMainActivity.java b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
index 3abcdb8..1a468d4 100644
--- a/app/src/main/java/org/torproject/android/OrbotMainActivity.java
+++ b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
@@ -30,6 +30,7 @@ import org.torproject.android.ui.Rotate3dAnimation;
import org.torproject.android.ui.hiddenservices.ClientCookiesActivity;
import org.torproject.android.ui.hiddenservices.HiddenServicesActivity;
import org.torproject.android.ui.hiddenservices.backup.BackupUtils;
+import org.torproject.android.ui.hiddenservices.permissions.PermissionManager;
import org.torproject.android.ui.hiddenservices.providers.HSContentProvider;
import org.torproject.android.vpn.VPNEnableActivity;
@@ -124,8 +125,6 @@ public class OrbotMainActivity extends AppCompatActivity
private final static int REQUEST_SETTINGS = 0x9874;
private final static int REQUEST_VPN_APPS_SELECT = 8889;
- private final static boolean mIsLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
-
// message types for mStatusUpdateHandler
private final static int STATUS_UPDATE = 1;
private static final int MESSAGE_TRAFFIC_COUNT = 2;
@@ -586,7 +585,7 @@ public class OrbotMainActivity extends AppCompatActivity
Prefs.putUseVpn(enable);
if (enable) {
- if (mIsLollipop) //let the user choose the apps
+ if (PermissionManager.isLollipopOrHigher()) //let the user choose the apps
startActivityForResult(new Intent(OrbotMainActivity.this, AppManager.class), REQUEST_VPN_APPS_SELECT);
else
startActivity(new Intent(OrbotMainActivity.this, VPNEnableActivity.class));
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 0b94812..ffbe3d5 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
@@ -28,8 +28,8 @@ import org.torproject.android.ui.hiddenservices.adapters.ClienCookiesAdapter;
import org.torproject.android.ui.hiddenservices.dialogs.AddCookieDialog;
import org.torproject.android.ui.hiddenservices.dialogs.CookieActionsDialog;
import org.torproject.android.ui.hiddenservices.dialogs.SelectCookieBackupDialog;
+import org.torproject.android.ui.hiddenservices.permissions.PermissionManager;
import org.torproject.android.ui.hiddenservices.providers.CookieContentProvider;
-import org.torproject.android.ui.hiddenservices.storage.PermissionManager;
public class ClientCookiesActivity extends AppCompatActivity {
public final int WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTIONBAR = 3;
@@ -111,9 +111,9 @@ public class ClientCookiesActivity extends AppCompatActivity {
int id = item.getItemId();
if (id == R.id.cookie_restore_backup) {
- if (PermissionManager.usesRuntimePermissions()
+ if (PermissionManager.isLollipopOrHigher()
&& !PermissionManager.hasExternalWritePermission(this)) {
- PermissionManager.requestPermissions(this, WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTIONBAR);
+ PermissionManager.requestExternalWritePermissions(this, WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTIONBAR);
return true;
}
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 ae2cd55..f644558 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,8 +25,8 @@ import org.torproject.android.ui.hiddenservices.adapters.OnionListAdapter;
import org.torproject.android.ui.hiddenservices.dialogs.HSActionsDialog;
import org.torproject.android.ui.hiddenservices.dialogs.HSDataDialog;
import org.torproject.android.ui.hiddenservices.dialogs.SelectHSBackupDialog;
+import org.torproject.android.ui.hiddenservices.permissions.PermissionManager;
import org.torproject.android.ui.hiddenservices.providers.HSContentProvider;
-import org.torproject.android.ui.hiddenservices.storage.PermissionManager;
public class HiddenServicesActivity extends AppCompatActivity {
public final int WRITE_EXTERNAL_STORAGE_FROM_ACTIONBAR = 1;
@@ -150,9 +150,9 @@ public class HiddenServicesActivity extends AppCompatActivity {
int id = item.getItemId();
if (id == R.id.menu_restore_backup) {
- if (PermissionManager.usesRuntimePermissions()
+ if (PermissionManager.isLollipopOrHigher()
&& !PermissionManager.hasExternalWritePermission(this)) {
- PermissionManager.requestPermissions(this, WRITE_EXTERNAL_STORAGE_FROM_ACTIONBAR);
+ PermissionManager.requestExternalWritePermissions(this, WRITE_EXTERNAL_STORAGE_FROM_ACTIONBAR);
return true;
}
@@ -194,6 +194,21 @@ public class HiddenServicesActivity extends AppCompatActivity {
mAdapter.changeCursor(mResolver.query(
HSContentProvider.CONTENT_URI, HSContentProvider.PROJECTION, mWhere, null, null
));
+
+ if (PermissionManager.isLollipopOrHigher()) {
+ 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.requestBatteryPermmssions(HiddenServicesActivity.this, getApplicationContext());
+ else // Drop whe not needed
+ PermissionManager.requestDropBatteryPermmssions(HiddenServicesActivity.this, getApplicationContext());
+
+ active.close();
+ }
}
}
}
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 e5683da..7b5a2cf 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
@@ -15,7 +15,7 @@ import android.widget.Toast;
import org.torproject.android.R;
import org.torproject.android.ui.hiddenservices.backup.BackupUtils;
-import org.torproject.android.ui.hiddenservices.storage.PermissionManager;
+import org.torproject.android.ui.hiddenservices.permissions.PermissionManager;
public class CookieActionsDialog extends DialogFragment {
public static final int WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTION_DIALOG = 4;
@@ -36,10 +36,10 @@ public class CookieActionsDialog extends DialogFragment {
public void onClick(View v) {
Context mContext = v.getContext();
- if (PermissionManager.usesRuntimePermissions()
+ if (PermissionManager.isLollipopOrHigher()
&& !PermissionManager.hasExternalWritePermission(mContext)) {
- PermissionManager.requestPermissions(
+ PermissionManager.requestExternalWritePermissions(
getActivity(), WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTION_DIALOG);
return;
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 ff7f7e1..5be7691 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
@@ -17,7 +17,7 @@ import android.widget.Toast;
import org.torproject.android.R;
import org.torproject.android.ui.hiddenservices.backup.BackupUtils;
-import org.torproject.android.ui.hiddenservices.storage.PermissionManager;
+import org.torproject.android.ui.hiddenservices.permissions.PermissionManager;
public class HSActionsDialog extends DialogFragment {
public static final int WRITE_EXTERNAL_STORAGE_FROM_ACTION_DIALOG = 2;
@@ -38,10 +38,10 @@ public class HSActionsDialog extends DialogFragment {
public void onClick(View v) {
Context mContext = v.getContext();
- if (PermissionManager.usesRuntimePermissions()
+ if (PermissionManager.isLollipopOrHigher()
&& !PermissionManager.hasExternalWritePermission(mContext)) {
- PermissionManager.requestPermissions(
+ PermissionManager.requestExternalWritePermissions(
getActivity(), WRITE_EXTERNAL_STORAGE_FROM_ACTION_DIALOG);
return;
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
new file mode 100644
index 0000000..a9df5a9
--- /dev/null
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/permissions/PermissionManager.java
@@ -0,0 +1,103 @@
+package org.torproject.android.ui.hiddenservices.permissions;
+
+
+import android.Manifest;
+import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.Build;
+import android.os.PowerManager;
+import android.provider.Settings;
+import android.support.design.widget.Snackbar;
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.app.FragmentActivity;
+import android.view.View;
+
+import org.torproject.android.R;
+
+public class PermissionManager {
+ public static int VERY_LONG_LENGTH = 6000;
+
+ public static boolean isLollipopOrHigher() {
+ return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP);
+ }
+
+ @SuppressLint("NewApi")
+ public static boolean hasExternalWritePermission(Context context) {
+ return (context.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
+ }
+
+ public static void requestExternalWritePermissions(FragmentActivity activity, int action) {
+ final int mAction = action;
+ final FragmentActivity mActivity = activity;
+
+ if (ActivityCompat.shouldShowRequestPermissionRationale
+ (mActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
+ Snackbar.make(mActivity.findViewById(android.R.id.content),
+ R.string.please_grant_permissions_for_external_storage,
+ Snackbar.LENGTH_INDEFINITE).setAction(R.string.activate,
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ ActivityCompat.requestPermissions(mActivity,
+ new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
+ mAction);
+ }
+ }).show();
+ } else {
+ ActivityCompat.requestPermissions(mActivity,
+ new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
+ mAction);
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.M)
+ public static void requestBatteryPermmssions(FragmentActivity activity, Context context) {
+ final Context mContext = context;
+ final String packageName = mContext.getPackageName();
+ PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+
+ if (pm.isIgnoringBatteryOptimizations(packageName))
+ return;
+
+ Snackbar.make(activity.findViewById(android.R.id.content),
+ R.string.consider_disable_battery_optimizations,
+ VERY_LONG_LENGTH).setAction(R.string.disable,
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent();
+ intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
+ intent.setData(Uri.parse("package:" + packageName));
+ mContext.startActivity(intent);
+ }
+ }).show();
+ }
+
+ @TargetApi(Build.VERSION_CODES.M)
+ public static void requestDropBatteryPermmssions(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))
+ return;
+
+ Snackbar.make(activity.findViewById(android.R.id.content),
+ R.string.consider_enable_battery_optimizations,
+ VERY_LONG_LENGTH).setAction(R.string.enable,
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent();
+ intent.setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
+ mContext.startActivity(intent);
+ }
+ }).show();
+ }
+}
+
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/storage/PermissionManager.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/storage/PermissionManager.java
deleted file mode 100644
index 3a3cf09..0000000
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/storage/PermissionManager.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package org.torproject.android.ui.hiddenservices.storage;
-
-
-import android.Manifest;
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.support.design.widget.Snackbar;
-import android.support.v4.app.ActivityCompat;
-import android.support.v4.app.FragmentActivity;
-import android.view.View;
-
-import org.torproject.android.R;
-
-public class PermissionManager {
-
- public static boolean usesRuntimePermissions() {
- return (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1);
- }
-
- @SuppressLint("NewApi")
- public static boolean hasExternalWritePermission(Context context) {
- return (context.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
- }
-
- public static void requestPermissions(FragmentActivity activity, int action) {
- final int mAction = action;
- final FragmentActivity mActivity = activity;
-
- if (ActivityCompat.shouldShowRequestPermissionRationale
- (mActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
- Snackbar.make(mActivity.findViewById(android.R.id.content),
- R.string.please_grant_permissions_for_external_storage,
- Snackbar.LENGTH_INDEFINITE).setAction("ENABLE",
- new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- ActivityCompat.requestPermissions(mActivity,
- new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
- mAction);
- }
- }).show();
- } else {
- ActivityCompat.requestPermissions(mActivity,
- new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
- mAction);
- }
- }
-}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 6a07c44..41b9e81 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -376,4 +376,8 @@
<string name="confirm_cookie_deletion">Confirm cookie deletion</string>
<string name="hosted_services">Hosted Services</string>
<string name="share_as_qr">Share as QR</string>
+ <string name="disable">Disable</string>
+ <string name="enable">Enable</string>
+ <string name="consider_disable_battery_optimizations">Consider disable battery optimizations</string>
+ <string name="consider_enable_battery_optimizations">Consider enable battery optimizations</string>
</resources>
[View Less]
1
0

[orbot/master] feature added: temporarily disable a hidden service
by n8fr8@torproject.org 02 Mar '17
by n8fr8@torproject.org 02 Mar '17
02 Mar '17
commit 4f7271b76e4e23ebe5476a223e1494d7ec7600a8
Author: arrase <arrase(a)gmail.com>
Date: Tue Dec 6 00:27:25 2016 +0100
feature added: temporarily disable a hidden service
---
.../hiddenservices/adapters/OnionListAdapter.java | 29 ++++++++++++++++++++++
.../ui/hiddenservices/backup/BackupUtils.java | 10 ++++++++
.../ui/hiddenservices/database/HSDatabase.java | 1 +
.../providers/HSContentProvider.java | 4 ++-
app/src/main/res/layout/layout_hs_list_item.…
[View More]xml | 27 ++++++++++++--------
.../org/torproject/android/service/TorService.java | 6 +++--
6 files changed, 64 insertions(+), 13 deletions(-)
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 1edbef2..b9f750a 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
@@ -1,12 +1,17 @@
package org.torproject.android.ui.hiddenservices.adapters;
+import android.content.ContentResolver;
+import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.support.v4.widget.CursorAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.CompoundButton;
+import android.widget.Switch;
import android.widget.TextView;
+import android.widget.Toast;
import org.torproject.android.R;
import org.torproject.android.ui.hiddenservices.providers.HSContentProvider;
@@ -23,12 +28,36 @@ public class OnionListAdapter extends CursorAdapter {
@Override
public void bindView(View view, Context context, Cursor cursor) {
+ final Context mContext = context;
+ int id = cursor.getInt(cursor.getColumnIndex(HSContentProvider.HiddenService._ID));
+ final String where = HSContentProvider.HiddenService._ID + "=" + id;
+
TextView port = (TextView) view.findViewById(R.id.hs_port);
port.setText(cursor.getString(cursor.getColumnIndex(HSContentProvider.HiddenService.PORT)));
TextView name = (TextView) view.findViewById(R.id.hs_name);
name.setText(cursor.getString(cursor.getColumnIndex(HSContentProvider.HiddenService.NAME)));
TextView domain = (TextView) view.findViewById(R.id.hs_onion);
domain.setText(cursor.getString(cursor.getColumnIndex(HSContentProvider.HiddenService.DOMAIN)));
+ Switch enabled = (Switch) view.findViewById(R.id.hs_switch);
+ enabled.setChecked(
+ cursor.getInt(cursor.getColumnIndex(HSContentProvider.HiddenService.ENABLED)) == 1
+ );
+
+ enabled.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ ContentResolver resolver = mContext.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();
+ }
+ });
}
@Override
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 1dccbf8..58911d9 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
@@ -102,6 +102,11 @@ public class BackupUtils {
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;
@@ -193,6 +198,11 @@ public class BackupUtils {
savedValues.getInt(HSContentProvider.HiddenService.CREATED_BY_USER)
);
+ fields.put(
+ HSContentProvider.HiddenService.ENABLED,
+ savedValues.getInt(HSContentProvider.HiddenService.ENABLED)
+ );
+
port = savedValues.getInt(HSContentProvider.HiddenService.PORT);
fields.put(HSContentProvider.HiddenService.PORT, port);
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/database/HSDatabase.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/database/HSDatabase.java
index 93ccd25..779c775 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/database/HSDatabase.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/database/HSDatabase.java
@@ -19,6 +19,7 @@ public class HSDatabase extends SQLiteOpenHelper {
"auth_cookie INTEGER DEFAULT 0, " +
"auth_cookie_value TEXT, " +
"created_by_user INTEGER DEFAULT 0, " +
+ "enabled INTEGER DEFAULT 1, " +
"port INTEGER);";
public HSDatabase(Context context) {
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 a0e85dd..d7b558f 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
@@ -24,7 +24,8 @@ public class HSContentProvider extends ContentProvider {
HiddenService.ONION_PORT,
HiddenService.AUTH_COOKIE,
HiddenService.AUTH_COOKIE_VALUE,
- HiddenService.CREATED_BY_USER
+ HiddenService.CREATED_BY_USER,
+ HiddenService.ENABLED
};
private static final String AUTH = "org.torproject.android.ui.hiddenservices.providers";
public static final Uri CONTENT_URI =
@@ -135,6 +136,7 @@ public class HSContentProvider extends ContentProvider {
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() {
}
diff --git a/app/src/main/res/layout/layout_hs_list_item.xml b/app/src/main/res/layout/layout_hs_list_item.xml
index d55f688..c8878b0 100644
--- a/app/src/main/res/layout/layout_hs_list_item.xml
+++ b/app/src/main/res/layout/layout_hs_list_item.xml
@@ -6,44 +6,51 @@
android:orientation="vertical">
<LinearLayout
- android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:orientation="horizontal"
android:paddingLeft="15dp"
- tools:paddingLeft="15dp">
+ android:paddingRight="15dp"
+ tools:paddingLeft="15dp"
+ tools:paddingRight="15dp">
<TextView
- android:layout_height="match_parent"
android:id="@+id/hs_port"
android:layout_width="wrap_content"
- android:paddingTop="10dp"
+ android:layout_height="match_parent"
android:paddingRight="10dp"
+ android:paddingTop="10dp"
android:textSize="35sp" />
<LinearLayout
- android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_weight="1">
+ android:layout_weight="1"
+ android:orientation="vertical">
<TextView
android:id="@+id/hs_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:textSize="24sp"
+ android:paddingBottom="10dp"
android:paddingLeft="10dp"
- android:paddingBottom="10dp" />
+ android:textSize="24sp" />
<TextView
android:id="@+id/hs_onion"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:textSize="18sp"
+ android:paddingBottom="10dp"
android:paddingLeft="10dp"
- android:paddingBottom="10dp" />
+ android:textSize="18sp" />
</LinearLayout>
+ <Switch
+ android:id="@+id/hs_switch"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
</LinearLayout>
</LinearLayout>
\ No newline at end of file
diff --git a/orbotservice/src/main/java/org/torproject/android/service/TorService.java b/orbotservice/src/main/java/org/torproject/android/service/TorService.java
index ff37d8c..19fb0d1 100644
--- a/orbotservice/src/main/java/org/torproject/android/service/TorService.java
+++ b/orbotservice/src/main/java/org/torproject/android/service/TorService.java
@@ -142,6 +142,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
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() {
}
@@ -154,7 +155,8 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
HiddenService.PORT,
HiddenService.AUTH_COOKIE,
HiddenService.AUTH_COOKIE_VALUE,
- HiddenService.ONION_PORT};
+ HiddenService.ONION_PORT,
+ HiddenService.ENABLED};
public void debug(String msg)
{
@@ -1792,7 +1794,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
/* ---- Hidden Services ---- */
ContentResolver mCR = getApplicationContext().getContentResolver();
- Cursor hidden_services = mCR.query(CONTENT_URI, mProjection, null, null, null);
+ Cursor hidden_services = mCR.query(CONTENT_URI, mProjection, HiddenService.ENABLED + "=1", null, null);
if(hidden_services != null) {
try {
while (hidden_services.moveToNext()) {
[View Less]
1
0
commit 500075454a94f92dfb7e981ccf7ea75f2078cf0c
Author: arrase <arrase(a)gmail.com>
Date: Thu Dec 8 15:45:16 2016 +0100
fix typo
---
.../ui/hiddenservices/ClientCookiesActivity.java | 6 +-
.../adapters/ClienCookiesAdapter.java | 64 ----------------------
.../adapters/ClientCookiesAdapter.java | 64 ++++++++++++++++++++++
3 files changed, 67 insertions(+), 67 deletions(-)
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/…
[View More]ClientCookiesActivity.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/ClientCookiesActivity.java
index ffbe3d5..a766a5c 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
@@ -24,7 +24,7 @@ import com.google.zxing.integration.android.IntentResult;
import org.json.JSONException;
import org.json.JSONObject;
import org.torproject.android.R;
-import org.torproject.android.ui.hiddenservices.adapters.ClienCookiesAdapter;
+import org.torproject.android.ui.hiddenservices.adapters.ClientCookiesAdapter;
import org.torproject.android.ui.hiddenservices.dialogs.AddCookieDialog;
import org.torproject.android.ui.hiddenservices.dialogs.CookieActionsDialog;
import org.torproject.android.ui.hiddenservices.dialogs.SelectCookieBackupDialog;
@@ -35,7 +35,7 @@ public class ClientCookiesActivity extends AppCompatActivity {
public final int WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTIONBAR = 3;
private ContentResolver mResolver;
- private ClienCookiesAdapter mAdapter;
+ private ClientCookiesAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -57,7 +57,7 @@ public class ClientCookiesActivity extends AppCompatActivity {
}
});
- mAdapter = new ClienCookiesAdapter(
+ mAdapter = new ClientCookiesAdapter(
this,
mResolver.query(CookieContentProvider.CONTENT_URI, CookieContentProvider.PROJECTION, null, null, null)
, 0);
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/adapters/ClienCookiesAdapter.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/adapters/ClienCookiesAdapter.java
deleted file mode 100644
index a9d782b..0000000
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/adapters/ClienCookiesAdapter.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.torproject.android.ui.hiddenservices.adapters;
-
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.support.v4.widget.CursorAdapter;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.CompoundButton;
-import android.widget.Switch;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import org.torproject.android.R;
-import org.torproject.android.ui.hiddenservices.providers.CookieContentProvider;
-
-public class ClienCookiesAdapter extends CursorAdapter {
- private LayoutInflater cursorInflater;
-
- public ClienCookiesAdapter(Context context, Cursor c, int flags) {
- super(context, c, flags);
-
- cursorInflater = (LayoutInflater) context.getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
- }
-
- @Override
- public void bindView(View view, Context context, Cursor cursor) {
- final Context mContext = context;
- int id = cursor.getInt(cursor.getColumnIndex(CookieContentProvider.ClientCookie._ID));
- final String where = CookieContentProvider.ClientCookie._ID + "=" + id;
-
- TextView domain = (TextView) view.findViewById(R.id.cookie_onion);
- domain.setText(cursor.getString(cursor.getColumnIndex(CookieContentProvider.ClientCookie.DOMAIN)));
-
- Switch enabled = (Switch) view.findViewById(R.id.cookie_switch);
- enabled.setChecked(
- cursor.getInt(cursor.getColumnIndex(CookieContentProvider.ClientCookie.ENABLED)) == 1
- );
-
- enabled.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- ContentResolver resolver = mContext.getContentResolver();
- ContentValues fields = new ContentValues();
- fields.put(CookieContentProvider.ClientCookie.ENABLED, isChecked);
- resolver.update(
- CookieContentProvider.CONTENT_URI, fields, where, null
- );
-
- Toast.makeText(
- mContext, R.string.please_restart_Orbot_to_enable_the_changes, Toast.LENGTH_LONG
- ).show();
- }
- });
- }
-
- @Override
- public View newView(Context context, Cursor cursor, ViewGroup parent) {
- return cursorInflater.inflate(R.layout.layout_client_cookie_list_item, parent, false);
- }
-}
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/adapters/ClientCookiesAdapter.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/adapters/ClientCookiesAdapter.java
new file mode 100644
index 0000000..bbc317a
--- /dev/null
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/adapters/ClientCookiesAdapter.java
@@ -0,0 +1,64 @@
+package org.torproject.android.ui.hiddenservices.adapters;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.support.v4.widget.CursorAdapter;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CompoundButton;
+import android.widget.Switch;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import org.torproject.android.R;
+import org.torproject.android.ui.hiddenservices.providers.CookieContentProvider;
+
+public class ClientCookiesAdapter extends CursorAdapter {
+ private LayoutInflater cursorInflater;
+
+ public ClientCookiesAdapter(Context context, Cursor c, int flags) {
+ super(context, c, flags);
+
+ cursorInflater = (LayoutInflater) context.getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+ }
+
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ final Context mContext = context;
+ int id = cursor.getInt(cursor.getColumnIndex(CookieContentProvider.ClientCookie._ID));
+ final String where = CookieContentProvider.ClientCookie._ID + "=" + id;
+
+ TextView domain = (TextView) view.findViewById(R.id.cookie_onion);
+ domain.setText(cursor.getString(cursor.getColumnIndex(CookieContentProvider.ClientCookie.DOMAIN)));
+
+ Switch enabled = (Switch) view.findViewById(R.id.cookie_switch);
+ enabled.setChecked(
+ cursor.getInt(cursor.getColumnIndex(CookieContentProvider.ClientCookie.ENABLED)) == 1
+ );
+
+ enabled.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ ContentResolver resolver = mContext.getContentResolver();
+ ContentValues fields = new ContentValues();
+ fields.put(CookieContentProvider.ClientCookie.ENABLED, isChecked);
+ resolver.update(
+ CookieContentProvider.CONTENT_URI, fields, where, null
+ );
+
+ Toast.makeText(
+ mContext, R.string.please_restart_Orbot_to_enable_the_changes, Toast.LENGTH_LONG
+ ).show();
+ }
+ });
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ return cursorInflater.inflate(R.layout.layout_client_cookie_list_item, parent, false);
+ }
+}
[View Less]
1
0

[orbot/master] New feature added: HidServAuth manager and QR share
by n8fr8@torproject.org 02 Mar '17
by n8fr8@torproject.org 02 Mar '17
02 Mar '17
commit 2aa2b4c3703f707d26c44b0b05663cb76cb084a3
Author: arrase <arrase(a)gmail.com>
Date: Tue Dec 6 23:10:36 2016 +0100
New feature added: HidServAuth manager and QR share
---
app/src/main/AndroidManifest.xml | 191 +++++++++++---------
.../org/torproject/android/OrbotMainActivity.java | 3 +
.../ui/hiddenservices/ClientCookiesActivity.java | 199 +++++++++++++++++++++
.../ui/hiddenservices/HiddenServicesActivity.java | 11 +-
.../adapters/…
[View More]ClienCookiesAdapter.java | 64 +++++++
.../ui/hiddenservices/backup/BackupUtils.java | 93 +++++++++-
.../ui/hiddenservices/database/HSDatabase.java | 9 +
.../ui/hiddenservices/dialogs/AddCookieDialog.java | 84 +++++++++
.../dialogs/CookieActionsDialog.java | 95 ++++++++++
.../hiddenservices/dialogs/CookieDeleteDialog.java | 50 ++++++
.../ui/hiddenservices/dialogs/HSCookieDialog.java | 25 +++
.../hiddenservices/dialogs/SelectBackupDialog.java | 84 ---------
.../dialogs/SelectCookieBackupDialog.java | 84 +++++++++
.../dialogs/SelectHSBackupDialog.java | 84 +++++++++
.../providers/CookieContentProvider.java | 134 ++++++++++++++
.../ui/hiddenservices/storage/ExternalStorage.java | 4 +-
.../res/layout/layout_activity_client_cookies.xml | 35 ++++
.../res/layout/layout_add_client_cookie_dialog.xml | 64 +++++++
.../res/layout/layout_client_cookie_list_item.xml | 24 +++
.../res/layout/layout_content_client_cookies.xml | 21 +++
app/src/main/res/layout/layout_cookie_actions.xml | 24 +++
app/src/main/res/layout/layout_hs_cookie.xml | 6 +
app/src/main/res/menu/cookie_menu.xml | 11 ++
app/src/main/res/menu/orbot_main.xml | 16 +-
app/src/main/res/values-v21/styles.xml | 1 +
app/src/main/res/values/strings.xml | 105 ++++++-----
.../org/torproject/android/service/TorService.java | 45 ++++-
27 files changed, 1320 insertions(+), 246 deletions(-)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 826ce67..7dd9c1c 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,28 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="org.torproject.android"
- android:versionName="15.2.0-RC-8-multi"
- android:versionCode="15208000"
- android:installLocation="auto"
- >
- <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="23"/>
- <!--
+ package="org.torproject.android"
+ android:installLocation="auto"
+ android:versionCode="15208000"
+ android:versionName="15.2.0-RC-8-multi">
+
+ <uses-sdk
+ android:minSdkVersion="16"
+ android:targetSdkVersion="23" />
+ <!--
<permission android:name="org.torproject.android.MANAGE_TOR"
android:label="@string/permission_manage_tor_label"
android:description="@string/permission_manage_tor_description"
android:protectionLevel="signature"/>
<uses-permission android:name="org.torproject.android.MANAGE_TOR"/>
- -->
-
- <uses-permission android:name="android.permission.INTERNET"/>
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
- <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
- <uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
+ -->
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+ <uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <android:uses-permission android:name="android.permission.READ_PHONE_STATE" />
+
<application
android:name=".OrbotApp"
android:allowBackup="false"
@@ -38,118 +41,114 @@
android:name=".OrbotMainActivity"
android:configChanges="orientation|screenSize"
android:excludeFromRecents="true"
- android:launchMode="singleTop"
- >
+ android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
+
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
+
<data android:scheme="bridge" />
</intent-filter>
-
- <intent-filter>
+ <intent-filter>
<category android:name="android.intent.category.DEFAULT" />
+
<action android:name="org.torproject.android.REQUEST_HS_PORT" />
</intent-filter>
- <intent-filter>
+ <intent-filter>
<category android:name="android.intent.category.DEFAULT" />
+
<action android:name="org.torproject.android.START_TOR" />
</intent-filter>
-
</activity>
- <!--
- This is for ensuring the background service still runs when/if the app is swiped away
- -->
- <activity
- android:name=".service.util.DummyActivity"
- android:theme="@android:style/Theme.Translucent"
- android:enabled="true"
- android:allowTaskReparenting="true"
- android:noHistory="true"
- android:excludeFromRecents="true"
- android:alwaysRetainTaskState="false"
- android:stateNotNeeded="true"
- android:clearTaskOnLaunch="true"
- android:finishOnTaskLaunch="true"
-
- />
-
- <activity
- android:name=".vpn.VPNEnableActivity" android:label="@string/app_name" android:exported="false"
- />
-
-
- <activity android:name="org.torproject.android.ui.PromoAppsActivity" android:exported="false"/>
-
-
- <activity android:name=".settings.SettingsPreferences" android:label="@string/app_name"/>
- <activity android:name=".ui.AppManager" android:label="@string/app_name"
- android:theme="@style/Theme.AppCompat"
- />
+ <!-- This is for ensuring the background service still runs when/if the app is swiped away -->
+ <activity
+ android:name=".service.util.DummyActivity"
+ android:allowTaskReparenting="true"
+ android:alwaysRetainTaskState="false"
+ android:clearTaskOnLaunch="true"
+ android:enabled="true"
+ android:excludeFromRecents="true"
+ android:finishOnTaskLaunch="true"
+ android:noHistory="true"
+ android:stateNotNeeded="true"
+ android:theme="@android:style/Theme.Translucent" />
+ <activity
+ android:name=".vpn.VPNEnableActivity"
+ android:exported="false"
+ android:label="@string/app_name" />
+ <activity
+ android:name=".ui.PromoAppsActivity"
+ android:exported="false" />
+ <activity
+ android:name=".settings.SettingsPreferences"
+ android:label="@string/app_name" />
+ <activity
+ android:name=".ui.AppManager"
+ android:label="@string/app_name"
+ android:theme="@style/Theme.AppCompat" />
<service
android:name=".service.TorService"
android:enabled="true"
android:permission="android.permission.BIND_VPN_SERVICE"
- android:stopWithTask="false" >
+ android:stopWithTask="false"></service>
+ <service
+ android:name=".service.vpn.TorVpnService"
+ android:enabled="true"
+ android:permission="android.permission.BIND_VPN_SERVICE">
+ <intent-filter>
+ <action android:name="android.net.VpnService" />
+ </intent-filter>
</service>
-
- <service
- android:name=".service.vpn.TorVpnService"
- android:enabled="true"
- android:permission="android.permission.BIND_VPN_SERVICE" >
- <intent-filter>
- <action android:name="android.net.VpnService"/>
- </intent-filter>
- </service>
-
<receiver
android:name=".service.StartTorReceiver"
android:exported="true">
- <intent-filter>
- <action android:name="org.torproject.android.intent.action.START" />
- </intent-filter>
+ <intent-filter>
+ <action android:name="org.torproject.android.intent.action.START" />
+ </intent-filter>
</receiver>
+ <receiver
+ android:name=".OnBootReceiver"
+ android:enabled="true"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.BOOT_COMPLETED" />
+
+ <category android:name="android.intent.category.HOME" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.QUICKBOOT_POWERON" />
- <receiver android:name=".OnBootReceiver"
- android:enabled="true" android:exported="true"
-
- >
- <intent-filter>
- <action android:name="android.intent.action.BOOT_COMPLETED" />
- <category android:name="android.intent.category.HOME" />
- </intent-filter>
- <intent-filter>
- <action android:name="android.intent.action.QUICKBOOT_POWERON" />
- <category android:name="android.intent.category.HOME" />
- </intent-filter>
- <intent-filter>
- <action android:name="android.intent.action.MEDIA_MOUNTED"/>
- <category android:name="android.intent.category.HOME" />
- </intent-filter>
- </receiver>
+ <category android:name="android.intent.category.HOME" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.MEDIA_MOUNTED" />
+
+ <category android:name="android.intent.category.HOME" />
+ </intent-filter>
+ </receiver>
<activity
android:name=".ui.hiddenservices.HiddenServicesActivity"
android:label="@string/title_activity_hidden_services"
- android:theme="@style/DefaultTheme" >
+ android:theme="@style/DefaultTheme">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value="org.torproject.android.OrbotMainActivity" />
+ android:value=".OrbotMainActivity" />
</activity>
<provider
android:name=".ui.hiddenservices.providers.HSContentProvider"
- android:exported="false"
- android:authorities="org.torproject.android.ui.hiddenservices.providers" />
-
+ android:authorities="org.torproject.android.ui.hiddenservices.providers"
+ android:exported="false" />
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="org.torproject.android.ui.hiddenservices.storage"
@@ -157,8 +156,22 @@
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
- android:resource="@xml/hidden_services_paths"/>
+ android:resource="@xml/hidden_services_paths" />
</provider>
-</application>
-</manifest>
+ <activity
+ android:name=".ui.hiddenservices.ClientCookiesActivity"
+ android:label="@string/client_cookies"
+ android:theme="@style/DefaultTheme">
+ <meta-data
+ android:name="android.support.PARENT_ACTIVITY"
+ android:value=".OrbotMainActivity" />
+ </activity>
+
+ <provider
+ android:name=".ui.hiddenservices.providers.CookieContentProvider"
+ android:authorities="org.torproject.android.ui.hiddenservices.providers.cookie"
+ android:exported="false" />
+ </application>
+
+</manifest>
\ No newline at end of file
diff --git a/app/src/main/java/org/torproject/android/OrbotMainActivity.java b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
index caed0c3..3abcdb8 100644
--- a/app/src/main/java/org/torproject/android/OrbotMainActivity.java
+++ b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
@@ -27,6 +27,7 @@ import org.torproject.android.ui.AppManager;
import org.torproject.android.ui.ImageProgressView;
import org.torproject.android.ui.PromoAppsActivity;
import org.torproject.android.ui.Rotate3dAnimation;
+import org.torproject.android.ui.hiddenservices.ClientCookiesActivity;
import org.torproject.android.ui.hiddenservices.HiddenServicesActivity;
import org.torproject.android.ui.hiddenservices.backup.BackupUtils;
import org.torproject.android.ui.hiddenservices.providers.HSContentProvider;
@@ -513,6 +514,8 @@ public class OrbotMainActivity extends AppCompatActivity
} else if (item.getItemId() == R.id.menu_hidden_services) {
startActivity(new Intent(this, HiddenServicesActivity.class));
+ } else if (item.getItemId() == R.id.menu_client_cookies) {
+ startActivity(new Intent(this, ClientCookiesActivity.class));
}
return super.onOptionsItemSelected(item);
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
new file mode 100644
index 0000000..0b94812
--- /dev/null
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/ClientCookiesActivity.java
@@ -0,0 +1,199 @@
+package org.torproject.android.ui.hiddenservices;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.design.widget.FloatingActionButton;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ListView;
+import android.widget.Toast;
+
+import com.google.zxing.integration.android.IntentIntegrator;
+import com.google.zxing.integration.android.IntentResult;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.torproject.android.R;
+import org.torproject.android.ui.hiddenservices.adapters.ClienCookiesAdapter;
+import org.torproject.android.ui.hiddenservices.dialogs.AddCookieDialog;
+import org.torproject.android.ui.hiddenservices.dialogs.CookieActionsDialog;
+import org.torproject.android.ui.hiddenservices.dialogs.SelectCookieBackupDialog;
+import org.torproject.android.ui.hiddenservices.providers.CookieContentProvider;
+import org.torproject.android.ui.hiddenservices.storage.PermissionManager;
+
+public class ClientCookiesActivity extends AppCompatActivity {
+ public final int WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTIONBAR = 3;
+
+ private ContentResolver mResolver;
+ private ClienCookiesAdapter mAdapter;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.layout_activity_client_cookies);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+ mResolver = getContentResolver();
+
+ FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
+ fab.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ AddCookieDialog dialog = new AddCookieDialog();
+ dialog.show(getSupportFragmentManager(), "AddCookieDialog");
+ }
+ });
+
+ mAdapter = new ClienCookiesAdapter(
+ this,
+ mResolver.query(CookieContentProvider.CONTENT_URI, CookieContentProvider.PROJECTION, null, null, null)
+ , 0);
+
+ mResolver.registerContentObserver(
+ CookieContentProvider.CONTENT_URI, true, new HSObserver(new Handler())
+ );
+
+ ListView cookies = (ListView) findViewById(R.id.clien_cookies_list);
+ cookies.setAdapter(mAdapter);
+
+ cookies.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ Cursor item = (Cursor) parent.getItemAtPosition(position);
+
+ Bundle arguments = new Bundle();
+ arguments.putInt(
+ "_id", item.getInt(item.getColumnIndex(CookieContentProvider.ClientCookie._ID))
+ );
+
+ arguments.putString(
+ "domain", item.getString(item.getColumnIndex(CookieContentProvider.ClientCookie.DOMAIN))
+ );
+
+ arguments.putString(
+ "auth_cookie_value", item.getString(item.getColumnIndex(CookieContentProvider.ClientCookie.AUTH_COOKIE_VALUE))
+ );
+
+ arguments.putInt(
+ "enabled", item.getInt(item.getColumnIndex(CookieContentProvider.ClientCookie.ENABLED))
+ );
+
+ CookieActionsDialog dialog = new CookieActionsDialog();
+ dialog.setArguments(arguments);
+ dialog.show(getSupportFragmentManager(), "CookieActionsDialog");
+ }
+ });
+
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.cookie_menu, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ int id = item.getItemId();
+
+ if (id == R.id.cookie_restore_backup) {
+ if (PermissionManager.usesRuntimePermissions()
+ && !PermissionManager.hasExternalWritePermission(this)) {
+ PermissionManager.requestPermissions(this, WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTIONBAR);
+ return true;
+ }
+
+ SelectCookieBackupDialog dialog = new SelectCookieBackupDialog();
+ dialog.show(getSupportFragmentManager(), "SelectCookieBackupDialog");
+
+ } else if (id == R.id.cookie_from_qr) {
+ IntentIntegrator integrator = new IntentIntegrator(ClientCookiesActivity.this);
+ integrator.initiateScan();
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode,
+ String permissions[], int[] grantResults) {
+ if (grantResults.length < 1
+ || grantResults[0] != PackageManager.PERMISSION_GRANTED) {
+ return;
+ }
+
+ switch (requestCode) {
+ case WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTIONBAR: {
+ SelectCookieBackupDialog dialog = new SelectCookieBackupDialog();
+ dialog.show(getSupportFragmentManager(), "SelectCookieBackupDialog");
+ break;
+ }
+ case CookieActionsDialog.WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTION_DIALOG: {
+ Toast.makeText(this, R.string.click_again_for_backup, Toast.LENGTH_LONG).show();
+ break;
+ }
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int request, int response, Intent data) {
+ super.onActivityResult(request, response, data);
+
+ IntentResult scanResult = IntentIntegrator.parseActivityResult(request, response, data);
+
+ if (scanResult == null) return;
+
+ String results = scanResult.getContents();
+
+ if (results == null || results.length() < 1) return;
+
+ try {
+ JSONObject savedValues = new JSONObject(results);
+ ContentValues fields = new ContentValues();
+
+ fields.put(
+ CookieContentProvider.ClientCookie.DOMAIN,
+ savedValues.getString(CookieContentProvider.ClientCookie.DOMAIN)
+ );
+
+ fields.put(
+ CookieContentProvider.ClientCookie.AUTH_COOKIE_VALUE,
+ savedValues.getString(CookieContentProvider.ClientCookie.AUTH_COOKIE_VALUE)
+ );
+
+ mResolver.insert(CookieContentProvider.CONTENT_URI, fields);
+
+ } catch (JSONException e) {
+ e.printStackTrace();
+ Toast.makeText(this, R.string.error, Toast.LENGTH_LONG).show();
+ }
+ }
+
+ class HSObserver extends ContentObserver {
+ HSObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ mAdapter.changeCursor(mResolver.query(
+ CookieContentProvider.CONTENT_URI, CookieContentProvider.PROJECTION, null, null, null
+ ));
+ }
+ }
+
+}
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 c4f55a1..ae2cd55 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
@@ -24,7 +24,7 @@ import org.torproject.android.R;
import org.torproject.android.ui.hiddenservices.adapters.OnionListAdapter;
import org.torproject.android.ui.hiddenservices.dialogs.HSActionsDialog;
import org.torproject.android.ui.hiddenservices.dialogs.HSDataDialog;
-import org.torproject.android.ui.hiddenservices.dialogs.SelectBackupDialog;
+import org.torproject.android.ui.hiddenservices.dialogs.SelectHSBackupDialog;
import org.torproject.android.ui.hiddenservices.providers.HSContentProvider;
import org.torproject.android.ui.hiddenservices.storage.PermissionManager;
@@ -156,9 +156,8 @@ public class HiddenServicesActivity extends AppCompatActivity {
return true;
}
- SelectBackupDialog dialog = new SelectBackupDialog();
- dialog.show(getSupportFragmentManager(), "SelectBackupDialog");
- return true;
+ SelectHSBackupDialog dialog = new SelectHSBackupDialog();
+ dialog.show(getSupportFragmentManager(), "SelectHSBackupDialog");
}
return super.onOptionsItemSelected(item);
@@ -174,8 +173,8 @@ public class HiddenServicesActivity extends AppCompatActivity {
switch (requestCode) {
case WRITE_EXTERNAL_STORAGE_FROM_ACTIONBAR: {
- SelectBackupDialog dialog = new SelectBackupDialog();
- dialog.show(getSupportFragmentManager(), "SelectBackupDialog");
+ SelectHSBackupDialog dialog = new SelectHSBackupDialog();
+ dialog.show(getSupportFragmentManager(), "SelectHSBackupDialog");
break;
}
case HSActionsDialog.WRITE_EXTERNAL_STORAGE_FROM_ACTION_DIALOG: {
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/adapters/ClienCookiesAdapter.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/adapters/ClienCookiesAdapter.java
new file mode 100644
index 0000000..a9d782b
--- /dev/null
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/adapters/ClienCookiesAdapter.java
@@ -0,0 +1,64 @@
+package org.torproject.android.ui.hiddenservices.adapters;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.support.v4.widget.CursorAdapter;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CompoundButton;
+import android.widget.Switch;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import org.torproject.android.R;
+import org.torproject.android.ui.hiddenservices.providers.CookieContentProvider;
+
+public class ClienCookiesAdapter extends CursorAdapter {
+ private LayoutInflater cursorInflater;
+
+ public ClienCookiesAdapter(Context context, Cursor c, int flags) {
+ super(context, c, flags);
+
+ cursorInflater = (LayoutInflater) context.getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+ }
+
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ final Context mContext = context;
+ int id = cursor.getInt(cursor.getColumnIndex(CookieContentProvider.ClientCookie._ID));
+ final String where = CookieContentProvider.ClientCookie._ID + "=" + id;
+
+ TextView domain = (TextView) view.findViewById(R.id.cookie_onion);
+ domain.setText(cursor.getString(cursor.getColumnIndex(CookieContentProvider.ClientCookie.DOMAIN)));
+
+ Switch enabled = (Switch) view.findViewById(R.id.cookie_switch);
+ enabled.setChecked(
+ cursor.getInt(cursor.getColumnIndex(CookieContentProvider.ClientCookie.ENABLED)) == 1
+ );
+
+ enabled.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ ContentResolver resolver = mContext.getContentResolver();
+ ContentValues fields = new ContentValues();
+ fields.put(CookieContentProvider.ClientCookie.ENABLED, isChecked);
+ resolver.update(
+ CookieContentProvider.CONTENT_URI, fields, where, null
+ );
+
+ Toast.makeText(
+ mContext, R.string.please_restart_Orbot_to_enable_the_changes, Toast.LENGTH_LONG
+ ).show();
+ }
+ });
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ return cursorInflater.inflate(R.layout.layout_client_cookie_list_item, parent, false);
+ }
+}
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 58911d9..a4790dd 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
@@ -12,6 +12,7 @@ import org.json.JSONException;
import org.json.JSONObject;
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.hiddenservices.storage.ExternalStorage;
@@ -28,21 +29,19 @@ import java.nio.charset.Charset;
public class BackupUtils {
private final String configFileName = "config.json";
- private File mHSBasePath;
private Context mContext;
private ContentResolver mResolver;
public BackupUtils(Context context) {
mContext = context;
- mHSBasePath = new File(
- mContext.getFilesDir().getAbsolutePath(),
- TorServiceConstants.HIDDEN_SERVICES_DIR
- );
-
mResolver = mContext.getContentResolver();
}
public String createZipBackup(Integer port) {
+ File mHSBasePath = new File(
+ mContext.getFilesDir().getAbsolutePath(),
+ TorServiceConstants.HIDDEN_SERVICES_DIR
+ );
String configFilePath = mHSBasePath + "/hs" + port + "/" + configFileName;
String hostnameFilePath = mHSBasePath + "/hs" + port + "/hostname";
@@ -115,6 +114,8 @@ public class BackupUtils {
return null;
}
+ portData.close();
+
try {
FileWriter file = new FileWriter(configFilePath);
file.write(config.toString());
@@ -124,8 +125,6 @@ public class BackupUtils {
return null;
}
- portData.close();
-
String zip_path = storage_path.getAbsolutePath() + "/hs" + port + ".zip";
String files[] = {hostnameFilePath, keyFilePath, configFilePath};
@@ -139,6 +138,11 @@ public class BackupUtils {
public void restoreZipBackup(File backup) {
+ File mHSBasePath = new File(
+ mContext.getFilesDir().getAbsolutePath(),
+ TorServiceConstants.HIDDEN_SERVICES_DIR
+ );
+
int port;
Cursor service;
String backupName = backup.getName();
@@ -154,7 +158,7 @@ public class BackupUtils {
zip.unzip(hsPath.getAbsolutePath());
File config = new File(configFilePath);
- FileInputStream stream = null;
+ FileInputStream stream;
try {
stream = new FileInputStream(config);
@@ -236,6 +240,10 @@ public class BackupUtils {
}
public void restoreKeyBackup(int hsPort, Uri hsKeyPath) {
+ File mHSBasePath = new File(
+ mContext.getFilesDir().getAbsolutePath(),
+ TorServiceConstants.HIDDEN_SERVICES_DIR
+ );
File serviceDir = new File(mHSBasePath, "hs" + hsPort);
@@ -258,4 +266,71 @@ public class BackupUtils {
e.printStackTrace();
}
}
+
+ public void restoreCookieBackup(File p) {
+ File config = new File(p.getAbsolutePath());
+ FileInputStream stream;
+ String jString = null;
+
+ try {
+ stream = new FileInputStream(config);
+ FileChannel fc = stream.getChannel();
+ MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
+ jString = Charset.defaultCharset().decode(bb).toString();
+ stream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ if (jString == null)
+ Toast.makeText(mContext, R.string.error, Toast.LENGTH_LONG).show();
+
+ try {
+ JSONObject savedValues = new JSONObject(jString);
+ ContentValues fields = new ContentValues();
+
+ fields.put(
+ CookieContentProvider.ClientCookie.DOMAIN,
+ savedValues.getString(CookieContentProvider.ClientCookie.DOMAIN)
+ );
+
+ fields.put(
+ CookieContentProvider.ClientCookie.AUTH_COOKIE_VALUE,
+ savedValues.getString(CookieContentProvider.ClientCookie.AUTH_COOKIE_VALUE)
+ );
+
+ fields.put(
+ CookieContentProvider.ClientCookie.ENABLED,
+ savedValues.getInt(CookieContentProvider.ClientCookie.ENABLED)
+ );
+
+ mResolver.insert(CookieContentProvider.CONTENT_URI, fields);
+
+ } catch (JSONException e) {
+ e.printStackTrace();
+ Toast.makeText(mContext, R.string.error, Toast.LENGTH_LONG).show();
+ }
+
+ Toast.makeText(mContext, R.string.backup_restored, Toast.LENGTH_LONG).show();
+ }
+
+ public String createCookieBackup(String domain, String cookie, Integer enabled) {
+ File storage_path = ExternalStorage.getOrCreateBackupDir();
+ String backupFile = storage_path.getAbsolutePath() + '/' + domain.replace(".onion", ".json");
+
+ JSONObject backup = new JSONObject();
+ try {
+ backup.put(CookieContentProvider.ClientCookie.DOMAIN, domain);
+ backup.put(CookieContentProvider.ClientCookie.AUTH_COOKIE_VALUE, cookie);
+ backup.put(CookieContentProvider.ClientCookie.ENABLED, enabled);
+ FileWriter file = new FileWriter(backupFile);
+ file.write(backup.toString());
+ file.close();
+ } catch (JSONException | IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+
+ return backupFile;
+ }
}
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/database/HSDatabase.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/database/HSDatabase.java
index 779c775..18bc7aa 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/database/HSDatabase.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/database/HSDatabase.java
@@ -8,6 +8,7 @@ import android.database.sqlite.SQLiteOpenHelper;
public class HSDatabase extends SQLiteOpenHelper {
public static final String HS_DATA_TABLE_NAME = "hs_data";
+ public static final String HS_CLIENT_COOKIE_TABLE_NAME = "hs_client_cookie";
private static final int DATABASE_VERSION = 2;
private static final String DATABASE_NAME = "hidden_services";
private static final String HS_DATA_TABLE_CREATE =
@@ -22,6 +23,13 @@ public class HSDatabase extends SQLiteOpenHelper {
"enabled INTEGER DEFAULT 1, " +
"port INTEGER);";
+ private static final String HS_CLIENT_COOKIE_TABLE_CREATE =
+ "CREATE TABLE " + HS_CLIENT_COOKIE_TABLE_NAME + " (" +
+ "_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
+ "domain TEXT, " +
+ "auth_cookie_value TEXT, " +
+ "enabled INTEGER DEFAULT 1);";
+
public HSDatabase(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@@ -29,6 +37,7 @@ public class HSDatabase extends SQLiteOpenHelper {
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(HS_DATA_TABLE_CREATE);
+ db.execSQL(HS_CLIENT_COOKIE_TABLE_CREATE);
}
@Override
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/AddCookieDialog.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/AddCookieDialog.java
new file mode 100644
index 0000000..7566364
--- /dev/null
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/AddCookieDialog.java
@@ -0,0 +1,84 @@
+package org.torproject.android.ui.hiddenservices.dialogs;
+
+
+import android.app.Dialog;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.app.DialogFragment;
+import android.support.v7.app.AlertDialog;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import org.torproject.android.R;
+import org.torproject.android.ui.hiddenservices.providers.CookieContentProvider;
+
+public class AddCookieDialog extends DialogFragment {
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+
+ final View dialog_view = getActivity().getLayoutInflater().inflate(R.layout.layout_add_client_cookie_dialog, null);
+
+ final AlertDialog addCookieDialog = new AlertDialog.Builder(getActivity())
+ .setView(dialog_view)
+ .setTitle(R.string.client_cookies)
+ .create();
+
+ Button save = (Button) dialog_view.findViewById(R.id.cookie_dialog_save);
+ save.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ String onion = ((EditText) dialog_view.findViewById(R.id.cookie_onion)).getText().toString();
+ String cookie = ((EditText) dialog_view.findViewById(R.id.cookie_value)).getText().toString();
+
+ if (checkInput(onion, cookie)) {
+ saveData(onion, cookie);
+ Toast.makeText(
+ v.getContext(), R.string.please_restart_Orbot_to_enable_the_changes, Toast.LENGTH_LONG
+ ).show();
+ addCookieDialog.dismiss();
+ }
+ }
+ });
+
+ Button cancel = (Button) dialog_view.findViewById(R.id.cookie_dialog_cancel);
+ cancel.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ addCookieDialog.cancel();
+ }
+ });
+
+ return addCookieDialog;
+ }
+
+ private boolean checkInput(String onion, String cookie) {
+
+ boolean is_set = ((onion != null && onion.length() > 0) && (cookie != null && cookie.length() > 0));
+ if (!is_set) {
+ Toast.makeText(getContext(), R.string.fields_can_t_be_empty, Toast.LENGTH_SHORT).show();
+ return false;
+ }
+
+ if (!onion.matches("([a-z0-9]{16})\\.onion")) {
+ Toast.makeText(getContext(), R.string.invalid_onion_address, Toast.LENGTH_SHORT).show();
+ return false;
+ }
+
+ return true;
+ }
+
+ private void saveData(String domain, String cookie) {
+
+ ContentValues fields = new ContentValues();
+ fields.put(CookieContentProvider.ClientCookie.DOMAIN, domain);
+ fields.put(CookieContentProvider.ClientCookie.AUTH_COOKIE_VALUE, cookie);
+
+ ContentResolver cr = getContext().getContentResolver();
+
+ cr.insert(CookieContentProvider.CONTENT_URI, fields);
+ }
+}
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
new file mode 100644
index 0000000..e5683da
--- /dev/null
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/CookieActionsDialog.java
@@ -0,0 +1,95 @@
+package org.torproject.android.ui.hiddenservices.dialogs;
+
+
+import android.app.Dialog;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.app.DialogFragment;
+import android.support.v7.app.AlertDialog;
+import android.view.View;
+import android.widget.Button;
+import android.widget.Toast;
+
+import org.torproject.android.R;
+import org.torproject.android.ui.hiddenservices.backup.BackupUtils;
+import org.torproject.android.ui.hiddenservices.storage.PermissionManager;
+
+public class CookieActionsDialog extends DialogFragment {
+ public static final int WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTION_DIALOG = 4;
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final Bundle arguments = getArguments();
+
+ final View dialog_view = getActivity().getLayoutInflater().inflate(R.layout.layout_cookie_actions, null);
+ final AlertDialog actionDialog = new AlertDialog.Builder(getActivity())
+ .setView(dialog_view)
+ .setTitle(R.string.client_cookies)
+ .create();
+
+ Button backup = (Button) dialog_view.findViewById(R.id.btn_cookie_backup);
+ backup.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ Context mContext = v.getContext();
+
+ if (PermissionManager.usesRuntimePermissions()
+ && !PermissionManager.hasExternalWritePermission(mContext)) {
+
+ PermissionManager.requestPermissions(
+ getActivity(), WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTION_DIALOG);
+
+ return;
+ }
+
+ BackupUtils backup_utils = new BackupUtils(mContext);
+ String backupPath = backup_utils.createCookieBackup(
+ arguments.getString("domain"),
+ arguments.getString("auth_cookie_value"),
+ arguments.getInt("enabled")
+ );
+
+ if (backupPath == null || backupPath.length() < 1) {
+ Toast.makeText(mContext, R.string.error, Toast.LENGTH_LONG).show();
+ actionDialog.dismiss();
+ return;
+ }
+
+ Toast.makeText(mContext, R.string.backup_saved_at_external_storage, Toast.LENGTH_LONG).show();
+
+ Uri selectedUri = Uri.parse(backupPath.substring(0, backupPath.lastIndexOf("/")));
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setDataAndType(selectedUri, "resource/folder");
+
+ if (intent.resolveActivityInfo(mContext.getPackageManager(), 0) != null) {
+ startActivity(intent);
+ } else {
+ Toast.makeText(mContext, R.string.filemanager_not_available, Toast.LENGTH_LONG).show();
+ }
+ actionDialog.dismiss();
+ }
+ });
+
+ Button delete = (Button) dialog_view.findViewById(R.id.btn_cookie_delete);
+ delete.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ CookieDeleteDialog dialog = new CookieDeleteDialog();
+ dialog.setArguments(arguments);
+ dialog.show(getFragmentManager(), "CookieDeleteDialog");
+ actionDialog.dismiss();
+ }
+ });
+
+ Button cancel = (Button) dialog_view.findViewById(R.id.btn_cookie_cancel);
+ cancel.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ actionDialog.dismiss();
+ }
+ });
+
+ return actionDialog;
+ }
+}
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/CookieDeleteDialog.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/CookieDeleteDialog.java
new file mode 100644
index 0000000..60c4d8e
--- /dev/null
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/CookieDeleteDialog.java
@@ -0,0 +1,50 @@
+package org.torproject.android.ui.hiddenservices.dialogs;
+
+
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.app.DialogFragment;
+import android.support.v7.app.AlertDialog;
+
+import org.torproject.android.R;
+import org.torproject.android.ui.hiddenservices.providers.CookieContentProvider;
+
+public class CookieDeleteDialog extends DialogFragment {
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final Bundle arguments = getArguments();
+ final Context context = getContext();
+
+ DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ switch (which) {
+ case DialogInterface.BUTTON_POSITIVE:
+ // Delete from db
+ context.getContentResolver().delete(
+ CookieContentProvider.CONTENT_URI,
+ CookieContentProvider.ClientCookie._ID + "=" + arguments.getInt("_id"),
+ null
+ );
+
+ break;
+
+ case DialogInterface.BUTTON_NEGATIVE:
+ // Do nothing
+ break;
+ }
+ }
+ };
+
+ return new AlertDialog.Builder(context)
+ .setMessage(R.string.confirm_cookie_deletion)
+ .setPositiveButton(R.string.btn_okay, dialogClickListener)
+ .setNegativeButton(R.string.btn_cancel, dialogClickListener)
+ .create();
+ }
+}
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSCookieDialog.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSCookieDialog.java
index ff53cec..39c1b51 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSCookieDialog.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSCookieDialog.java
@@ -13,7 +13,12 @@ import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
+import com.google.zxing.integration.android.IntentIntegrator;
+
+import org.json.JSONException;
+import org.json.JSONObject;
import org.torproject.android.R;
+import org.torproject.android.ui.hiddenservices.providers.CookieContentProvider;
public class HSCookieDialog extends DialogFragment {
@@ -44,6 +49,26 @@ public class HSCookieDialog extends DialogFragment {
}
});
+ Button shareQR = (Button) dialog_view.findViewById(R.id.hs_cookie_to_qr);
+ shareQR.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ try {
+ JSONObject backup = new JSONObject();
+ backup.put(CookieContentProvider.ClientCookie.DOMAIN, arguments.getString("onion"));
+ backup.put(CookieContentProvider.ClientCookie.AUTH_COOKIE_VALUE, arguments.getString("auth_cookie_value"));
+
+ IntentIntegrator integrator = new IntentIntegrator(getActivity());
+ integrator.shareText(backup.toString());
+
+ } catch (JSONException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ cookieDialog.dismiss();
+ }
+ });
+
Button cancel = (Button) dialog_view.findViewById(R.id.hs_cookie_cancel);
cancel.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/SelectBackupDialog.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/SelectBackupDialog.java
deleted file mode 100644
index 0c0d943..0000000
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/SelectBackupDialog.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package org.torproject.android.ui.hiddenservices.dialogs;
-
-import android.app.Dialog;
-import android.content.DialogInterface;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v4.app.DialogFragment;
-import android.support.v7.app.AlertDialog;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ListView;
-
-import org.torproject.android.R;
-import org.torproject.android.ui.hiddenservices.adapters.BackupAdapter;
-import org.torproject.android.ui.hiddenservices.backup.BackupUtils;
-import org.torproject.android.ui.hiddenservices.storage.ExternalStorage;
-
-import java.io.File;
-import java.io.FilenameFilter;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-public class SelectBackupDialog extends DialogFragment {
-
- @NonNull
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- AlertDialog.Builder backupsDialog = new AlertDialog.Builder(getActivity());
-
- backupsDialog.setTitle(R.string.restore_backup);
-
- File backupDir = ExternalStorage.getOrCreateBackupDir();
- File[] files = null;
-
- try {
- files = backupDir.listFiles(new FilenameFilter() {
- @Override
- public boolean accept(File dir, String name) {
- return name.toLowerCase().endsWith(".zip");
- }
- });
- } catch (NullPointerException e) {
- // Silent block
- }
-
- if (files == null || files.length < 1) {
- backupsDialog.setMessage(R.string.create_a_backup_first);
- backupsDialog.setNegativeButton(R.string.btn_cancel, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- dialog.dismiss();
- }
- });
-
- return backupsDialog.create();
- }
-
- final View dialog_view = getActivity().getLayoutInflater().inflate(R.layout.layout_hs_backups_list, null);
-
- backupsDialog.setView(dialog_view);
- backupsDialog.setPositiveButton(R.string.btn_okay, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- dialog.dismiss();
- }
- });
-
- ListView backups = (ListView) dialog_view.findViewById(R.id.listview_hs_backups);
-
- List<File> zips = new ArrayList<>();
- Collections.addAll(zips, files);
-
- backups.setAdapter(new BackupAdapter(getContext(), R.layout.layout_hs_backups_list_item, zips));
- backups.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- BackupUtils backupUtils = new BackupUtils(view.getContext().getApplicationContext());
- File p = (File) parent.getItemAtPosition(position);
- backupUtils.restoreZipBackup(p);
- }
- });
-
- return backupsDialog.create();
- }
-}
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/SelectCookieBackupDialog.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/SelectCookieBackupDialog.java
new file mode 100644
index 0000000..de5b784
--- /dev/null
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/SelectCookieBackupDialog.java
@@ -0,0 +1,84 @@
+package org.torproject.android.ui.hiddenservices.dialogs;
+
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.app.DialogFragment;
+import android.support.v7.app.AlertDialog;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ListView;
+
+import org.torproject.android.R;
+import org.torproject.android.ui.hiddenservices.adapters.BackupAdapter;
+import org.torproject.android.ui.hiddenservices.backup.BackupUtils;
+import org.torproject.android.ui.hiddenservices.storage.ExternalStorage;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class SelectCookieBackupDialog extends DialogFragment {
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ AlertDialog.Builder cookieBackupDialog = new AlertDialog.Builder(getActivity());
+
+ cookieBackupDialog.setTitle(R.string.restore_backup);
+
+ File backupDir = ExternalStorage.getOrCreateBackupDir();
+ File[] files = null;
+
+ try {
+ files = backupDir.listFiles(new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.toLowerCase().endsWith(".json");
+ }
+ });
+ } catch (NullPointerException e) {
+ // Silent block
+ }
+
+ if (files == null || files.length < 1) {
+ cookieBackupDialog.setMessage(R.string.create_a_backup_first);
+ cookieBackupDialog.setNegativeButton(R.string.btn_cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.dismiss();
+ }
+ });
+
+ return cookieBackupDialog.create();
+ }
+
+ final View dialog_view = getActivity().getLayoutInflater().inflate(R.layout.layout_hs_backups_list, null);
+
+ cookieBackupDialog.setView(dialog_view);
+ cookieBackupDialog.setPositiveButton(R.string.btn_okay, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.dismiss();
+ }
+ });
+
+ ListView backups = (ListView) dialog_view.findViewById(R.id.listview_hs_backups);
+
+ List<File> json_backups = new ArrayList<>();
+ Collections.addAll(json_backups, files);
+
+ backups.setAdapter(new BackupAdapter(getContext(), R.layout.layout_hs_backups_list_item, json_backups));
+ backups.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ BackupUtils backupUtils = new BackupUtils(view.getContext().getApplicationContext());
+ File p = (File) parent.getItemAtPosition(position);
+ backupUtils.restoreCookieBackup(p);
+ }
+ });
+
+ return cookieBackupDialog.create();
+ }
+}
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/SelectHSBackupDialog.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/SelectHSBackupDialog.java
new file mode 100644
index 0000000..a6e3bac
--- /dev/null
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/SelectHSBackupDialog.java
@@ -0,0 +1,84 @@
+package org.torproject.android.ui.hiddenservices.dialogs;
+
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.app.DialogFragment;
+import android.support.v7.app.AlertDialog;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ListView;
+
+import org.torproject.android.R;
+import org.torproject.android.ui.hiddenservices.adapters.BackupAdapter;
+import org.torproject.android.ui.hiddenservices.backup.BackupUtils;
+import org.torproject.android.ui.hiddenservices.storage.ExternalStorage;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class SelectHSBackupDialog extends DialogFragment {
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ AlertDialog.Builder backupsDialog = new AlertDialog.Builder(getActivity());
+
+ backupsDialog.setTitle(R.string.restore_backup);
+
+ File backupDir = ExternalStorage.getOrCreateBackupDir();
+ File[] files = null;
+
+ try {
+ files = backupDir.listFiles(new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.toLowerCase().endsWith(".zip");
+ }
+ });
+ } catch (NullPointerException e) {
+ // Silent block
+ }
+
+ if (files == null || files.length < 1) {
+ backupsDialog.setMessage(R.string.create_a_backup_first);
+ backupsDialog.setNegativeButton(R.string.btn_cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.dismiss();
+ }
+ });
+
+ return backupsDialog.create();
+ }
+
+ final View dialog_view = getActivity().getLayoutInflater().inflate(R.layout.layout_hs_backups_list, null);
+
+ backupsDialog.setView(dialog_view);
+ backupsDialog.setPositiveButton(R.string.btn_okay, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.dismiss();
+ }
+ });
+
+ ListView backups = (ListView) dialog_view.findViewById(R.id.listview_hs_backups);
+
+ List<File> zips = new ArrayList<>();
+ Collections.addAll(zips, files);
+
+ backups.setAdapter(new BackupAdapter(getContext(), R.layout.layout_hs_backups_list_item, zips));
+ backups.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ BackupUtils backupUtils = new BackupUtils(view.getContext().getApplicationContext());
+ File p = (File) parent.getItemAtPosition(position);
+ backupUtils.restoreZipBackup(p);
+ }
+ });
+
+ return backupsDialog.create();
+ }
+}
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/providers/CookieContentProvider.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/providers/CookieContentProvider.java
new file mode 100644
index 0000000..f420a6d
--- /dev/null
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/providers/CookieContentProvider.java
@@ -0,0 +1,134 @@
+package org.torproject.android.ui.hiddenservices.providers;
+
+import android.content.ContentProvider;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.UriMatcher;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.net.Uri;
+import android.provider.BaseColumns;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+import org.torproject.android.ui.hiddenservices.database.HSDatabase;
+
+
+public class CookieContentProvider extends ContentProvider {
+ public static final String[] PROJECTION = new String[]{
+ ClientCookie._ID,
+ ClientCookie.DOMAIN,
+ ClientCookie.AUTH_COOKIE_VALUE,
+ ClientCookie.ENABLED
+ };
+ private static final String AUTH = "org.torproject.android.ui.hiddenservices.providers.cookie";
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://" + AUTH + "/cookie");
+ //UriMatcher
+ private static final int COOKIES = 1;
+ private static final int COOKIE_ID = 2;
+
+ private static final UriMatcher uriMatcher;
+
+ static {
+ uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+ uriMatcher.addURI(AUTH, "hs", COOKIES);
+ uriMatcher.addURI(AUTH, "hs/#", COOKIE_ID);
+ }
+
+ private HSDatabase mServervices;
+ private Context mContext;
+
+ @Override
+ public boolean onCreate() {
+ mContext = getContext();
+ mServervices = new HSDatabase(mContext);
+ return true;
+ }
+
+ @Nullable
+ @Override
+ public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
+ String where = selection;
+ if (uriMatcher.match(uri) == COOKIE_ID) {
+ where = "_id=" + uri.getLastPathSegment();
+ }
+
+ SQLiteDatabase db = mServervices.getReadableDatabase();
+
+ return db.query(HSDatabase.HS_CLIENT_COOKIE_TABLE_NAME, projection, where,
+ selectionArgs, null, null, sortOrder);
+ }
+
+ @Nullable
+ @Override
+ public String getType(@NonNull Uri uri) {
+ int match = uriMatcher.match(uri);
+
+ switch (match) {
+ case COOKIES:
+ return "vnd.android.cursor.dir/vnd.torproject.cookies";
+ case COOKIE_ID:
+ return "vnd.android.cursor.item/vnd.torproject.cookie";
+ default:
+ return null;
+ }
+ }
+
+ @Nullable
+ @Override
+ public Uri insert(@NonNull Uri uri, ContentValues values) {
+ long regId;
+
+ SQLiteDatabase db = mServervices.getWritableDatabase();
+
+ regId = db.insert(HSDatabase.HS_CLIENT_COOKIE_TABLE_NAME, null, values);
+
+ mContext.getContentResolver().notifyChange(CONTENT_URI, null);
+
+ return ContentUris.withAppendedId(CONTENT_URI, regId);
+ }
+
+ @Override
+ public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) {
+
+ String where = selection;
+ if (uriMatcher.match(uri) == COOKIE_ID) {
+ where = "_id=" + uri.getLastPathSegment();
+ }
+
+ SQLiteDatabase db = mServervices.getWritableDatabase();
+
+ Integer rows = db.delete(HSDatabase.HS_CLIENT_COOKIE_TABLE_NAME, where, selectionArgs);
+
+ mContext.getContentResolver().notifyChange(CONTENT_URI, null);
+
+ return rows;
+
+ }
+
+ @Override
+ public int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ SQLiteDatabase db = mServervices.getWritableDatabase();
+
+ String where = selection;
+ if (uriMatcher.match(uri) == COOKIE_ID) {
+ where = "_id=" + uri.getLastPathSegment();
+ }
+
+ Integer rows = db.update(HSDatabase.HS_CLIENT_COOKIE_TABLE_NAME, values, where, null);
+ mContext.getContentResolver().notifyChange(CONTENT_URI, null);
+
+ return rows;
+ }
+
+ public static final class ClientCookie implements BaseColumns {
+ public static final String DOMAIN = "domain";
+ public static final String AUTH_COOKIE_VALUE = "auth_cookie_value";
+ public static final String ENABLED = "enabled";
+
+ private ClientCookie() {
+ }
+ }
+}
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/storage/ExternalStorage.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/storage/ExternalStorage.java
index cda3f8c..c50108b 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/storage/ExternalStorage.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/storage/ExternalStorage.java
@@ -5,13 +5,13 @@ import android.os.Environment;
import java.io.File;
public class ExternalStorage {
- private static final String BACKUPS_DIR = "Orbot-HiddenServices";
+ private static final String ORBOT_BACKUPS_DIR = "Orbot";
public static File getOrCreateBackupDir() {
if (!isExternalStorageWritable())
return null;
- File dir = new File(Environment.getExternalStorageDirectory(), BACKUPS_DIR);
+ File dir = new File(Environment.getExternalStorageDirectory(), ORBOT_BACKUPS_DIR);
if (!dir.isDirectory() && !dir.mkdirs())
return null;
diff --git a/app/src/main/res/layout/layout_activity_client_cookies.xml b/app/src/main/res/layout/layout_activity_client_cookies.xml
new file mode 100644
index 0000000..b8f0626
--- /dev/null
+++ b/app/src/main/res/layout/layout_activity_client_cookies.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fitsSystemWindows="true"
+ tools:context="org.torproject.android.ui.hiddenservices.ClientCookiesActivity">
+
+ <android.support.design.widget.AppBarLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:theme="@style/DefaultTheme.AppBarOverlay">
+
+ <android.support.v7.widget.Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?attr/actionBarSize"
+ android:background="?attr/colorPrimary"
+ app:popupTheme="@style/DefaultTheme.PopupOverlay" />
+
+ </android.support.design.widget.AppBarLayout>
+
+ <include layout="@layout/layout_content_client_cookies" />
+
+ <android.support.design.widget.FloatingActionButton
+ android:id="@+id/fab"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom|end"
+ android:layout_margin="@dimen/fab_margin"
+ app:srcCompat="@android:drawable/stat_notify_more"
+ app:backgroundTint="@android:color/darker_gray" />
+
+</android.support.design.widget.CoordinatorLayout>
diff --git a/app/src/main/res/layout/layout_add_client_cookie_dialog.xml b/app/src/main/res/layout/layout_add_client_cookie_dialog.xml
new file mode 100644
index 0000000..4669a92
--- /dev/null
+++ b/app/src/main/res/layout/layout_add_client_cookie_dialog.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="5dp"
+ android:paddingRight="5dp"
+ android:paddingTop="5dp"
+ android:paddingBottom="5dp">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/label_onion_name"
+ android:text="@string/onion"
+ android:textAppearance="@style/TextAppearance.AppCompat.Widget.PopupMenu.Small"
+ android:paddingLeft="5dp" />
+
+ <EditText
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:inputType="text"
+ android:ems="10"
+ android:id="@+id/cookie_onion" />
+
+ <TextView
+ android:text="@string/auth_cookie"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/label_cookie_value"
+ android:textAppearance="@style/TextAppearance.AppCompat.Widget.PopupMenu.Small"
+ android:paddingLeft="5dp" />
+
+ <EditText
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ems="10"
+ android:id="@+id/cookie_value"
+ android:inputType="text" />
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <Button
+ android:text="@string/btn_cancel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/cookie_dialog_cancel"
+ android:layout_weight="1"
+ style="@style/Widget.AppCompat.Button.Borderless.Colored" />
+
+ <Button
+ android:text="@string/save"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/cookie_dialog_save"
+ android:layout_weight="1"
+ style="@style/Widget.AppCompat.Button.Borderless.Colored" />
+
+ </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/layout_client_cookie_list_item.xml b/app/src/main/res/layout/layout_client_cookie_list_item.xml
new file mode 100644
index 0000000..80eefb9
--- /dev/null
+++ b/app/src/main/res/layout/layout_client_cookie_list_item.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:padding="15dp">
+
+ <TextView
+ android:id="@+id/cookie_onion"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textSize="18sp"
+ android:layout_weight="1" />
+
+ <Switch
+ android:id="@+id/cookie_switch"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:focusable="false"
+ android:focusableInTouchMode="false"
+ android:switchPadding="30dp" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/layout_content_client_cookies.xml b/app/src/main/res/layout/layout_content_client_cookies.xml
new file mode 100644
index 0000000..3ee9a89
--- /dev/null
+++ b/app/src/main/res/layout/layout_content_client_cookies.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/content_client_cookies"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ app:layout_behavior="@string/appbar_scrolling_view_behavior"
+ tools:context="org.torproject.android.ui.hiddenservices.ClientCookiesActivity"
+ tools:showIn="@layout/layout_activity_client_cookies">
+
+ <ListView
+ android:id="@+id/clien_cookies_list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+</RelativeLayout>
diff --git a/app/src/main/res/layout/layout_cookie_actions.xml b/app/src/main/res/layout/layout_cookie_actions.xml
new file mode 100644
index 0000000..64d8c1c
--- /dev/null
+++ b/app/src/main/res/layout/layout_cookie_actions.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical" android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <Button
+ android:text="@string/backup_cookie"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/btn_cookie_backup" />
+
+ <Button
+ android:text="@string/delete_cookie"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/btn_cookie_delete" />
+
+ <Button
+ android:text="@string/btn_cancel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/btn_cookie_cancel" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/layout_hs_cookie.xml b/app/src/main/res/layout/layout_hs_cookie.xml
index 398178f..6d1a893 100644
--- a/app/src/main/res/layout/layout_hs_cookie.xml
+++ b/app/src/main/res/layout/layout_hs_cookie.xml
@@ -18,6 +18,12 @@
android:id="@+id/hs_cookie_to_clipboard" />
<Button
+ android:text="@string/share_as_qr"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/hs_cookie_to_qr" />
+
+ <Button
android:text="@string/btn_cancel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/app/src/main/res/menu/cookie_menu.xml b/app/src/main/res/menu/cookie_menu.xml
new file mode 100644
index 0000000..7811025
--- /dev/null
+++ b/app/src/main/res/menu/cookie_menu.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+
+ <item
+ android:id="@+id/cookie_restore_backup"
+ android:title="@string/restore_backup" />
+ <item
+ android:id="@+id/cookie_from_qr"
+ android:title="@string/cookie_from_QR" />
+</menu>
\ No newline at end of file
diff --git a/app/src/main/res/menu/orbot_main.xml b/app/src/main/res/menu/orbot_main.xml
index 179675a..e556b76 100644
--- a/app/src/main/res/menu/orbot_main.xml
+++ b/app/src/main/res/menu/orbot_main.xml
@@ -44,10 +44,22 @@
</menu>
</item>
- <item android:id="@+id/menu_hidden_services"
+ <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>
+ </item>
<!--
<item android:id="@+id/menu_promo_apps"
diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml
new file mode 100644
index 0000000..7abc06d
--- /dev/null
+++ b/app/src/main/res/values-v21/styles.xml
@@ -0,0 +1 @@
+<resources></resources>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 4402608..6a07c44 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -128,21 +128,21 @@
<string name="pref_entrance_node_dialog">Enter Entrance Nodes</string>
<string name="pref_allow_background_starts_title">Allow Background Starts</string>
<string name="pref_allow_background_starts_summary">Let any app tell Orbot to start Tor and related services</string>
-
+
<string name="button_proxy_all">Proxy All</string>
<string name="button_proxy_none">Proxy None</string>
<string name="button_invert_selection">Invert Selection</string>
<string name="pref_proxy_title">Outbound Network Proxy (Optional)</string>
-
+
<string name="pref_proxy_type_title">Outbound Proxy Type</string>
<string name="pref_proxy_type_summary">Protocol to use for proxy server: HTTP, HTTPS, Socks4, Socks5</string>
<string name="pref_proxy_type_dialog">Enter Proxy Type</string>
-
+
<string name="pref_proxy_host_title">Outbound Proxy Host</string>
<string name="pref_proxy_host_summary">Proxy Server hostname</string>
<string name="pref_proxy_host_dialog">Enter Proxy Host</string>
-
+
<string name="pref_proxy_port_title">Outbound Proxy Port</string>
<string name="pref_proxy_port_summary">Proxy Server port</string>
<string name="pref_proxy_port_dialog">Enter Proxy port</string>
@@ -150,13 +150,12 @@
<string name="pref_proxy_username_title">Outbound Proxy Username</string>
<string name="pref_proxy_username_summary">Proxy Username (Optional)</string>
<string name="pref_proxy_username_dialog">Enter Proxy Username</string>
-
+
<string name="pref_proxy_password_title">Outbound Proxy Password</string>
<string name="pref_proxy_password_summary">Proxy Password (Optional)</string>
<string name="pref_proxy_password_dialog">Enter Proxy Password</string>
-
-
-
+
+
<string name="status">Status</string>
<string name="setting_up_full_transparent_proxying_">Setting up full transparent proxying…</string>
<string name="setting_up_app_based_transparent_proxying_">Setting up app-based transparent proxying…</string>
@@ -227,17 +226,17 @@
<string name="unable_to_reset_tor">Reboot your device, unable to reset Tor!</string>
<string name="pref_use_sys_iptables_title">Use Default Iptables</string>
<string name="pref_use_sys_iptables_summary">use the built-in iptables binary instead of the one bundled with Orbot</string>
-
+
<string name="error_installing_binares">The Tor binaries were not able to be installed or upgraded.</string>
-
+
<string name="pref_use_persistent_notifications">Always keep the icon in toolbar when Orbot is connected</string>
<string name="pref_use_persistent_notifications_title">Always-On Notifications</string>
-
+
<string name="pref_use_expanded_notifications">Show expanded notification with Tor exit country and IP</string>
<string name="pref_use_expanded_notifications_title">Expanded Notifications</string>
-
+
<string name="notification_using_bridges">Bridges enabled!</string>
- <string name="default_bridges"/>
+ <string name="default_bridges" />
<string name="set_locale_title">Language</string>
<string name="set_locale_summary">Choose the locale and language for Orbot</string>
<string name="wizard_locale_title">Choose Language</string>
@@ -251,8 +250,8 @@
<string name="pref_disable_network_title">No Network Auto-Sleep</string>
<string name="pref_disable_network_summary">Put Tor to sleep when there is no internet available</string>
<string name="newnym">You\'ve switched to a new Tor identity!</string>
-
- <string name="menu_verify_browser">Browser</string>
+
+ <string name="menu_verify_browser">Browser</string>
<string name="menu_use_chatsecure">Use ChatSecure</string>
<string name="permission_manage_tor_label">Manage Tor</string>
@@ -262,77 +261,77 @@
<string name="no_network_connectivity_putting_tor_to_sleep_">No network connectivity. Putting Tor to sleep…</string>
<string name="network_connectivity_is_good_waking_tor_up_">Network connectivity is good. Waking Tor up…</string>
<string name="updating_settings_in_tor_service">updating settings in Tor service</string>
-
- <string name="pref_socks_title">Tor SOCKS</string>
+
+ <string name="pref_socks_title">Tor SOCKS</string>
<string name="pref_socks_summary">Port that Tor offers its SOCKS proxy on (default: 9050 or 0 to disable)</string>
<string name="pref_socks_dialog">SOCKS Port Config</string>
-
- <string name="pref_transport_title">Tor TransProxy Port</string>
+
+ <string name="pref_transport_title">Tor TransProxy Port</string>
<string name="pref_transport_summary">Port that Tor offers its Transparent Proxy on (default: 9040 or 0 to disable)</string>
<string name="pref_transport_dialog">TransProxy Port Config</string>
-
-
- <string name="pref_dnsport_title">Tor DNS Port</string>
+
+
+ <string name="pref_dnsport_title">Tor DNS Port</string>
<string name="pref_dnsport_summary">Port that Tor offers its DNS on (default: 5400 or 0 to disable)</string>
<string name="pref_dnsport_dialog">DNS Port Config</string>
-
-
- <string name="pref_torrc_title">Torrc Custom Config</string>
+
+
+ <string name="pref_torrc_title">Torrc Custom Config</string>
<string name="pref_torrc_summary">EXPERTS ONLY: enter direct torrc config lines</string>
<string name="pref_torrc_dialog">Custom Torrc</string>
-
- <string name="wizard_tips_martus">Mobile Martus - Benetech Human Rights Documentation App</string>
+
+ <string name="wizard_tips_martus">Mobile Martus - Benetech Human Rights Documentation App</string>
<string name="your_tor_public_ips_">Your Tor Public IPs:</string>
<string name="please_disable_this_app_in_android_settings_apps_if_you_are_having_problems_with_orbot_">"Please disable this app in Android->Settings->Apps if you are having problems with Orbot: "</string>
<string name="app_conflict">App Conflict</string>
-
+
<string name="pref_transproxy_refresh_title">Transproxy Auto-Refresh</string>
<string name="pref_transproxy_refresh_summary">Re-apply Transproxy rules when the network state changes</string>
-
+
<string name="pref_transproxy_flush_title">Transproxy FORCE REMOVE</string>
<string name="pref_transproxy_flush_summary">Tap here to flush all transproxy network rules NOW</string>
<string name="transparent_proxy_rules_flushed_">Transparent proxy rules flushed!</string>
<string name="you_do_not_have_root_access_enabled">You do not have ROOT access enabled</string>
<string name="you_may_need_to_stop_and_start_orbot_for_settings_change_to_be_enabled_">You may need to stop and start Orbot for settings change to be enabled.</string>
-
+
<string name="menu_vpn">Apps</string>
-
+
<string name="kbps">kbps</string>
-
+
<string name="mbps">mbps</string>
-
+
<string name="kb">KB</string>
-
+
<string name="mb">MB</string>
-
+
<string name="bridges_updated">Bridges Updated</string>
-
+
<string name="restart_orbot_to_use_this_bridge_">Please restart Orbot to enable the changes</string>
-
+
<string name="menu_qr">QR Codes</string>
-
+
<string name="if_your_mobile_network_actively_blocks_tor_you_can_use_a_tor_bridge_to_access_the_network_another_way_to_get_bridges_is_to_send_an_email_to_bridges_torproject_org_please_note_that_you_must_send_the_email_using_an_address_from_one_of_the_following_email_providers_riseup_gmail_or_yahoo_">If your mobile network actively blocks Tor, you can use a Bridge to access the network. SELECT one of the bridge types above to enable bridges.</string>
-
+
<string name="bridge_mode">Bridge Mode</string>
-
+
<string name="get_bridges_email">Email</string>
<string name="get_bridges_web">Web</string>
-
+
<string name="activate">Activate</string>
-
+
<string name="apps_mode">Apps VPN Mode</string>
-
+
<string name="you_can_enable_all_apps_on_your_device_to_run_through_the_tor_network_using_the_vpn_feature_of_android_">You can enable all apps on your device to run through the Tor network using the VPN feature of Android.\n\n*WARNING* This is a new, experimental feature and in some cases may not start automatically, or may stop. It should NOT be used for anonymity, and ONLY used for getting through firewalls and filters.</string>
-
+
<string name="send_email">Send Email</string>
-
+
<string name="you_must_get_a_bridge_address_by_email_web_or_from_a_friend_once_you_have_this_address_please_paste_it_into_the_bridges_preference_in_orbot_s_setting_and_restart_">You can get a bridge address through email, the web or by scanning a bridge QR code. Select \'Email\' or \'Web\' below to request a bridge address.\n\nOnce you have an address, copy & paste it into the \"Bridges\" preference in Orbot\'s setting and restart.</string>
-
+
<string name="install_orweb">Install Orfox</string>
-
+
<string name="standard_browser">Standard Browser</string>
-
+
<string name="note_only_standard_tor_bridges_work_on_intel_x86_atom_devices">NOTE: Only standard Tor bridges work on Intel X86/ATOM devices</string>
<string name="vpn_default_world">World (Location)</string>
@@ -359,6 +358,7 @@
<string name="restore_backup">Restore Backup</string>
<string name="create_a_backup_first">Create a backup first</string>
<string name="name_can_t_be_empty">Name can\'t be empty</string>
+ <string name="fields_can_t_be_empty">Fields can\'t be empty</string>
<string name="start_tor_again_for_finish_the_process">Start Tor again for finish the process</string>
<string name="confirm_service_deletion">Confirm service deletion</string>
<string name="click_again_for_backup">Click again for backup</string>
@@ -367,4 +367,13 @@
<string name="copy_cookie_to_clipboard">Copy cookie to clipboard</string>
<string name="auth_cookie_was_not_configured">Auth cookie was not configured</string>
<string name="please_restart_Orbot_to_enable_the_changes">Please restart Orbot to enable the changes</string>
+ <string name="client_cookies">Client cookies</string>
+ <string name="onion">.onion</string>
+ <string name="invalid_onion_address">Invalid .onion address</string>
+ <string name="cookie_from_QR">Read from QR</string>
+ <string name="backup_cookie">Backup cookie</string>
+ <string name="delete_cookie">Delete cookie</string>
+ <string name="confirm_cookie_deletion">Confirm cookie deletion</string>
+ <string name="hosted_services">Hosted Services</string>
+ <string name="share_as_qr">Share as QR</string>
</resources>
diff --git a/orbotservice/src/main/java/org/torproject/android/service/TorService.java b/orbotservice/src/main/java/org/torproject/android/service/TorService.java
index 19fb0d1..8956163 100644
--- a/orbotservice/src/main/java/org/torproject/android/service/TorService.java
+++ b/orbotservice/src/main/java/org/torproject/android/service/TorService.java
@@ -132,7 +132,8 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
private Shell mShellPolipo;
- private static final Uri CONTENT_URI = Uri.parse("content://org.torproject.android.ui.hiddenservices.providers/hs");
+ private static final Uri HS_CONTENT_URI = Uri.parse("content://org.torproject.android.ui.hiddenservices.providers/hs");
+ private static final Uri COOKIE_CONTENT_URI = Uri.parse("content://org.torproject.android.ui.hiddenservices.providers.cookie/cookie");
public static final class HiddenService implements BaseColumns {
public static final String NAME = "name";
@@ -148,7 +149,16 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
}
}
- private String[] mProjection = new String[]{
+ public static final class ClientCookie implements BaseColumns {
+ public static final String DOMAIN = "domain";
+ public static final String AUTH_COOKIE_VALUE = "auth_cookie_value";
+ public static final String ENABLED = "enabled";
+
+ private ClientCookie() {
+ }
+ }
+
+ private String[] hsProjection = new String[]{
HiddenService._ID,
HiddenService.NAME,
HiddenService.DOMAIN,
@@ -158,6 +168,12 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
HiddenService.ONION_PORT,
HiddenService.ENABLED};
+ private String[] cookieProjection = new String[]{
+ ClientCookie._ID,
+ ClientCookie.DOMAIN,
+ ClientCookie.AUTH_COOKIE_VALUE,
+ ClientCookie.ENABLED};
+
public void debug(String msg)
{
if (Prefs.useDebugLogging())
@@ -778,7 +794,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
// Tor is running, update new .onion names at db
ContentResolver mCR = getApplicationContext().getContentResolver();
- Cursor hidden_services = mCR.query(CONTENT_URI, mProjection, null, null, null);
+ Cursor hidden_services = mCR.query(HS_CONTENT_URI, hsProjection, null, null, null);
if(hidden_services != null) {
try {
while (hidden_services.moveToNext()) {
@@ -804,7 +820,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
fields.put(HiddenService.AUTH_COOKIE_VALUE, aux[1]);
}
fields.put(HiddenService.DOMAIN, onionHostname);
- mCR.update(CONTENT_URI, fields, "port=" + HSLocalPort , null);
+ mCR.update(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);
@@ -1792,9 +1808,10 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
return false;
}
- /* ---- Hidden Services ---- */
ContentResolver mCR = getApplicationContext().getContentResolver();
- Cursor hidden_services = mCR.query(CONTENT_URI, mProjection, HiddenService.ENABLED + "=1", null, null);
+
+ /* ---- Hidden Services ---- */
+ Cursor hidden_services = mCR.query(HS_CONTENT_URI, hsProjection, HiddenService.ENABLED + "=1", null, null);
if(hidden_services != null) {
try {
while (hidden_services.moveToNext()) {
@@ -1821,6 +1838,22 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
hidden_services.close();
}
+ /* ---- Client Cookies ---- */
+ Cursor client_cookies = mCR.query(COOKIE_CONTENT_URI, cookieProjection, 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');
+ }
+ } catch (Exception e) {
+ Log.e(OrbotConstants.TAG,"error starting share server",e);
+ }
+
+ client_cookies.close();
+ }
+
return true;
}
[View Less]
1
0
commit ba76f574a91be0d7cb4ccea8e4756a69e3a99fc6
Author: arrase <arrase(a)gmail.com>
Date: Mon Dec 5 22:20:47 2016 +0100
spanish translation
---
app/src/main/res/values-es/strings.xml | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index 15c5d59..8291ea4 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -291,4 +291,…
[View More]36 @@ direcciones (o rangos). No prevalecen sobre las configuraciones de exclusión de
<string name="standard_browser">Navegador estándar</string>
<string name="note_only_standard_tor_bridges_work_on_intel_x86_atom_devices">NOTA: Sólo los repetidores puente (bridges) estándar de Tor funcionan en dispositivos Intel X86/ATOM</string>
<string name="vpn_default_world">Mundo</string>
+
+ <string name="hidden_services">Servicios Ocultos</string>
+ <string name="title_activity_hidden_services">Servicios Ocultos</string>
+ <string name="menu_hidden_services">Servicios Ocultos</string>
+ <string name="save">Guardar</string>
+ <string name="ports">Puertos</string>
+ <string name="local_port">Puerto Local</string>
+ <string name="onion_port">Puerto Onion</string>
+ <string name="name">Nombre</string>
+ <string name="done">Hecho!</string>
+ <string name="invalid_port">Puerto no vàlido</string>
+ <string name="copy_address_to_clipboard">Copiar dirección a portapapeles</string>
+ <string name="show_auth_cookie">Mostra cookie de autenticación</string>
+ <string name="backup_service">Crear backup</string>
+ <string name="delete_service">Borrar servicio</string>
+ <string name="backup_saved_at_external_storage">Backup guardado en almacenamiento externo</string>
+ <string name="backup_restored">Backup restaurado</string>
+ <string name="filemanager_not_available">Gestor de archivos no disponible</string>
+ <string name="please_grant_permissions_for_external_storage">Permitir permisos para almacenamiento externo</string>
+ <string name="permission_granted">Permisos concedidos</string>
+ <string name="permission_denied">Permisos denegados</string>
+ <string name="restore_backup">Restaurar Backup</string>
+ <string name="create_a_backup_first">Crear primero una copia de seguridad</string>
+ <string name="name_can_t_be_empty">Nombre no puede estar vacio</string>
+ <string name="start_tor_again_for_finish_the_process">Inicie Tor de nuevo para finalizar el proceso</string>
+ <string name="confirm_service_deletion">Confirmar eliminación de servicio</string>
+ <string name="click_again_for_backup">Haga clic de nuevo para realizar copias de seguridad</string>
+ <string name="service_type">Tipo de servicio</string>
+ <string name="auth_cookie">Cookie de autenticación</string>
+ <string name="copy_cookie_to_clipboard">Copiar cookie al portapapeles</string>
+ <string name="auth_cookie_was_not_configured">La cookie de autenticación no estaba configurada</string>
+ <string name="please_restart_Orbot_to_enable_the_changes">Reinicie Orbot para habilitar los cambios</string>
</resources>
[View Less]
1
0

02 Mar '17
commit a5744d795891d0092f3127976a50381f30746fd2
Author: Nathan Freitas <nathan(a)freitas.net>
Date: Fri Jan 13 22:14:39 2017 -0500
small chnage to only check for sys iptables once
---
.../android/service/transproxy/TorTransProxy.java | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/orbotservice/src/main/java/org/torproject/android/service/transproxy/TorTransProxy.java b/orbotservice/src/main/java/org/torproject/android/service/…
[View More]transproxy/TorTransProxy.java
index ca6d830..6c3121a 100644
--- a/orbotservice/src/main/java/org/torproject/android/service/transproxy/TorTransProxy.java
+++ b/orbotservice/src/main/java/org/torproject/android/service/transproxy/TorTransProxy.java
@@ -103,20 +103,21 @@ public class TorTransProxy implements TorServiceConstants {
private String findSystemIPTables ()
{
-
- //if the user wants us to use the built-in iptables, then we have to find it
- File fileIpt = new File("/system/xbin/iptables");
-
- if (fileIpt.exists())
- mSysIptables = fileIpt.getAbsolutePath();
- else
+ if (mSysIptables == null)
{
-
- fileIpt = new File("/system/bin/iptables");
+ //if the user wants us to use the built-in iptables, then we have to find it
+ File fileIpt = new File("/system/xbin/iptables");
if (fileIpt.exists())
mSysIptables = fileIpt.getAbsolutePath();
- }
+ else
+ {
+
+ fileIpt = new File("/system/bin/iptables");
+
+ if (fileIpt.exists())
+ mSysIptables = fileIpt.getAbsolutePath();
+ }
return mSysIptables;
}
[View Less]
1
0
commit 070d6151837a2780cd775c9f47879dbdeb95476d
Author: arrase <arrase(a)gmail.com>
Date: Mon Dec 5 21:28:33 2016 +0100
center port text
---
app/src/main/res/layout/layout_hs_list_item.xml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/app/src/main/res/layout/layout_hs_list_item.xml b/app/src/main/res/layout/layout_hs_list_item.xml
index e8b3f4c..d55f688 100644
--- a/app/src/main/res/layout/layout_hs_list_item.xml
+++ b/app/src/main/res/layout/layout_hs_list_item.xml
@@ -16,…
[View More]6 +16,8 @@
android:layout_height="match_parent"
android:id="@+id/hs_port"
android:layout_width="wrap_content"
+ android:paddingTop="10dp"
+ android:paddingRight="10dp"
android:textSize="35sp" />
<LinearLayout
[View Less]
1
0
commit 8d5df9c9eb12371a7b7c0394a6f7bb6a90e75e4e
Author: arrase <arrase(a)gmail.com>
Date: Mon Dec 5 21:14:15 2016 +0100
better cookie dialog
---
.../ui/hiddenservices/dialogs/HSActionsDialog.java | 7 +--
.../ui/hiddenservices/dialogs/HSCookieDialog.java | 56 ++++++++++++++++++++++
.../ui/hiddenservices/dialogs/HSDataDialog.java | 3 ++
app/src/main/res/layout/layout_hs_cookie.xml | 25 ++++++++++
app/src/main/res/values/strings.xml | 1 +
5 files …
[View More]changed, 89 insertions(+), 3 deletions(-)
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 06b650b..ff7f7e1 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
@@ -87,15 +87,16 @@ public class HSActionsDialog extends DialogFragment {
showAuth.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
String auth_cookie_value = arguments.getString("auth_cookie_value");
+
if (arguments.getInt("auth_cookie") == 1) {
if (auth_cookie_value == null || auth_cookie_value.length() < 1) {
Toast.makeText(
v.getContext(), R.string.please_restart_Orbot_to_enable_the_changes, Toast.LENGTH_LONG
).show();
} else {
- new AlertDialog.Builder(getActivity())
- .setMessage(auth_cookie_value)
- .show();
+ HSCookieDialog dialog = new HSCookieDialog();
+ dialog.setArguments(arguments);
+ dialog.show(getFragmentManager(), "HSCookieDialog");
}
} else {
Toast.makeText(
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSCookieDialog.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSCookieDialog.java
new file mode 100644
index 0000000..ff53cec
--- /dev/null
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSCookieDialog.java
@@ -0,0 +1,56 @@
+package org.torproject.android.ui.hiddenservices.dialogs;
+
+import android.app.Dialog;
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.app.DialogFragment;
+import android.support.v7.app.AlertDialog;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import org.torproject.android.R;
+
+public class HSCookieDialog extends DialogFragment {
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final View dialog_view = getActivity().getLayoutInflater().inflate(R.layout.layout_hs_cookie, null);
+
+ final Bundle arguments = getArguments();
+ final String auth_cookie_value = arguments.getString("auth_cookie_value");
+
+ final AlertDialog cookieDialog = new AlertDialog.Builder(getActivity())
+ .setView(dialog_view)
+ .create();
+
+ TextView cookie = (TextView) dialog_view.findViewById(R.id.hs_cookie);
+ cookie.setText(auth_cookie_value);
+
+ Button clipboard = (Button) dialog_view.findViewById(R.id.hs_cookie_to_clipboard);
+ clipboard.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ Context mContext = v.getContext();
+ ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
+ ClipData clip = ClipData.newPlainText("cookie", auth_cookie_value);
+ clipboard.setPrimaryClip(clip);
+ Toast.makeText(mContext, R.string.done, Toast.LENGTH_LONG).show();
+ cookieDialog.dismiss();
+ }
+ });
+
+ Button cancel = (Button) dialog_view.findViewById(R.id.hs_cookie_cancel);
+ cancel.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ cookieDialog.dismiss();
+ }
+ });
+
+ return cookieDialog;
+ }
+}
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSDataDialog.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSDataDialog.java
index 56c6d3f..9825560 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSDataDialog.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSDataDialog.java
@@ -47,6 +47,9 @@ public class HSDataDialog extends DialogFragment {
if (checkInput(serverName, localPort, onionPort)) {
saveData(serverName, localPort, onionPort, authCookie);
+ Toast.makeText(
+ v.getContext(), R.string.please_restart_Orbot_to_enable_the_changes, Toast.LENGTH_LONG
+ ).show();
serviceDataDialog.dismiss();
}
}
diff --git a/app/src/main/res/layout/layout_hs_cookie.xml b/app/src/main/res/layout/layout_hs_cookie.xml
new file mode 100644
index 0000000..398178f
--- /dev/null
+++ b/app/src/main/res/layout/layout_hs_cookie.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical" android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/hs_cookie"
+ android:paddingBottom="5dp"
+ android:paddingLeft="5dp"
+ android:paddingTop="5dp" />
+
+ <Button
+ android:text="@string/copy_cookie_to_clipboard"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/hs_cookie_to_clipboard" />
+
+ <Button
+ android:text="@string/btn_cancel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/hs_cookie_cancel" />
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index b8192b8..4402608 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -364,6 +364,7 @@
<string name="click_again_for_backup">Click again for backup</string>
<string name="service_type">Service type</string>
<string name="auth_cookie">Auth cookie</string>
+ <string name="copy_cookie_to_clipboard">Copy cookie to clipboard</string>
<string name="auth_cookie_was_not_configured">Auth cookie was not configured</string>
<string name="please_restart_Orbot_to_enable_the_changes">Please restart Orbot to enable the changes</string>
</resources>
[View Less]
1
0
commit f1a8fbd6b64446e2ccf3c594ceb3f528694ea419
Author: arrase <arrase(a)gmail.com>
Date: Thu Dec 8 16:16:47 2016 +0100
isolate
---
app/src/main/java/org/torproject/android/OrbotMainActivity.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/src/main/java/org/torproject/android/OrbotMainActivity.java b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
index 062db3d..ef9d6a0 100644
--- a/app/src/main/java/org/torproject/android/…
[View More]OrbotMainActivity.java
+++ b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
@@ -1305,7 +1305,7 @@ public class OrbotMainActivity extends AppCompatActivity
String newTorStatus = msg.getData().getString("status");
String log = (String)msg.obj;
- if (torStatus == null && newTorStatus != null) //first time status
+ if (torStatus == null && newTorStatus != null) //first time status
{
torStatus = newTorStatus;
findViewById(R.id.frameMain).setVisibility(View.VISIBLE);
[View Less]
1
0