From 74842cba92591aa9fbf64e8c6f39900a68b0c11c Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 19 Oct 2018 23:15:13 +0200 Subject: #8919 update dependencies --- .../java/de/blinkt/openvpn/core/OrbotHelper.java | 202 +++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 app/src/main/java/de/blinkt/openvpn/core/OrbotHelper.java (limited to 'app/src/main/java/de/blinkt/openvpn/core/OrbotHelper.java') diff --git a/app/src/main/java/de/blinkt/openvpn/core/OrbotHelper.java b/app/src/main/java/de/blinkt/openvpn/core/OrbotHelper.java new file mode 100644 index 00000000..68f5835f --- /dev/null +++ b/app/src/main/java/de/blinkt/openvpn/core/OrbotHelper.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2012-2018 Arne Schwabe + * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt + */ + +/* + * Portions Copyright 2014-2016 Hans-Christoph Steiner + * Portions Copyright 2012-2016 Nathan Freitas + * Portions Copyright (c) 2016 CommonsWare, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package de.blinkt.openvpn.core; + +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.text.TextUtils; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static de.blinkt.openvpn.core.OpenVPNService.ORBOT_PACKAGE_NAME; + +public class OrbotHelper { + //! Based on the class from NetCipher but stripped down and modified for icsopenvpn + + /** + * {@link Intent} send by Orbot with {@code ON/OFF/STARTING/STOPPING} status + * included as an {@link #EXTRA_STATUS} {@code String}. Your app should + * always receive {@code ACTION_STATUS Intent}s since any other app could + * start Orbot. Also, user-triggered starts and stops will also cause + * {@code ACTION_STATUS Intent}s to be broadcast. + */ + public final static String ACTION_STATUS = "org.torproject.android.intent.action.STATUS"; + public final static String STATUS_ON = "ON"; + public final static String STATUS_STARTS_DISABLED = "STARTS_DISABLED"; + + public final static String STATUS_STARTING = "STARTING"; + public final static String STATUS_STOPPING = "STOPPING"; + public final static String EXTRA_STATUS = "org.torproject.android.intent.extra.STATUS"; + /** + * A request to Orbot to transparently start Tor services + */ + public final static String ACTION_START = "org.torproject.android.intent.action.START"; + public final static String EXTRA_PACKAGE_NAME = "org.torproject.android.intent.extra.PACKAGE_NAME"; + public static final int SOCKS_PROXY_PORT_DEFAULT = 9050; + private static OrbotHelper mInstance; + + String EXTRA_SOCKS_PROXY_HOST = "org.torproject.android.intent.extra.SOCKS_PROXY_HOST"; + String EXTRA_SOCKS_PROXY_PORT = "org.torproject.android.intent.extra.SOCKS_PROXY_PORT"; + private Context mContext; + private Set statusCallbacks = new HashSet<>(); + private BroadcastReceiver orbotStatusReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context c, Intent intent) { + if (TextUtils.equals(intent.getAction(), + OrbotHelper.ACTION_STATUS)) { + for (StatusCallback cb : statusCallbacks) { + cb.onStatus(intent); + } + + String status = intent.getStringExtra(EXTRA_STATUS); + if (TextUtils.equals(status, STATUS_ON)) { + int socksPort = intent.getIntExtra(EXTRA_SOCKS_PROXY_PORT, SOCKS_PROXY_PORT_DEFAULT); + String socksHost = intent.getStringExtra(EXTRA_SOCKS_PROXY_HOST); + if (TextUtils.isEmpty(socksHost)) + socksHost = "127.0.0.1"; + for (StatusCallback cb : statusCallbacks) { + cb.onOrbotReady(intent, socksHost, socksPort); + } + } else if (TextUtils.equals(status, STATUS_STARTS_DISABLED)) { + for (StatusCallback cb : statusCallbacks) + cb.onDisabled(intent); + } + + } + } + }; + + private OrbotHelper() { + + } + + public static OrbotHelper get(OpenVPNService mOpenVPNService) { + if (mInstance == null) + mInstance = new OrbotHelper(); + return mInstance; + } + + /** + * Gets an {@link Intent} for starting Orbot. Orbot will reply with the + * current status to the {@code packageName} of the app in the provided + * {@link Context} (i.e. {@link Context#getPackageName()}. + */ + public static Intent getOrbotStartIntent(Context context) { + Intent intent = new Intent(ACTION_START); + intent.setPackage(ORBOT_PACKAGE_NAME); + intent.putExtra(EXTRA_PACKAGE_NAME, context.getPackageName()); + return intent; + } + + public static boolean checkTorReceier(Context c) { + Intent startOrbot = getOrbotStartIntent(c); + PackageManager pm = c.getPackageManager(); + Intent result = null; + List receivers = + pm.queryBroadcastReceivers(startOrbot, 0); + + return receivers != null && receivers.size() > 0; + } + + /** + * Adds a StatusCallback to be called when we find out that + * Orbot is ready. If Orbot is ready for use, your callback + * will be called with onEnabled() immediately, before this + * method returns. + * + * @param cb a callback + * @return the singleton, for chaining + */ + public synchronized OrbotHelper addStatusCallback(Context c, StatusCallback cb) { + if (statusCallbacks.size() == 0) { + c.getApplicationContext().registerReceiver(orbotStatusReceiver, + new IntentFilter(OrbotHelper.ACTION_STATUS)); + mContext = c.getApplicationContext(); + } + if (!checkTorReceier(c)) + cb.onNotYetInstalled(); + statusCallbacks.add(cb); + return (this); + } + + /** + * Removes an existing registered StatusCallback. + * + * @param cb the callback to remove + * @return the singleton, for chaining + */ + public synchronized void removeStatusCallback(StatusCallback cb) { + statusCallbacks.remove(cb); + if (statusCallbacks.size() == 0) + mContext.unregisterReceiver(orbotStatusReceiver); + } + + public void sendOrbotStartAndStatusBroadcast() { + mContext.sendBroadcast(getOrbotStartIntent(mContext)); + } + + private void startOrbotService(String action) { + Intent clearVPNMode = new Intent(); + clearVPNMode.setComponent(new ComponentName(ORBOT_PACKAGE_NAME, ".service.TorService")); + clearVPNMode.setAction(action); + mContext.startService(clearVPNMode); + } + + public interface StatusCallback { + /** + * Called when Orbot is operational + * + * @param statusIntent an Intent containing information about + * Orbot, including proxy ports + */ + void onStatus(Intent statusIntent); + + + /** + * Called if Orbot is not yet installed. Usually, you handle + * this by checking the return value from init() on OrbotInitializer + * or calling isInstalled() on OrbotInitializer. However, if + * you have need for it, if a callback is registered before + * an init() call determines that Orbot is not installed, your + * callback will be called with onNotYetInstalled(). + */ + void onNotYetInstalled(); + + void onOrbotReady(Intent intent, String socksHost, int socksPort); + + /** + * Called if Orbot background control is disabled. + * @param intent the intent delivered + */ + void onDisabled(Intent intent); + } +} -- cgit v1.2.3