Bug Fixes
|
@ -101,7 +101,7 @@ dependencies {
|
|||
|
||||
implementation "org.mozilla.components:browser-engine-gecko:73.0.8"
|
||||
implementation "org.mozilla.components:browser-icons:73.0.9"
|
||||
implementation "org.mozilla.geckoview:geckoview:80.0.20200903001900"
|
||||
implementation "org.mozilla.geckoview:geckoview:89.0.20210524222230"
|
||||
implementation "org.mozilla.components:concept-fetch:73.0.9"
|
||||
implementation "org.mozilla.components:concept-base:73.0.9"
|
||||
implementation "org.mozilla.components:support-utils:73.0.9"
|
||||
|
|
|
@ -233,10 +233,6 @@
|
|||
android:resource="@xml/provider_paths" />
|
||||
</provider>
|
||||
|
||||
<provider
|
||||
android:authorities="com.darkweb.genesissearchengine.production.provider"
|
||||
android:name="com.darkweb.genesissearchengine.libs.clientauth.ClientAuthContentProvider"
|
||||
android:exported="false"/>
|
||||
-->
|
||||
|
||||
<!-- Permissions File Provider Dev -->
|
||||
|
@ -250,11 +246,27 @@
|
|||
android:resource="@xml/provider_paths" />
|
||||
</provider>
|
||||
|
||||
|
||||
<provider
|
||||
android:authorities="com.darkweb.genesissearchengine.production.provider"
|
||||
android:name="com.darkweb.genesissearchengine.libs.clientauth.ClientAuthContentProvider"
|
||||
android:name="com.darkweb.genesissearchengine.libs.providers.HSContentProvider"
|
||||
android:authorities="org.torproject.android.ui.hiddenservices.providers"
|
||||
android:exported="false" />
|
||||
|
||||
<provider
|
||||
android:name="com.darkweb.genesissearchengine.libs.providers.OnionServiceContentProvider"
|
||||
android:authorities="org.torproject.android.ui.v3onionservice"
|
||||
android:exported="false" />
|
||||
|
||||
<provider
|
||||
android:authorities="org.torproject.android.ui.v3onionservice.clientauth"
|
||||
android:name="com.darkweb.genesissearchengine.libs.providers.ClientAuthContentProviderGenesis"
|
||||
android:exported="false"/>
|
||||
|
||||
<provider
|
||||
android:name="com.darkweb.genesissearchengine.libs.providers.CookieContentProvider"
|
||||
android:authorities="org.torproject.android.ui.hiddenservices.providers.cookie"
|
||||
android:exported="false" />
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.fileprovider"
|
||||
|
@ -266,7 +278,7 @@
|
|||
</provider>
|
||||
|
||||
<service
|
||||
android:name="org.torproject.android.proxy.OrbotService"
|
||||
android:name="org.torproject.android.service.OrbotService"
|
||||
android:enabled="true"
|
||||
android:permission="android.permission.BIND_VPN_SERVICE"
|
||||
android:stopWithTask="false">
|
||||
|
|
|
@ -179,6 +179,16 @@ public class activityContextManager
|
|||
}
|
||||
}
|
||||
|
||||
public void onResetLanguage(){
|
||||
for(int mCounter=0;mCounter<mStackList.size();mCounter++){
|
||||
try{
|
||||
if(!mStackList.get(mCounter).get().isFinishing()){
|
||||
activityThemeManager.getInstance().onConfigurationChanged(mStackList.get(mCounter).get());
|
||||
}
|
||||
}catch (Exception ignored){}
|
||||
}
|
||||
}
|
||||
|
||||
public void onClearStack(){
|
||||
for(int mCounter=0;mCounter<mStackList.size();mCounter++){
|
||||
try{
|
||||
|
|
|
@ -3,17 +3,9 @@ package com.darkweb.genesissearchengine.appManager;
|
|||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
|
||||
import com.darkweb.genesissearchengine.constants.status;
|
||||
import com.darkweb.genesissearchengine.pluginManager.pluginController;
|
||||
import com.darkweb.genesissearchengine.pluginManager.pluginEnums;
|
||||
|
||||
import org.torproject.android.proxy.OrbotService;
|
||||
import org.torproject.android.proxy.wrapper.orbotLocalConstants;
|
||||
|
||||
import java.util.Collections;
|
||||
import org.torproject.android.service.OrbotService;
|
||||
|
||||
public class activityStateManager extends Service {
|
||||
|
||||
|
|
|
@ -10,8 +10,7 @@ import com.darkweb.genesissearchengine.constants.status;
|
|||
import com.darkweb.genesissearchengine.dataManager.dataController;
|
||||
import com.darkweb.genesissearchengine.helperManager.helperMethod;
|
||||
import com.example.myapplication.R;
|
||||
|
||||
import org.torproject.android.proxy.wrapper.orbotLocalConstants;
|
||||
import org.torproject.android.service.wrapper.orbotLocalConstants;
|
||||
|
||||
public class externalShortcutController extends AppCompatActivity {
|
||||
|
||||
|
|
|
@ -119,9 +119,6 @@ public class NestedGeckoView extends GeckoView {
|
|||
mNestedOffsetY += mScrollOffset[1];
|
||||
}
|
||||
|
||||
if(status.sFullScreenBrowsing){
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
|
@ -186,8 +183,10 @@ public class NestedGeckoView extends GeckoView {
|
|||
|
||||
@Override
|
||||
public void stopNestedScroll() {
|
||||
if(mChildHelper !=null){
|
||||
mChildHelper.stopNestedScroll();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNestedScrollingParent() {
|
||||
|
|
|
@ -8,20 +8,24 @@ import android.util.Log;
|
|||
import android.widget.ImageView;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import com.darkweb.genesissearchengine.appManager.activityContextManager;
|
||||
import com.darkweb.genesissearchengine.appManager.homeManager.homeController.homeController;
|
||||
import com.darkweb.genesissearchengine.appManager.kotlinHelperLibraries.BrowserIconManager;
|
||||
import com.darkweb.genesissearchengine.constants.*;
|
||||
import com.darkweb.genesissearchengine.dataManager.dataController;
|
||||
import com.darkweb.genesissearchengine.dataManager.dataEnums;
|
||||
import com.darkweb.genesissearchengine.eventObserver;
|
||||
import com.darkweb.genesissearchengine.helperManager.helperMethod;
|
||||
import com.darkweb.genesissearchengine.pluginManager.pluginController;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.darkweb.genesissearchengine.constants.constants.CONST_GENESIS_URL_CACHED;
|
||||
import static com.darkweb.genesissearchengine.constants.constants.CONST_GENESIS_URL_CACHED_DARK;
|
||||
import static com.darkweb.genesissearchengine.constants.constants.CONST_REPORT_URL;
|
||||
import static com.darkweb.genesissearchengine.constants.enums.etype.on_handle_external_intent;
|
||||
import static com.darkweb.genesissearchengine.pluginManager.pluginEnums.eMessageManager.M_APPLICATION_CRASH;
|
||||
import static org.mozilla.geckoview.GeckoSessionSettings.USER_AGENT_MODE_MOBILE;
|
||||
import static org.mozilla.geckoview.StorageController.ClearFlags.AUTH_SESSIONS;
|
||||
import static org.mozilla.geckoview.StorageController.ClearFlags.COOKIES;
|
||||
|
@ -77,11 +81,8 @@ public class geckoClients
|
|||
if(mStatus){
|
||||
boolean mState = mSession.onRestoreState();
|
||||
if(!mState){
|
||||
new Handler().postDelayed(() ->
|
||||
{
|
||||
mSession.stop();
|
||||
mSession.loadUri(mSession.getCurrentURL());
|
||||
}, 500);
|
||||
loadURL(mSession.getCurrentURL(), mNestedGeckoView, pcontext);
|
||||
}else {
|
||||
String mURL = mSession.getCurrentURL();
|
||||
if(mURL.equals("https://genesishiddentechnologies.com") || mURL.startsWith(CONST_GENESIS_URL_CACHED) || mURL.startsWith(CONST_GENESIS_URL_CACHED_DARK)){
|
||||
|
@ -140,7 +141,6 @@ public class geckoClients
|
|||
if(mRuntime==null){
|
||||
mRuntime = GeckoRuntime.getDefault(context.getApplicationContext());
|
||||
mRuntime.getSettings().setAboutConfigEnabled(true);
|
||||
mRuntime.getSettings().setAboutConfigEnabled(true);
|
||||
mRuntime.getSettings().setAutomaticFontSizeAdjustment(false);
|
||||
mRuntime.getSettings().setWebFontsEnabled(status.sShowWebFonts);
|
||||
mRuntime.getSettings().setForceUserScalableEnabled(status.sSettingEnableZoom);
|
||||
|
@ -202,8 +202,10 @@ public class geckoClients
|
|||
public String getTheme(){
|
||||
if(mSessionID.equals(strings.GENERIC_EMPTY_STR)){
|
||||
return null;
|
||||
}else {
|
||||
}else if(mSession!=null && mSession.getTheme()!=null){
|
||||
return mSession.getTheme();
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -242,6 +244,8 @@ public class geckoClients
|
|||
String mURL = constants.CONST_GENESIS_URL_CACHED + "?pData="+ dataController.getInstance().invokeReferenceWebsite(dataEnums.eReferenceWebsiteCommands.M_FETCH,null);
|
||||
mSession.getSettings().setAllowJavascript(true);
|
||||
mSession.initURL(mURL);
|
||||
|
||||
mSession.stop();
|
||||
mSession.loadUri(mURL);
|
||||
}else {
|
||||
String mURL = constants.CONST_GENESIS_URL_CACHED_DARK + "?pData="+ dataController.getInstance().invokeReferenceWebsite(dataEnums.eReferenceWebsiteCommands.M_FETCH,null);
|
||||
|
|
|
@ -50,7 +50,7 @@ import org.mozilla.geckoview.GeckoView;
|
|||
import org.mozilla.geckoview.SlowScriptResponse;
|
||||
import org.mozilla.geckoview.WebRequestError;
|
||||
import org.mozilla.geckoview.WebResponse;
|
||||
import org.torproject.android.proxy.wrapper.orbotLocalConstants;
|
||||
import org.torproject.android.service.wrapper.orbotLocalConstants;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
@ -72,6 +72,7 @@ import static com.darkweb.genesissearchengine.constants.constants.CONST_GENESIS_
|
|||
import static com.darkweb.genesissearchengine.constants.constants.CONST_GENESIS_HELP_URL_CACHE_DARK;
|
||||
import static com.darkweb.genesissearchengine.constants.constants.CONST_GENESIS_URL_CACHED;
|
||||
import static com.darkweb.genesissearchengine.constants.constants.CONST_GENESIS_URL_CACHED_DARK;
|
||||
import static com.darkweb.genesissearchengine.constants.enums.etype.M_DEFAULT_BROWSER;
|
||||
import static com.darkweb.genesissearchengine.constants.enums.etype.M_RATE_COUNT;
|
||||
import static com.darkweb.genesissearchengine.pluginManager.pluginEnums.eMessageManager.M_LONG_PRESS_URL;
|
||||
import static com.darkweb.genesissearchengine.pluginManager.pluginEnums.eMessageManager.M_LONG_PRESS_WITH_LINK;
|
||||
|
@ -102,6 +103,7 @@ geckoSession extends GeckoSession implements GeckoSession.MediaDelegate,GeckoSes
|
|||
private boolean mRemovableFromBackPressed = false;
|
||||
private boolean mThemeChanged = false;
|
||||
private int mScollOffset = 0;
|
||||
private selectionActionDelegate mSelectionActionDelegate;
|
||||
|
||||
/*Temp Variables*/
|
||||
private GeckoSession.HistoryDelegate.HistoryList mHistoryList = null;
|
||||
|
@ -131,8 +133,9 @@ geckoSession extends GeckoSession implements GeckoSession.MediaDelegate,GeckoSes
|
|||
setPermissionDelegate(this);
|
||||
setScrollDelegate(this);
|
||||
mDownloadManager = new geckoDownloadManager();
|
||||
mSelectionActionDelegate = new selectionActionDelegate(mContext, true);
|
||||
setPromptDelegate(new geckoPromptView(mContext));
|
||||
setSelectionActionDelegate(new selectionActionDelegate(mContext, true));
|
||||
setSelectionActionDelegate(mSelectionActionDelegate);
|
||||
}
|
||||
|
||||
public void onDestroy(){
|
||||
|
@ -358,6 +361,9 @@ geckoSession extends GeckoSession implements GeckoSession.MediaDelegate,GeckoSes
|
|||
mContext.get().runOnUiThread(() -> event.invokeObserver(Arrays.asList(5,mSessionID), enums.etype.progress_update));
|
||||
}else {
|
||||
if(progress==100){
|
||||
if(!mCurrentURL.contains("genesis")){
|
||||
checkApplicationRate();
|
||||
}
|
||||
if(!mIsProgressBarChanging){
|
||||
mIsProgressBarChanging = true;
|
||||
mContext.get().runOnUiThread(() -> event.invokeObserver(Arrays.asList(mProgress,mSessionID), enums.etype.progress_update));
|
||||
|
@ -529,7 +535,6 @@ geckoSession extends GeckoSession implements GeckoSession.MediaDelegate,GeckoSes
|
|||
|
||||
event.invokeObserver(Arrays.asList(var1.uri,mSessionID), enums.etype.start_proxy);
|
||||
event.invokeObserver(Arrays.asList(mCurrentURL,mSessionID), enums.etype.search_update);
|
||||
checkApplicationRate();
|
||||
|
||||
/* Its Absence causes delay on first launch*/
|
||||
|
||||
|
@ -732,6 +737,7 @@ geckoSession extends GeckoSession implements GeckoSession.MediaDelegate,GeckoSes
|
|||
@Override
|
||||
public void onFullScreen(@NonNull GeckoSession var1, boolean var2) {
|
||||
mFullScreen = var2;
|
||||
mSelectionActionDelegate.setFullScreen(mFullScreen);
|
||||
event.invokeObserver(Arrays.asList(var2,mSessionID), enums.etype.on_full_screen);
|
||||
}
|
||||
|
||||
|
@ -1105,10 +1111,15 @@ geckoSession extends GeckoSession implements GeckoSession.MediaDelegate,GeckoSes
|
|||
|
||||
private void checkApplicationRate(){
|
||||
if(status.sSettingIsAppStarted){
|
||||
if(status.sRateCount==10){
|
||||
if(status.sGlobalURLCount == 10){
|
||||
event.invokeObserver(Arrays.asList(mCurrentURL,mSessionID,mCurrentTitle, mTheme), M_RATE_APPLICATION);
|
||||
}
|
||||
status.sRateCount+=1;
|
||||
|
||||
else if(status.sGlobalURLCount == 20 || status.sGlobalURLCount == 80){
|
||||
event.invokeObserver(Arrays.asList(mCurrentURL,mSessionID,mCurrentTitle, mTheme), M_DEFAULT_BROWSER);
|
||||
}
|
||||
|
||||
status.sGlobalURLCount +=1;
|
||||
event.invokeObserver(Arrays.asList(mCurrentURL,mSessionID,mCurrentTitle, mTheme), M_RATE_COUNT);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,9 @@ package com.darkweb.genesissearchengine.appManager.homeManager.geckoManager;
|
|||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Matrix;
|
||||
|
@ -56,6 +59,7 @@ public class selectionActionDelegate implements ActionMode.Callback,
|
|||
protected final boolean mUseFloatingToolbar;
|
||||
protected final @NonNull Matrix mTempMatrix = new Matrix();
|
||||
protected final @NonNull RectF mTempRect = new RectF();
|
||||
private boolean mFullScreen = false;
|
||||
|
||||
private boolean mExternalActionsEnabled;
|
||||
|
||||
|
@ -64,6 +68,10 @@ public class selectionActionDelegate implements ActionMode.Callback,
|
|||
protected @Nullable Selection mSelection;
|
||||
protected boolean mRepopulatedMenu;
|
||||
|
||||
public void setFullScreen(boolean pFullScreen){
|
||||
mFullScreen = pFullScreen;
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.M)
|
||||
private class Callback2Wrapper extends ActionMode.Callback2 {
|
||||
@Override
|
||||
|
@ -148,7 +156,7 @@ public class selectionActionDelegate implements ActionMode.Callback,
|
|||
* @return True if the action is presently available.
|
||||
*/
|
||||
protected boolean isActionAvailable(final @NonNull String id) {
|
||||
if (mSelection == null) {
|
||||
if (mSelection == null || mSelection.text.toString().length()<1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -189,6 +197,9 @@ public class selectionActionDelegate implements ActionMode.Callback,
|
|||
*/
|
||||
protected void prepareAction(final @NonNull String id, final @NonNull MenuItem item) {
|
||||
|
||||
if(mFullScreen){
|
||||
return;
|
||||
}
|
||||
switch (id) {
|
||||
case ACTION_CUT:
|
||||
item.setTitle(android.R.string.cut);
|
||||
|
|
|
@ -28,6 +28,7 @@ import com.example.myapplication.R;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -227,11 +228,14 @@ public class hintAdapter extends RecyclerView.Adapter<hintAdapter.listViewHolder
|
|||
@SuppressLint("ClickableViewAccessibility")
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
if(v.getId() == mpHintListener.getId() || v.getId() == mMoveURL.getId()){
|
||||
if(v.getId() == mpHintListener.getId()){
|
||||
if(event.getAction() == MotionEvent.ACTION_MOVE){
|
||||
helperMethod.hideKeyboard(mContext);
|
||||
}
|
||||
}
|
||||
else if(v.getId() == mMoveURL.getId()){
|
||||
mEvent.invokeObserver(Collections.singletonList(mMoveURL.getTag()), enums.etype.M_COPY_URL);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package com.darkweb.genesissearchengine.appManager.homeManager.homeController;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.text.Spanned;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
|
@ -25,6 +29,41 @@ public class editTextManager extends androidx.appcompat.widget.AppCompatAutoCom
|
|||
mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTextContextMenuItem(int id) {
|
||||
if (id == android.R.id.paste) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
id = android.R.id.pasteAsPlainText;
|
||||
} else {
|
||||
onInterceptClipDataToPlainText();
|
||||
}
|
||||
}
|
||||
return super.onTextContextMenuItem(id);
|
||||
}
|
||||
|
||||
private void onInterceptClipDataToPlainText() {
|
||||
ClipboardManager clipboard = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
ClipData clip = clipboard.getPrimaryClip();
|
||||
if (clip != null) {
|
||||
for (int i = 0; i < clip.getItemCount(); i++) {
|
||||
final CharSequence paste;
|
||||
// Get an item as text and remove all spans by toString().
|
||||
final CharSequence text = clip.getItemAt(i).coerceToText(getContext());
|
||||
paste = (text instanceof Spanned) ? text.toString() : text;
|
||||
if (paste != null) {
|
||||
copyToClipBoard(getContext(), paste);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void copyToClipBoard(@NonNull Context context, @NonNull CharSequence text) {
|
||||
ClipData clipData = ClipData.newPlainText("rebase_copy", text);
|
||||
ClipboardManager manager = (ClipboardManager) context
|
||||
.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
manager.setPrimaryClip(clipData);
|
||||
}
|
||||
|
||||
public editTextManager(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mContext = context;
|
||||
|
|
|
@ -2,7 +2,6 @@ package com.darkweb.genesissearchengine.appManager.homeManager.homeController;
|
|||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.DownloadManager;
|
||||
import android.app.Notification;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentCallbacks2;
|
||||
|
@ -11,6 +10,7 @@ import android.content.Intent;
|
|||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
|
@ -78,10 +78,10 @@ import com.google.android.gms.ads.AdView;
|
|||
import org.mozilla.geckoview.ContentBlocking;
|
||||
import org.mozilla.geckoview.GeckoResult;
|
||||
import org.mozilla.geckoview.GeckoSession;
|
||||
import org.torproject.android.proxy.OrbotService;
|
||||
import org.torproject.android.proxy.util.Prefs;
|
||||
import org.torproject.android.proxy.wrapper.LocaleHelper;
|
||||
import org.torproject.android.proxy.wrapper.orbotLocalConstants;
|
||||
import org.torproject.android.service.OrbotService;
|
||||
import org.torproject.android.service.util.Prefs;
|
||||
import org.torproject.android.service.wrapper.LocaleHelper;
|
||||
import org.torproject.android.service.wrapper.orbotLocalConstants;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Field;
|
||||
|
@ -197,6 +197,9 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
dataController.getInstance().invokeSQLCipher(dataEnums.eSqlCipherCommands.M_INIT, Collections.singletonList(this));
|
||||
trueTime.getInstance().initTime();
|
||||
|
||||
helperMethod.updateResources(this, status.mSystemLocale.getLanguage());
|
||||
pluginController.getInstance().onLanguageInvoke(Collections.singletonList(this), pluginEnums.eLangManager.M_ACTIVITY_CREATED);
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.home_view);
|
||||
|
||||
|
@ -734,8 +737,6 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
super.onDestroy();
|
||||
return;
|
||||
}
|
||||
mBackSplash.setImageDrawable(null);
|
||||
mBackSplash.setBackground(null);
|
||||
|
||||
if(!status.mThemeApplying){
|
||||
if(!status.sSettingIsAppStarted){
|
||||
|
@ -746,32 +747,8 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
}
|
||||
}
|
||||
|
||||
KeyboardUtils.removeAllKeyboardToggleListeners();
|
||||
mGatewaySplash.setOnTouchListener(null);
|
||||
|
||||
((ConstraintLayout)mGatewaySplash.getParent()).removeView(mGatewaySplash);
|
||||
((ConstraintLayout)mGeckoView.getParent()).removeView(mGeckoView);
|
||||
((ConstraintLayout)mTabFragment.getParent()).removeView(mTabFragment);
|
||||
((LinearLayout)mSearchbar.getParent()).removeView(mSearchbar);
|
||||
|
||||
mTabFragment = null;
|
||||
mNestedScroll = null;
|
||||
mGeckoView.setOnFocusChangeListener(null);
|
||||
mGeckoView.setOnTouchListener(null);
|
||||
mGeckoView.destroyDrawingCache();
|
||||
mGeckoView.releaseSession();
|
||||
mGeckoClient.onDestroy();
|
||||
|
||||
mGeckoView.onDestroy();
|
||||
mGeckoClient=null;
|
||||
mHomeViewController = null;
|
||||
activityContextManager.getInstance().setHomeController(null);
|
||||
mGeckoView.releaseSession();
|
||||
mGeckoView = null;
|
||||
|
||||
activityContextManager.getInstance().setHomeController(null);
|
||||
activityContextManager.getInstance().setCurrentActivity(null);
|
||||
pluginController.getInstance().onRemoveInstances();
|
||||
// mGeckoClient.onDestroy();
|
||||
// mGeckoView.onDestroy();
|
||||
|
||||
unregisterReceiver(downloadStatus);
|
||||
|
||||
|
@ -807,8 +784,8 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start,int before, int count) {
|
||||
if(!mSearchbar.isFocused()){
|
||||
if(mFindText.getText().length()==0 && mGeckoClient!=null){
|
||||
if(!mSearchbar.isFocused() && !status.mThemeApplying && mGeckoClient.getSession()!=null){
|
||||
if(mFindText.getText().length()==0 && mGeckoClient!=null && mGeckoClient.getSession()!=null){
|
||||
mGeckoClient.getSession().getFinder().clear();
|
||||
mHomeViewController.onUpdateFindBarCount(0,0);
|
||||
}else if(mGeckoClient!=null){
|
||||
|
@ -1394,6 +1371,9 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
mHomeViewController.onUpdateFindBar(false);
|
||||
mHomeViewController.onClearSelections(isKeyboardOpened);
|
||||
mTopBarContainer.getLayoutTransition().setDuration(0);
|
||||
|
||||
mSearchbar.clearFocus();
|
||||
mHomeViewController.onUpdateSearchBar(mGeckoClient.getSession().getCurrentURL(),false,false, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1583,9 +1563,12 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
}
|
||||
|
||||
public void onStartApplication(View view){
|
||||
mHomeViewController.initHomePage();
|
||||
new Handler().postDelayed(() ->
|
||||
{
|
||||
pluginController.getInstance().onOrbotInvoke(Arrays.asList(status.sBridgeCustomBridge, status.sBridgeGatewayManual, status.sBridgeCustomType, status.sBridgeStatus, status.sShowImages, status.sClearOnExit, (String)dataController.getInstance().invokeBridges(dataEnums.eBridgeWebsiteCommands.M_FETCH, null)), pluginEnums.eOrbotManager.M_START_ORBOT);
|
||||
onInvokeProxyLoading();
|
||||
mHomeViewController.initHomePage();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
public void onDownloadFile(){
|
||||
|
@ -1895,7 +1878,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_INT, Arrays.asList(keys.SETTING_SHOW_IMAGES,0));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_SHOW_FONTS,true));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_TOOLBAR_THEME,true));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_FULL_SCREEN_BROWSIING,true));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_FULL_SCREEN_BROWSIING,false));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_INT, Arrays.asList(keys.SETTING_THEME, enums.Theme.THEME_DEFAULT));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_LIST_VIEW,true));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_SHOW_TAB_GRID,true));
|
||||
|
@ -1946,9 +1929,6 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
mHomeViewController.onClearSelections(isKeyboardOpened);
|
||||
mSearchbar.clearFocus();
|
||||
}
|
||||
else if(e_type.equals(GECKO_SCROLL_DOWN_MOVE)){
|
||||
mAppBar.setExpanded(true,false);
|
||||
}
|
||||
else if(e_type.equals(GECKO_SCROLL_UP_MOVE)){
|
||||
mAppBar.setExpanded(false,false);
|
||||
}
|
||||
|
@ -1960,8 +1940,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
mAppBar.getLocalVisibleRect(rectf);
|
||||
int height = mAppBar.getHeight();
|
||||
|
||||
Log.i("asddasas","asdasd : " + rectf.top + " : " + height);
|
||||
if(rectf.top!=0 && rectf.top + height!=0)
|
||||
if(rectf.top>0 && rectf.top + height!=0){
|
||||
if(rectf.top<=height/2){
|
||||
mHomeViewController.expandTopBar(true, mGeckoView.getMaxY());
|
||||
}else {
|
||||
|
@ -1969,6 +1948,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -2160,10 +2140,27 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
if(e_type.equals(enums.etype.fetch_favicon)){
|
||||
mGeckoClient.onGetFavIcon((ImageView) data.get(0), (String) data.get(1), homeController.this);
|
||||
}
|
||||
else if(e_type.equals(enums.etype.M_COPY_URL)){
|
||||
mHomeViewController.onUpdateSearchBar((String) data.get(0), true, true, false);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean updateResources(Context context, String language) {
|
||||
Locale locale = new Locale(language);
|
||||
Locale.setDefault(locale);
|
||||
|
||||
Resources resources = context.getResources();
|
||||
|
||||
Configuration configuration = resources.getConfiguration();
|
||||
configuration.locale = locale;
|
||||
|
||||
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void onDisableAdvert(){
|
||||
mHomeViewController.updateBannerAdvertStatus(false, true);
|
||||
}
|
||||
|
@ -2198,7 +2195,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
}catch (Exception ignored){}
|
||||
new Handler().postDelayed(() ->
|
||||
{
|
||||
if(mTabFragment!=null){
|
||||
if(mTabFragment!=null && mGeckoClient.getSession()!=null){
|
||||
if(mTabFragment.getVisibility()!=View.VISIBLE){
|
||||
dataController.getInstance().invokeTab(dataEnums.eTabCommands.M_UPDATE_PIXEL, Arrays.asList(mGeckoClient.getSession().getSessionID(), mRenderedBitmap, null, mGeckoView, true));
|
||||
}else {
|
||||
|
@ -2367,11 +2364,16 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
mHomeViewController.initTopBarPadding();
|
||||
}
|
||||
else if(e_type.equals(enums.etype.M_RATE_COUNT)){
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_INT, Arrays.asList(keys.SETTING_RATE_COUNT, status.sRateCount));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_INT, Arrays.asList(keys.SETTING_RATE_COUNT, status.sGlobalURLCount));
|
||||
}
|
||||
else if(e_type.equals(enums.etype.M_ORBOT_LOADING)){
|
||||
pluginController.getInstance().onMessageManagerInvoke(Collections.singletonList(homeController.this), M_ORBOT_LOADING);
|
||||
}
|
||||
else if(e_type.equals(enums.etype.M_DEFAULT_BROWSER)){
|
||||
if(helperMethod.isDefaultBrowserSet(homeController.this)){
|
||||
helperMethod.openDefaultBrowser(homeController.this);
|
||||
}
|
||||
}
|
||||
else if(e_type.equals(enums.etype.M_NEW_IDENTITY)){
|
||||
pluginController.getInstance().onOrbotInvoke(null, pluginEnums.eOrbotManager.M_NEW_CIRCUIT);
|
||||
}
|
||||
|
|
|
@ -47,8 +47,11 @@ import com.darkweb.genesissearchengine.helperManager.helperMethod;
|
|||
import com.example.myapplication.R;
|
||||
import com.google.android.gms.ads.AdView;
|
||||
import com.google.android.material.appbar.AppBarLayout;
|
||||
import com.google.android.material.appbar.CollapsingToolbarLayout;
|
||||
|
||||
import org.mozilla.geckoview.GeckoView;
|
||||
import org.torproject.android.proxy.wrapper.orbotLocalConstants;
|
||||
import org.torproject.android.service.wrapper.orbotLocalConstants;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -164,6 +167,8 @@ class homeViewController
|
|||
recreateStatusBar();
|
||||
initTopBarPadding();
|
||||
initializeViews();
|
||||
stopScroll();
|
||||
onFullScreen();
|
||||
}
|
||||
|
||||
@SuppressLint("WrongConstant")
|
||||
|
@ -227,6 +232,7 @@ class homeViewController
|
|||
View child = mAppBar.getChildAt(0);
|
||||
AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) child.getLayoutParams();
|
||||
params.setScrollFlags(0);
|
||||
onFullScreen();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -237,7 +243,7 @@ class homeViewController
|
|||
View child = mAppBar.getChildAt(0);
|
||||
AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) child.getLayoutParams();
|
||||
params.setScrollFlags(0);
|
||||
|
||||
onFullScreen();
|
||||
}else {
|
||||
int paddingDp = 0;
|
||||
if(isFullScreen){
|
||||
|
@ -250,6 +256,7 @@ class homeViewController
|
|||
View child = mAppBar.getChildAt(0);
|
||||
AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) child.getLayoutParams();
|
||||
params.setScrollFlags(1);
|
||||
onFullScreen();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -496,11 +503,13 @@ class homeViewController
|
|||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
ColorAnimator oneToTwo = new ColorAnimator(ContextCompat.getColor(mContext, R.color.landing_ease_blue), ContextCompat.getColor(mContext, R.color.green_dark_v2));
|
||||
|
||||
int mDelay = 500;
|
||||
int mDelay = 1250;
|
||||
if(status.mThemeApplying || mInstant){
|
||||
mDelay = 0;
|
||||
}
|
||||
|
||||
Log.i("asdadsshadkkasjd","asdasdasd");
|
||||
|
||||
ValueAnimator animator = ObjectAnimator.ofFloat(0f, 1f);
|
||||
animator.setDuration(250).setStartDelay(mDelay);
|
||||
animator.addUpdateListener(animation ->
|
||||
|
@ -531,16 +540,17 @@ class homeViewController
|
|||
});
|
||||
animator.start();
|
||||
}else {
|
||||
mContext.getWindow().setStatusBarColor(ContextCompat.getColor(mContext, R.color.c_background));
|
||||
mSplashScreen.animate().alpha(0).setDuration(250).setStartDelay(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void initSplashLoading(){
|
||||
|
||||
mLoadingText.setAlpha(0);
|
||||
mLoadingText.setVisibility(View.VISIBLE);
|
||||
mLoadingText.animate().setStartDelay(0).alpha(1);
|
||||
if(mLoadingText.getAlpha()==0){
|
||||
Log.i("sadads111","asdasdasd");
|
||||
mLoadingText.animate().setStartDelay(0).setDuration(250).alpha(1);
|
||||
}
|
||||
|
||||
mProgressBarIndeterminate.setVisibility(View.VISIBLE);
|
||||
mProgressBarIndeterminate.animate().alpha(1);
|
||||
|
@ -615,7 +625,7 @@ class homeViewController
|
|||
}
|
||||
}
|
||||
|
||||
sleep(1500);
|
||||
sleep(500);
|
||||
if(mFastConnect){
|
||||
continue;
|
||||
}
|
||||
|
@ -632,10 +642,10 @@ class homeViewController
|
|||
}
|
||||
}
|
||||
if(!status.sSettingIsAppStarted){
|
||||
startPostTask(messages.MESSAGE_ON_URL_LOAD);
|
||||
mContext.runOnUiThread(() -> {
|
||||
splashScreenDisable();
|
||||
});
|
||||
startPostTask(messages.MESSAGE_ON_URL_LOAD);
|
||||
}else {
|
||||
mContext.runOnUiThread(() -> {
|
||||
mEvent.invokeObserver(null, enums.etype.ON_LOAD_TAB_ON_RESUME);
|
||||
|
@ -655,6 +665,9 @@ class homeViewController
|
|||
splashScreenDisable();
|
||||
}
|
||||
|
||||
public void stopScroll() {
|
||||
}
|
||||
|
||||
public void splashScreenDisableInstant() {
|
||||
mSplashScreen.setAlpha(0f);
|
||||
mSplashScreen.setVisibility(View.GONE);
|
||||
|
@ -669,18 +682,11 @@ class homeViewController
|
|||
if(mSplashScreen.getAlpha()==1){
|
||||
if(!mIsAnimating){
|
||||
mIsAnimating = true;
|
||||
triggerPostUI(2000);
|
||||
mProgressBar.setVisibility(View.GONE);
|
||||
mSplashScreen.animate().cancel();
|
||||
onClearSelections(false);
|
||||
mGeckoView.requestFocus();
|
||||
mProgressBarIndeterminate.animate().cancel();
|
||||
mProgressBarIndeterminate.animate().setStartDelay(350).setDuration(250).alpha(0).withEndAction(() -> {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
initStatusBarColor(false);
|
||||
}
|
||||
mProgressBarIndeterminate.animate().setStartDelay(350).setDuration(250).alpha(0).withEndAction(() -> {
|
||||
|
||||
mSplashScreen.animate().setDuration(0).setStartDelay(1000).alpha(0).withEndAction(() -> {
|
||||
new Handler().postDelayed(() ->
|
||||
{
|
||||
mProgressBarIndeterminate.setVisibility(View.GONE);
|
||||
mSplashScreen.setClickable(false);
|
||||
mSplashScreen.setFocusable(false);
|
||||
|
@ -695,7 +701,8 @@ class homeViewController
|
|||
|
||||
mEvent.invokeObserver(null, enums.etype.M_CACHE_UPDATE_TAB);
|
||||
mEvent.invokeObserver(null, enums.etype.M_SPLASH_DISABLE);
|
||||
});
|
||||
}, 2000);
|
||||
|
||||
});
|
||||
mEvent.invokeObserver(null, enums.etype.M_WELCOME_MESSAGE);
|
||||
mOrbotLogManager.setClickable(false);
|
||||
|
@ -1446,7 +1453,7 @@ class homeViewController
|
|||
params.setMargins(0, 0, 0,0);
|
||||
mNestedScroll.setLayoutParams(params);
|
||||
|
||||
com.darkweb.genesissearchengine.constants.status.sFullScreenBrowsing = (boolean) dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_GET_BOOL, Arrays.asList(keys.SETTING_FULL_SCREEN_BROWSIING,true));
|
||||
com.darkweb.genesissearchengine.constants.status.sFullScreenBrowsing = (boolean) dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_GET_BOOL, Arrays.asList(keys.SETTING_FULL_SCREEN_BROWSIING,false));
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
if(status.sTheme == enums.Theme.THEME_DARK || status.sDefaultNightMode){
|
||||
|
@ -1470,6 +1477,15 @@ class homeViewController
|
|||
|
||||
}
|
||||
|
||||
public void onFullScreen(){
|
||||
if(status.sFullScreenBrowsing || isFullScreen){
|
||||
mWebviewContainer.setPadding(0,0,0,0);
|
||||
}
|
||||
else {
|
||||
mWebviewContainer.setPadding(0,0,0,helperMethod.pxFromDp(60));
|
||||
}
|
||||
}
|
||||
|
||||
void onReDraw(){
|
||||
if(mWebviewContainer.getPaddingBottom()==0){
|
||||
mWebviewContainer.setPadding(0,0,0,1);
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
package com.darkweb.genesissearchengine.appManager.kotlinHelperLibraries
|
||||
|
||||
import android.app.Activity
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import android.app.role.RoleManager
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.provider.Settings
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.os.bundleOf
|
||||
|
||||
class defaultBrowser {
|
||||
fun Activity.enterToImmersiveMode() {
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
@Suppress("DEPRECATION")
|
||||
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
||||
or View.SYSTEM_UI_FLAG_FULLSCREEN
|
||||
or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
|
||||
}
|
||||
|
||||
fun Activity.getabcEnabledValue(): Boolean {
|
||||
when {
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> {
|
||||
getSystemService(RoleManager::class.java).also {
|
||||
if (it.isRoleAvailable(RoleManager.ROLE_BROWSER) && !it.isRoleHeld(
|
||||
RoleManager.ROLE_BROWSER
|
||||
)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.N -> {
|
||||
navigateToDefaultBrowserAppsSettings()
|
||||
}
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fun Activity.openSetDefaultBrowserOption() {
|
||||
when {
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> {
|
||||
getSystemService(RoleManager::class.java).also {
|
||||
if (it.isRoleAvailable(RoleManager.ROLE_BROWSER) && !it.isRoleHeld(
|
||||
RoleManager.ROLE_BROWSER
|
||||
)
|
||||
) {
|
||||
startActivityForResult(
|
||||
it.createRequestRoleIntent(RoleManager.ROLE_BROWSER),
|
||||
REQUEST_CODE_BROWSER_ROLE
|
||||
)
|
||||
} else {
|
||||
navigateToDefaultBrowserAppsSettings()
|
||||
}
|
||||
}
|
||||
}
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.N -> {
|
||||
navigateToDefaultBrowserAppsSettings()
|
||||
}
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Activity.navigateToDefaultBrowserAppsSettings() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
val intent = Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS)
|
||||
intent.putExtra(
|
||||
SETTINGS_SELECT_OPTION_KEY,
|
||||
DEFAULT_BROWSER_APP_OPTION
|
||||
)
|
||||
intent.putExtra(
|
||||
SETTINGS_SHOW_FRAGMENT_ARGS,
|
||||
bundleOf(SETTINGS_SELECT_OPTION_KEY to DEFAULT_BROWSER_APP_OPTION)
|
||||
)
|
||||
startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the icon for the back (up) navigation button.
|
||||
* @param icon The resource id of the icon.
|
||||
*/
|
||||
fun Activity.setNavigationIcon(
|
||||
@DrawableRes icon: Int
|
||||
) {
|
||||
(this as? AppCompatActivity)?.supportActionBar?.let {
|
||||
it.setDisplayHomeAsUpEnabled(true)
|
||||
it.setHomeAsUpIndicator(icon)
|
||||
it.setHomeActionContentDescription("Set Default Browser")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
const val REQUEST_CODE_BROWSER_ROLE = 1
|
||||
const val SETTINGS_SELECT_OPTION_KEY = ":settings:fragment_args_key"
|
||||
const val SETTINGS_SHOW_FRAGMENT_ARGS = ":settings:show_fragment_args"
|
||||
const val DEFAULT_BROWSER_APP_OPTION = "default_browser"
|
|
@ -1,5 +1,6 @@
|
|||
package com.darkweb.genesissearchengine.appManager.languageManager;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
|
@ -44,6 +45,8 @@ public class languageController extends AppCompatActivity {
|
|||
private languageViewController mLanguageViewController;
|
||||
private languageModel mLanguageModel;
|
||||
private ImageView mBlocker;
|
||||
private boolean mThemeApplied = false;
|
||||
private Locale mLanguagePrevious = status.mSystemLocale;
|
||||
|
||||
private RecyclerView mRecycleView;
|
||||
private languageAdapter mLanguageAdapter;
|
||||
|
@ -113,6 +116,7 @@ public class languageController extends AppCompatActivity {
|
|||
mRecycleView.scrollToPosition(mPosition);
|
||||
}else {
|
||||
int mPositionOffset = getIntent().getExtras().getInt("activity_restarted");
|
||||
mThemeApplied = true;
|
||||
Objects.requireNonNull(mRecycleView.getLayoutManager()).scrollToPosition(mPositionOffset);
|
||||
}
|
||||
}
|
||||
|
@ -149,12 +153,6 @@ public class languageController extends AppCompatActivity {
|
|||
}
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_STRING, Arrays.asList(keys.SETTING_LANGUAGE,status.sSettingLanguage));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_STRING, Arrays.asList(keys.SETTING_LANGUAGE_REGION,status.sSettingLanguageRegion));
|
||||
finish();
|
||||
|
||||
getIntent().putExtra("activity_restarted",((LinearLayoutManager) Objects.requireNonNull(mRecycleView.getLayoutManager())).findFirstCompletelyVisibleItemPosition());
|
||||
helperMethod.restartActivity(getIntent(), this);
|
||||
overridePendingTransition(R.anim.fade_in_lang, R.anim.fade_out_lang);
|
||||
pluginController.getInstance().onLanguageInvoke(Arrays.asList(this, status.sSettingLanguage, status.sSettingLanguageRegion, status.mThemeApplying), pluginEnums.eLangManager.M_SET_LANGUAGE);
|
||||
|
||||
if(activityContextManager.getInstance().getSettingController()!=null && !activityContextManager.getInstance().getSettingController().isDestroyed()){
|
||||
activityContextManager.getInstance().getSettingController().onRedrawXML();
|
||||
|
@ -168,10 +166,14 @@ public class languageController extends AppCompatActivity {
|
|||
}
|
||||
|
||||
status.mThemeApplying = true;
|
||||
activityContextManager.getInstance().getHomeController().recreate();
|
||||
if(activityContextManager.getInstance().getSettingGeneralController()!=null){
|
||||
activityContextManager.getInstance().getSettingGeneralController().recreate();
|
||||
}
|
||||
mThemeApplied = true;
|
||||
|
||||
Intent intent = new Intent(this, languageController.class);
|
||||
intent.putExtra("activity_restarted",((LinearLayoutManager) Objects.requireNonNull(mRecycleView.getLayoutManager())).findFirstCompletelyVisibleItemPosition());
|
||||
this.startActivity(intent);
|
||||
|
||||
overridePendingTransition(R.anim.fade_in_lang, R.anim.fade_out_lang);
|
||||
this.finish();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -226,6 +228,22 @@ public class languageController extends AppCompatActivity {
|
|||
super.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
if(mThemeApplied && !status.mThemeApplying){
|
||||
helperMethod.updateResources(activityContextManager.getInstance().getHomeController(), status.mSystemLocale.getLanguage());
|
||||
activityContextManager.getInstance().onResetTheme();
|
||||
|
||||
String mSystemLangugage = status.mSystemLocale.toString();
|
||||
if(mSystemLangugage.equals("ur_PK") || mSystemLangugage.equals("ur_UR") || mLanguagePrevious.toString().equals("ur_PK") || mLanguagePrevious.toString().equals("ur_UR")){
|
||||
activityContextManager.getInstance().getHomeController().recreate();
|
||||
}
|
||||
mLanguagePrevious = status.mSystemLocale;
|
||||
}
|
||||
status.mThemeApplying = false;
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
onClose(null);
|
||||
|
|
|
@ -15,7 +15,9 @@ import com.darkweb.genesissearchengine.appManager.tabManager.tabEnums;
|
|||
import com.darkweb.genesissearchengine.constants.constants;
|
||||
import com.darkweb.genesissearchengine.eventObserver;
|
||||
import com.example.myapplication.R;
|
||||
import org.torproject.android.proxy.wrapper.logRowModel;
|
||||
|
||||
import org.torproject.android.service.wrapper.logRowModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
|
|
@ -28,8 +28,9 @@ import com.darkweb.genesissearchengine.pluginManager.pluginEnums;
|
|||
import com.example.myapplication.R;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
|
||||
import org.torproject.android.proxy.wrapper.logRowModel;
|
||||
import org.torproject.android.proxy.wrapper.orbotLocalConstants;
|
||||
|
||||
import org.torproject.android.service.wrapper.logRowModel;
|
||||
import org.torproject.android.service.wrapper.orbotLocalConstants;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
|
|
@ -2,7 +2,8 @@ package com.darkweb.genesissearchengine.appManager.orbotLogManager;
|
|||
|
||||
import com.darkweb.genesissearchengine.constants.constants;
|
||||
import com.darkweb.genesissearchengine.helperManager.helperMethod;
|
||||
import org.torproject.android.proxy.wrapper.logRowModel;
|
||||
import org.torproject.android.service.wrapper.logRowModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
|
|
@ -209,7 +209,7 @@ public class settingClearController extends AppCompatActivity {
|
|||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_INT, Arrays.asList(keys.SETTING_SHOW_IMAGES,0));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_SHOW_FONTS,true));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_TOOLBAR_THEME,true));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_FULL_SCREEN_BROWSIING,true));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_FULL_SCREEN_BROWSIING,false));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_INT, Arrays.asList(keys.SETTING_THEME, enums.Theme.THEME_DEFAULT));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_LIST_VIEW,true));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_SHOW_TAB_GRID,true));
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package com.darkweb.genesissearchengine.appManager.settingManager.generalManager;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.RadioButton;
|
||||
|
@ -27,6 +29,7 @@ import com.google.android.material.switchmaterial.SwitchMaterial;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class settingGeneralController extends AppCompatActivity {
|
||||
|
||||
|
@ -70,6 +73,7 @@ public class settingGeneralController extends AppCompatActivity {
|
|||
}
|
||||
}
|
||||
|
||||
helperMethod.updateResources(this, status.mSystemLocale.getDisplayName());
|
||||
}
|
||||
|
||||
private void viewsInitializations() {
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
package com.darkweb.genesissearchengine.appManager.settingManager.settingHomeManager;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
|
@ -11,6 +16,8 @@ import androidx.annotation.NonNull;
|
|||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import com.darkweb.genesissearchengine.appManager.activityContextManager;
|
||||
import com.darkweb.genesissearchengine.appManager.helpManager.helpController;
|
||||
import com.darkweb.genesissearchengine.appManager.kotlinHelperLibraries.BrowserIconManager;
|
||||
import com.darkweb.genesissearchengine.appManager.kotlinHelperLibraries.defaultBrowser;
|
||||
import com.darkweb.genesissearchengine.appManager.proxyStatusManager.proxyStatusController;
|
||||
import com.darkweb.genesissearchengine.appManager.settingManager.accessibilityManager.settingAccessibilityController;
|
||||
import com.darkweb.genesissearchengine.appManager.settingManager.advanceManager.settingAdvanceController;
|
||||
|
@ -37,6 +44,8 @@ import java.net.URLEncoder;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import static com.darkweb.genesissearchengine.pluginManager.pluginEnums.eMessageManager.*;
|
||||
|
||||
public class settingHomeController extends AppCompatActivity
|
||||
|
@ -73,6 +82,8 @@ public class settingHomeController extends AppCompatActivity
|
|||
activityContextManager.getInstance().onResetTheme();
|
||||
}
|
||||
|
||||
helperMethod.updateResources(this, status.mSystemLocale.getDisplayName());
|
||||
activityContextManager.getInstance().getHomeController().updateResources(this, status.mSystemLocale.getDisplayName());
|
||||
super.onConfigurationChanged(newConfig);
|
||||
}
|
||||
|
||||
|
@ -176,9 +187,9 @@ public class settingHomeController extends AppCompatActivity
|
|||
|
||||
public void onDefaultBrowser(View view){
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
startActivity(new Intent(android.provider.Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS));
|
||||
helperMethod.openDefaultBrowser(this);
|
||||
}else{
|
||||
//pluginController.getInstance().onMessageManagerInvoke(Collections.singletonList(this), M_NOT_SUPPORTED);
|
||||
pluginController.getInstance().onMessageManagerInvoke(Collections.singletonList(this), M_NOT_SUPPORTED);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,10 +4,10 @@ public class enums
|
|||
{
|
||||
/*Settings Manager*/
|
||||
public enum etype{
|
||||
M_CHANGE_HOME_THEME, on_update_favicon,M_RELOAD,ON_UPDATE_TAB_TITLE, ON_OPEN_TAB_VIEW,ON_NEW_TAB_ANIMATION, M_UPDATE_SESSION_STATE,ON_LOAD_REQUEST, GECKO_SCROLL_UP, GECKO_SCROLL_UP_ALWAYS, GECKO_SCROLL_DOWN, WAS_SCROLL_CHANGED, GECKO_SCROLL_DOWN_MOVE, GECKO_SCROLL_UP_MOVE, GECKO_SCROLL_DOWN_CALLER,ON_UPDATE_SEARCH_BAR,M_ON_MAIL,SESSION_ID,M_UPDATE_PIXEL_BACKGROUND, M_ON_SCROLL_BOUNDARIES, M_ON_SCROLL_TOP_BOUNDARIES, M_ON_SCROLL_NO_BOUNDARIES, M_INIT_PADDING, M_RATE_COUNT,M_CACHE_UPDATE_TAB,
|
||||
M_CHANGE_HOME_THEME, on_update_favicon,M_RELOAD,ON_UPDATE_TAB_TITLE, ON_OPEN_TAB_VIEW,ON_NEW_TAB_ANIMATION, M_UPDATE_SESSION_STATE,ON_LOAD_REQUEST, GECKO_SCROLL_UP, GECKO_SCROLL_UP_ALWAYS, GECKO_SCROLL_DOWN, WAS_SCROLL_CHANGED, GECKO_SCROLL_DOWN_MOVE, GECKO_SCROLL_UP_MOVE, GECKO_SCROLL_DOWN_CALLER,ON_UPDATE_SEARCH_BAR,M_ON_MAIL,SESSION_ID,M_UPDATE_PIXEL_BACKGROUND, M_ON_SCROLL_BOUNDARIES, M_ON_SCROLL_TOP_BOUNDARIES, M_ON_SCROLL_NO_BOUNDARIES, M_INIT_PADDING, M_RATE_COUNT,M_CACHE_UPDATE_TAB,M_DEFAULT_BROWSER,
|
||||
on_verify_selected_url_menu,FINDER_RESULT_CALLBACK,M_ADMOB_BANNER_RECHECK,M_OPEN_SESSION,M_DOWNLOAD_FAILURE,
|
||||
welcome, reload,download_folder, M_UPDATE_THEME,M_ON_BANNER_UPDATE, M_LOAD_HOMEPAGE_GENESIS,M_INIT_TAB_COUNT_FORCED,M_SPLASH_DISABLE,M_NEW_LINK_IN_NEW_TAB,M_RESET_SUGGESTION,
|
||||
url_triggered, url_triggered_new_tab,url_clear,fetch_favicon,url_clear_at,remove_from_database,is_empty,M_HOME_PAGE,M_PRELOAD_URL,ON_KEYBOARD_CLOSE,M_CLOSE_TAB,
|
||||
url_triggered, url_triggered_new_tab,url_clear,fetch_favicon, M_COPY_URL,url_clear_at,remove_from_database,is_empty,M_HOME_PAGE,M_PRELOAD_URL,ON_KEYBOARD_CLOSE,M_CLOSE_TAB,
|
||||
on_close_sesson,on_long_press, on_full_screen,on_handle_external_intent,on_update_suggestion_url,progress_update,progress_update_forced, ON_EXPAND_TOP_BAR,recheck_orbot,on_url_load,on_playstore_load,back_list_empty,start_proxy, ON_UPDATE_THEME, M_NEW_IDENTITY, M_NEW_IDENTITY_MESSAGED, M_INITIALIZE_TAB_SINGLE, M_INITIALIZE_TAB_LINK,on_request_completed, on_update_history,on_update_suggestion,M_WELCOME_MESSAGE,ON_FIRST_PAINT, ON_LOAD_TAB_ON_RESUME, ON_SESSION_REINIT,on_page_loaded,on_load_error, M_ORBOT_LOADING,download_file_popup,on_init_ads, M_GET_CURRENT_URL,search_update, open_new_tab,open_new_tab_instant
|
||||
}
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ public class status
|
|||
public static int sWidgetResponse = enums.WidgetResponse.NONE;
|
||||
public static int sBridgeNotificationManual = 0;
|
||||
public static int sSettingTrackingProtection = 0;
|
||||
public static int sRateCount = 0;
|
||||
public static int sGlobalURLCount = 0;
|
||||
|
||||
public static float sSettingFontSize = 1;
|
||||
|
||||
|
@ -126,13 +126,13 @@ public class status
|
|||
status.sCharacterEncoding = (boolean)dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_GET_BOOL, Arrays.asList(keys.SETTING_CHARACTER_ENCODING,false));
|
||||
status.sShowImages = (int)dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_GET_INT, Arrays.asList(keys.SETTING_SHOW_IMAGES,0));
|
||||
status.sShowWebFonts = (boolean)dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_GET_BOOL, Arrays.asList(keys.SETTING_SHOW_FONTS,true));
|
||||
status.sFullScreenBrowsing = (boolean)dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_GET_BOOL, Arrays.asList(keys.SETTING_FULL_SCREEN_BROWSIING,true));
|
||||
status.sFullScreenBrowsing = (boolean)dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_GET_BOOL, Arrays.asList(keys.SETTING_FULL_SCREEN_BROWSIING,false));
|
||||
status.sToolbarTheme = (boolean)dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_GET_BOOL, Arrays.asList(keys.SETTING_TOOLBAR_THEME,true));
|
||||
status.sTheme = (int)dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_GET_INT, Arrays.asList(keys.SETTING_THEME,enums.Theme.THEME_DEFAULT));
|
||||
status.sOpenURLInNewTab = (boolean)dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_GET_BOOL, Arrays.asList(keys.SETTING_OPEN_URL_IN_NEW_TAB,true));
|
||||
status.sLogThemeStyleAdvanced = (boolean)dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_GET_BOOL, Arrays.asList(keys.SETTING_LIST_VIEW,true));
|
||||
status.sTabGridLayoutEnabled = (boolean)dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_GET_BOOL, Arrays.asList(keys.SETTING_SHOW_TAB_GRID,true));
|
||||
status.sRateCount = (int)dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_GET_INT, Arrays.asList(keys.SETTING_RATE_COUNT, 0));
|
||||
status.sGlobalURLCount = (int)dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_GET_INT, Arrays.asList(keys.SETTING_RATE_COUNT, 0));
|
||||
status.sAppInstalled = (boolean)dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_GET_BOOL, Arrays.asList(keys.SETTING_INSTALLED,false));
|
||||
}
|
||||
|
||||
|
|
|
@ -229,7 +229,7 @@ public class dataController
|
|||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_INT, Arrays.asList(keys.SETTING_SHOW_IMAGES,0));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_SHOW_FONTS,true));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_TOOLBAR_THEME,true));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_FULL_SCREEN_BROWSIING,true));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_FULL_SCREEN_BROWSIING,false));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_INT, Arrays.asList(keys.SETTING_THEME, enums.Theme.THEME_DEFAULT));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_LIST_VIEW,true));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_SHOW_TAB_GRID,true));
|
||||
|
|
|
@ -158,8 +158,10 @@ class tabDataModel
|
|||
try{
|
||||
if(mTabs.get(counter).getSession().getSessionID().equals(mSessionID))
|
||||
{
|
||||
String[] params = new String[1];
|
||||
params[0] = mSessionState;
|
||||
|
||||
mExternalEvents.invokeObserver(Arrays.asList("UPDATE tab SET session = '" + mSessionState + "' WHERE mid='"+mTabs.get(counter).getmId() + "'",null), dataEnums.eTabCallbackCommands.M_EXEC_SQL);
|
||||
mExternalEvents.invokeObserver(Arrays.asList("UPDATE tab SET session = ? WHERE mid='"+mTabs.get(counter).getmId() + "'",params), dataEnums.eTabCallbackCommands.M_EXEC_SQL);
|
||||
mTabs.add(0,mTabs.remove(counter));
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import android.content.ContentResolver;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
|
@ -50,6 +51,8 @@ import androidx.core.app.ShareCompat;
|
|||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.content.FileProvider;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
|
||||
import com.darkweb.genesissearchengine.appManager.kotlinHelperLibraries.defaultBrowser;
|
||||
import com.darkweb.genesissearchengine.constants.enums;
|
||||
import com.darkweb.genesissearchengine.constants.keys;
|
||||
import com.example.myapplication.R;
|
||||
|
@ -589,6 +592,25 @@ public class helperMethod
|
|||
return size;
|
||||
}
|
||||
|
||||
public static void openDefaultBrowser(AppCompatActivity mContext){
|
||||
defaultBrowser mIconManager = new defaultBrowser();
|
||||
mIconManager.openSetDefaultBrowserOption(mContext);
|
||||
}
|
||||
|
||||
public static boolean isDefaultBrowserSet(AppCompatActivity mContext){
|
||||
defaultBrowser mIconManager = new defaultBrowser();
|
||||
return mIconManager.getabcEnabledValue(mContext);
|
||||
}
|
||||
|
||||
public static void updateResources(Context context, String language) {
|
||||
Locale locale = new Locale(language);
|
||||
Locale.setDefault(locale);
|
||||
Resources resources = context.getResources();
|
||||
Configuration configuration = resources.getConfiguration();
|
||||
configuration.locale = locale;
|
||||
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
|
||||
}
|
||||
|
||||
public static void openActivity( Class<?> cls,int type,AppCompatActivity context,boolean animation){
|
||||
Intent myIntent = new Intent(context, cls);
|
||||
myIntent.putExtra(keys.PROXY_LIST_TYPE, type);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package com.darkweb.genesissearchengine.libs.clientauth;
|
||||
package com.darkweb.genesissearchengine.libs.providers;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentUris;
|
||||
|
@ -12,14 +12,14 @@ import android.provider.BaseColumns;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class ClientAuthContentProvider extends ContentProvider {
|
||||
public class ClientAuthContentProviderGenesis extends ContentProvider {
|
||||
public static final String[] PROJECTION = {
|
||||
V3ClientAuth._ID,
|
||||
V3ClientAuth.DOMAIN,
|
||||
V3ClientAuth.HASH,
|
||||
V3ClientAuth.ENABLED,
|
||||
};
|
||||
private static final String AUTH = "com.darkweb.genesissearchengine.libs.clientauth.ClientAuthContentProvider";
|
||||
private static final String AUTH = "org.torproject.android.ui.v3onionservice.clientauth";
|
||||
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTH + "/v3auth");
|
||||
private static final int V3AUTHS = 1, V3AUTH_ID = 2;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.darkweb.genesissearchengine.libs.clientauth;
|
||||
package com.darkweb.genesissearchengine.libs.providers;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
|
@ -0,0 +1,133 @@
|
|||
package com.darkweb.genesissearchengine.libs.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 androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.darkweb.genesissearchengine.libs.providers.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();
|
||||
|
||||
int 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();
|
||||
}
|
||||
|
||||
int 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() {
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
package com.darkweb.genesissearchengine.libs.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 androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.darkweb.genesissearchengine.libs.providers.HSDatabase;
|
||||
|
||||
|
||||
public class HSContentProvider extends ContentProvider {
|
||||
public static final String[] PROJECTION = new String[]{
|
||||
HiddenService._ID,
|
||||
HiddenService.NAME,
|
||||
HiddenService.PORT,
|
||||
HiddenService.DOMAIN,
|
||||
HiddenService.ONION_PORT,
|
||||
HiddenService.AUTH_COOKIE,
|
||||
HiddenService.AUTH_COOKIE_VALUE,
|
||||
HiddenService.CREATED_BY_USER,
|
||||
HiddenService.ENABLED
|
||||
};
|
||||
private static final String AUTH = "org.torproject.android.ui.hiddenservices.providers";
|
||||
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTH + "/hs");
|
||||
//UriMatcher
|
||||
private static final int ONIONS = 1;
|
||||
private static final int ONION_ID = 2;
|
||||
|
||||
private static final UriMatcher uriMatcher;
|
||||
|
||||
static {
|
||||
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
|
||||
uriMatcher.addURI(AUTH, "hs", ONIONS);
|
||||
uriMatcher.addURI(AUTH, "hs/#", ONION_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) == ONION_ID) {
|
||||
where = "_id=" + uri.getLastPathSegment();
|
||||
}
|
||||
|
||||
SQLiteDatabase db = mServervices.getReadableDatabase();
|
||||
|
||||
return db.query(HSDatabase.HS_DATA_TABLE_NAME, projection, where, selectionArgs, null, null, sortOrder);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getType(@NonNull Uri uri) {
|
||||
int match = uriMatcher.match(uri);
|
||||
|
||||
switch (match) {
|
||||
case ONIONS:
|
||||
return "vnd.android.cursor.dir/vnd.torproject.onions";
|
||||
case ONION_ID:
|
||||
return "vnd.android.cursor.item/vnd.torproject.onion";
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Uri insert(@NonNull Uri uri, ContentValues values) {
|
||||
long regId;
|
||||
|
||||
SQLiteDatabase db = mServervices.getWritableDatabase();
|
||||
|
||||
regId = db.insert(HSDatabase.HS_DATA_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) == ONION_ID) {
|
||||
where = "_id=" + uri.getLastPathSegment();
|
||||
}
|
||||
|
||||
SQLiteDatabase db = mServervices.getWritableDatabase();
|
||||
|
||||
int rows = db.delete(HSDatabase.HS_DATA_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) == ONION_ID) {
|
||||
where = "_id=" + uri.getLastPathSegment();
|
||||
}
|
||||
|
||||
int rows = db.update(HSDatabase.HS_DATA_TABLE_NAME, values, where, null);
|
||||
mContext.getContentResolver().notifyChange(CONTENT_URI, null);
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
public static final class HiddenService implements BaseColumns {
|
||||
public static final String NAME = "name";
|
||||
public static final String PORT = "port";
|
||||
public static final String ONION_PORT = "onion_port";
|
||||
public static final String DOMAIN = "domain";
|
||||
public static final String AUTH_COOKIE = "auth_cookie";
|
||||
public static final String AUTH_COOKIE_VALUE = "auth_cookie_value";
|
||||
public static final String CREATED_BY_USER = "created_by_user";
|
||||
public static final String ENABLED = "enabled";
|
||||
|
||||
private HiddenService() {
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package com.darkweb.genesissearchengine.libs.providers;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
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 = 4;
|
||||
private static final String DATABASE_NAME = "hidden_services";
|
||||
private static final String HS_DATA_TABLE_CREATE =
|
||||
"CREATE TABLE " + HS_DATA_TABLE_NAME + " (" +
|
||||
"_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
|
||||
"name TEXT, " +
|
||||
"domain TEXT, " +
|
||||
"onion_port INTEGER, " +
|
||||
"auth_cookie INTEGER DEFAULT 0, " +
|
||||
"auth_cookie_value TEXT, " +
|
||||
"created_by_user INTEGER DEFAULT 0, " +
|
||||
"enabled INTEGER DEFAULT 1, " +
|
||||
"port INTEGER, " +
|
||||
"filepath TEXT);";
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL(HS_DATA_TABLE_CREATE);
|
||||
db.execSQL(HS_CLIENT_COOKIE_TABLE_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
if (newVersion > oldVersion) {
|
||||
db.execSQL("ALTER TABLE " + HS_DATA_TABLE_NAME + " ADD COLUMN filepath TEXT");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
package com.darkweb.genesissearchengine.libs.providers;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentUris;
|
||||
import android.content.ContentValues;
|
||||
import android.content.UriMatcher;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.net.Uri;
|
||||
import android.provider.BaseColumns;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class OnionServiceContentProvider extends ContentProvider {
|
||||
|
||||
public static final String[] PROJECTION = {
|
||||
OnionService._ID,
|
||||
OnionService.NAME,
|
||||
OnionService.PORT,
|
||||
OnionService.DOMAIN,
|
||||
OnionService.ONION_PORT,
|
||||
OnionService.CREATED_BY_USER,
|
||||
OnionService.ENABLED
|
||||
};
|
||||
|
||||
private static final int ONIONS = 1, ONION_ID = 2;
|
||||
private static final String AUTH = "org.torproject.android.ui.v3onionservice";
|
||||
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTH + "/v3");
|
||||
private static final UriMatcher uriMatcher;
|
||||
|
||||
static {
|
||||
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
|
||||
uriMatcher.addURI(AUTH, "v3", ONIONS);
|
||||
uriMatcher.addURI(AUTH, "v3/#", ONION_ID);
|
||||
}
|
||||
|
||||
private OnionServiceDatabase mDatabase;
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
mDatabase = new OnionServiceDatabase(getContext());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
|
||||
if (uriMatcher.match(uri) == ONION_ID)
|
||||
selection = "_id=" + uri.getLastPathSegment();
|
||||
SQLiteDatabase db = mDatabase.getReadableDatabase();
|
||||
return db.query(OnionServiceDatabase.ONION_SERVICE_TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getType(@NonNull Uri uri) {
|
||||
int match = uriMatcher.match(uri);
|
||||
switch (match) {
|
||||
case ONIONS:
|
||||
return "vnd.android.cursor.dir/vnd.torproject.onions";
|
||||
case ONION_ID:
|
||||
return "vnd.android.cursor.item/vnd.torproject.onion";
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
|
||||
SQLiteDatabase db = mDatabase.getWritableDatabase();
|
||||
long regId = db.insert(OnionServiceDatabase.ONION_SERVICE_TABLE_NAME, null, values);
|
||||
getContext().getContentResolver().notifyChange(CONTENT_URI, null);
|
||||
return ContentUris.withAppendedId(CONTENT_URI, regId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
|
||||
if (uriMatcher.match(uri) == ONION_ID)
|
||||
selection = "_id=" + uri.getLastPathSegment();
|
||||
SQLiteDatabase db = mDatabase.getWritableDatabase();
|
||||
int rows = db.delete(OnionServiceDatabase.ONION_SERVICE_TABLE_NAME, selection, selectionArgs);
|
||||
getContext().getContentResolver().notifyChange(CONTENT_URI, null);
|
||||
return rows;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
|
||||
SQLiteDatabase db = mDatabase.getWritableDatabase();
|
||||
if (uriMatcher.match(uri) == ONION_ID)
|
||||
selection = "_id=" + uri.getLastPathSegment();
|
||||
int rows = db.update(OnionServiceDatabase.ONION_SERVICE_TABLE_NAME, values, selection, null);
|
||||
getContext().getContentResolver().notifyChange(CONTENT_URI, null);
|
||||
return rows;
|
||||
}
|
||||
|
||||
public static final class OnionService implements BaseColumns {
|
||||
public static final String NAME = "name";
|
||||
public static final String PORT = "port";
|
||||
public static final String ONION_PORT = "onion_port";
|
||||
public static final String DOMAIN = "domain";
|
||||
public static final String CREATED_BY_USER = "created_by_user";
|
||||
public static final String ENABLED = "enabled";
|
||||
|
||||
private OnionService() { // no-op
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.darkweb.genesissearchengine.libs.providers;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
|
||||
public class OnionServiceDatabase extends SQLiteOpenHelper {
|
||||
|
||||
static final String DATABASE_NAME = "onion_service",
|
||||
ONION_SERVICE_TABLE_NAME = "onion_services";
|
||||
private static final int DATABASE_VERSION = 2;
|
||||
|
||||
private static final String ONION_SERVICES_CREATE_SQL =
|
||||
"CREATE TABLE " + ONION_SERVICE_TABLE_NAME + " (" +
|
||||
"_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
|
||||
"name TEXT, " +
|
||||
"domain TEXT, " +
|
||||
"onion_port INTEGER, " +
|
||||
"created_by_user INTEGER DEFAULT 0, " +
|
||||
"enabled INTEGER DEFAULT 1, " +
|
||||
"port INTEGER, " +
|
||||
"filepath TEXT);";
|
||||
|
||||
OnionServiceDatabase(Context context) {
|
||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL(ONION_SERVICES_CREATE_SQL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
if (newVersion > oldVersion) {
|
||||
db.execSQL("ALTER TABLE " + ONION_SERVICE_TABLE_NAME + " ADD COLUMN filepath text");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,9 +1,14 @@
|
|||
package com.darkweb.genesissearchengine.pluginManager.adPluginManager;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.darkweb.genesissearchengine.dataManager.dataController;
|
||||
import com.darkweb.genesissearchengine.dataManager.dataEnums;
|
||||
import com.darkweb.genesissearchengine.eventObserver;
|
||||
import com.darkweb.genesissearchengine.pluginManager.pluginEnums;
|
||||
import com.google.android.gms.ads.*;
|
||||
|
@ -83,8 +88,10 @@ public class adManager
|
|||
|
||||
@Override
|
||||
public void onAdFailedToLoad(@NonNull LoadAdError var1) {
|
||||
Log.i("dsa","asd");
|
||||
bannerAdsLoading = false;
|
||||
new Handler().postDelayed(() ->
|
||||
{
|
||||
initializeBannerAds();
|
||||
}, 10000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ import com.darkweb.genesissearchengine.pluginManager.pluginEnums;
|
|||
import com.darkweb.genesissearchengine.pluginManager.pluginReciever.downloadNotificationReciever;
|
||||
import com.example.myapplication.R;
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.util.Log;
|
||||
import org.torproject.android.proxy.util.Prefs;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
|
|
|
@ -4,7 +4,11 @@ import android.content.res.Configuration;
|
|||
import android.content.res.Resources;
|
||||
import android.os.Build;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.darkweb.genesissearchengine.appManager.activityContextManager;
|
||||
import com.darkweb.genesissearchengine.constants.status;
|
||||
import com.darkweb.genesissearchengine.eventObserver;
|
||||
import com.darkweb.genesissearchengine.helperManager.helperMethod;
|
||||
import com.darkweb.genesissearchengine.pluginManager.pluginEnums;
|
||||
|
||||
import java.util.Collections;
|
||||
|
@ -29,35 +33,39 @@ public class langManager {
|
|||
onInitLanguage(pAppContext, pSettingLanguage, pSettingRegionLanguage, pThemeApplying);
|
||||
}
|
||||
|
||||
private boolean initLocale(Boolean pThemeApplying){
|
||||
if(!pThemeApplying){
|
||||
private boolean initLocale(){
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
Locale mSystemLocale = Resources.getSystem().getConfiguration().getLocales().get(0);
|
||||
if(mSystemLocale!=mSystemLocale || !mSystemLocale.getLanguage().equals(mLanguage.getLanguage()) ){
|
||||
mEvent.invokeObserver(Collections.singletonList(mSystemLocale), pluginEnums.eLangManager.M_UPDATE_LOCAL);
|
||||
}
|
||||
Locale mSystemLocaleTemp = Resources.getSystem().getConfiguration().getLocales().get(0);
|
||||
mEvent.invokeObserver(Collections.singletonList(mSystemLocaleTemp), pluginEnums.eLangManager.M_UPDATE_LOCAL);
|
||||
mSystemLocale = mSystemLocaleTemp;
|
||||
} else {
|
||||
Locale mSystemLocale = Resources.getSystem().getConfiguration().locale;
|
||||
if(mSystemLocale!=mSystemLocale || !mSystemLocale.getLanguage().equals(mLanguage.getLanguage())){
|
||||
mEvent.invokeObserver(Collections.singletonList(mSystemLocale), pluginEnums.eLangManager.M_UPDATE_LOCAL);
|
||||
}
|
||||
}
|
||||
Locale mSystemLocaleTemp = Resources.getSystem().getConfiguration().locale;
|
||||
mEvent.invokeObserver(Collections.singletonList(mSystemLocaleTemp), pluginEnums.eLangManager.M_UPDATE_LOCAL);
|
||||
mSystemLocale = mSystemLocaleTemp;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void onInitLanguage(AppCompatActivity pAppContext, String pSettingLanguage, String pSettingRegionLanguage, Boolean pThemeApplying) {
|
||||
if(pSettingLanguage.equals("default")){
|
||||
if(!mLanguage.getLanguage().equals(Resources.getSystem().getConfiguration().locale.getLanguage()) || !mLanguage.getCountry().equals(Resources.getSystem().getConfiguration().locale.getCountry()))
|
||||
Locale mSystemLocaleTemp = null;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
mSystemLocaleTemp = Resources.getSystem().getConfiguration().getLocales().get(0);
|
||||
} else {
|
||||
mSystemLocaleTemp = Resources.getSystem().getConfiguration().locale;
|
||||
}
|
||||
|
||||
if(!mLanguage.toString().equals(mSystemLocaleTemp.toString()))
|
||||
{
|
||||
if(mSystemLocale==null){
|
||||
initLocale(pThemeApplying);
|
||||
initLocale();
|
||||
}
|
||||
mSystemLocale = mSystemLocaleTemp;
|
||||
String mSystemLangugage = mSystemLocale.toString();
|
||||
if(mSystemLangugage.equals("en_US") || mSystemLangugage.equals("de_DE") || mSystemLangugage.equals("ur_UR") || mSystemLangugage.equals("ur_PK") || mSystemLangugage.equals("ca_ES") || mSystemLangugage.equals("zh_CN") || mSystemLangugage.equals("ch_CZ") || mSystemLangugage.equals("nl_NL") || mSystemLangugage.equals("fr_FR") || mSystemLangugage.equals("el_GR") || mSystemLangugage.equals("hu_HU") || mSystemLangugage.equals("in_ID") || mSystemLangugage.equals("it_IT") || mSystemLangugage.equals("ja_JP") || mSystemLangugage.equals("ko_KR") || mSystemLangugage.equals("pt_PT") || mSystemLangugage.equals("ro_RO") || mSystemLangugage.equals("ru_RU") || mSystemLangugage.equals("th_TH") || mSystemLangugage.equals("tr_TR") || mSystemLangugage.equals("uk_UA") || mSystemLangugage.equals("vi_VN")){
|
||||
if(mSystemLangugage.equals("cs_CZ") || mSystemLangugage.equals("en_US") || mSystemLangugage.equals("de_DE") || mSystemLangugage.equals("ur_UR") || mSystemLangugage.equals("ur_PK") || mSystemLangugage.equals("ca_ES") || mSystemLangugage.equals("zh_CN") || mSystemLangugage.equals("ch_CZ") || mSystemLangugage.equals("nl_NL") || mSystemLangugage.equals("fr_FR") || mSystemLangugage.equals("el_GR") || mSystemLangugage.equals("hu_HU") || mSystemLangugage.equals("in_ID") || mSystemLangugage.equals("it_IT") || mSystemLangugage.equals("ja_JP") || mSystemLangugage.equals("ko_KR") || mSystemLangugage.equals("pt_PT") || mSystemLangugage.equals("ro_RO") || mSystemLangugage.equals("ru_RU") || mSystemLangugage.equals("th_TH") || mSystemLangugage.equals("tr_TR") || mSystemLangugage.equals("uk_UA") || mSystemLangugage.equals("vi_VN")){
|
||||
if(mSystemLangugage.equals("ur_PK")){
|
||||
mLanguage = new Locale("ur", "Ur");
|
||||
} else if(mSystemLangugage.equals("vi_VN")){
|
||||
} else if(mSystemLangugage.equals("vi_VN") || mSystemLangugage.equals("cs_CZ")){
|
||||
mLanguage = new Locale("ch", "Cz");
|
||||
} else {
|
||||
mLanguage = new Locale(mSystemLocale.getLanguage(), mSystemLocale.getCountry());
|
||||
|
@ -65,15 +73,18 @@ public class langManager {
|
|||
}else {
|
||||
mLanguage = new Locale("en", "Us");
|
||||
}
|
||||
helperMethod.updateResources(pAppContext, status.mSystemLocale.getLanguage());
|
||||
}else {
|
||||
Locale mSystemLocale = Resources.getSystem().getConfiguration().locale;
|
||||
mEvent.invokeObserver(Collections.singletonList(mSystemLocale), pluginEnums.eLangManager.M_UPDATE_LOCAL);
|
||||
helperMethod.updateResources(pAppContext, status.mSystemLocale.getLanguage());
|
||||
return;
|
||||
}
|
||||
|
||||
}else {
|
||||
mLanguage = new Locale(pSettingLanguage, pSettingRegionLanguage);
|
||||
}
|
||||
|
||||
|
||||
status.mSystemLocale = mLanguage;
|
||||
Locale.setDefault(mLanguage);
|
||||
Resources resources = pAppContext.getResources();
|
||||
Configuration config = resources.getConfiguration();
|
||||
|
@ -115,7 +126,7 @@ public class langManager {
|
|||
}
|
||||
else if(pEventType.equals(pluginEnums.eLangManager.M_RESUME))
|
||||
{
|
||||
initLocale((boolean)pData.get(3));
|
||||
initLocale();
|
||||
onResume((AppCompatActivity) pData.get(0), (String)pData.get(1), (String)pData.get(2), (boolean)pData.get(3));
|
||||
}
|
||||
else if(pEventType.equals(pluginEnums.eLangManager.M_SET_LANGUAGE))
|
||||
|
|
|
@ -4,9 +4,9 @@ import android.content.Intent;
|
|||
import android.os.Build;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import org.mozilla.gecko.PrefsHelper;
|
||||
import org.torproject.android.proxy.OrbotService;
|
||||
import org.torproject.android.proxy.util.Prefs;
|
||||
import org.torproject.android.proxy.wrapper.orbotLocalConstants;
|
||||
import org.torproject.android.service.OrbotService;
|
||||
import org.torproject.android.service.util.Prefs;
|
||||
import org.torproject.android.service.wrapper.orbotLocalConstants;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
|
@ -17,7 +17,8 @@ import com.darkweb.genesissearchengine.constants.strings;
|
|||
import com.darkweb.genesissearchengine.eventObserver;
|
||||
import com.darkweb.genesissearchengine.pluginManager.pluginEnums;
|
||||
|
||||
import static org.torproject.android.proxy.TorServiceConstants.ACTION_START;
|
||||
import static org.torproject.android.service.TorServiceConstants.ACTION_START;
|
||||
|
||||
|
||||
// https://github.com/guardianproject/orbot/blob/8fca5f8ecddb4da9565ac3fd8936e4f28acdd352/BUILD.md
|
||||
public class orbotManager
|
||||
|
@ -60,6 +61,7 @@ public class orbotManager
|
|||
}
|
||||
else
|
||||
{
|
||||
mAppContext.get().stopService(mServiceIntent);
|
||||
mAppContext.get().startService(mServiceIntent);
|
||||
}
|
||||
|
||||
|
@ -219,8 +221,10 @@ public class orbotManager
|
|||
}
|
||||
|
||||
private void newCircuit(){
|
||||
if(OrbotService.getServiceObject()!=null){
|
||||
OrbotService.getServiceObject().newIdentity();
|
||||
}
|
||||
}
|
||||
|
||||
private String getOrbotStatus(){
|
||||
return OrbotService.getServiceObject().getProxyStatus();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:startOffset="0">
|
||||
<alpha
|
||||
android:duration="250"
|
||||
android:duration="350"
|
||||
android:fromAlpha="0.0"
|
||||
android:interpolator="@android:anim/linear_interpolator"
|
||||
android:toAlpha="1.0" />
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<alpha
|
||||
android:duration="250"
|
||||
android:duration="350"
|
||||
android:fromAlpha="1.0"
|
||||
android:interpolator="@android:anim/linear_interpolator"
|
||||
android:toAlpha="0.5" />
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
|
||||
<item android:drawable="@color/landing_ease_blue"/>
|
||||
<item>
|
||||
</item>
|
||||
</layer-list>
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
</PreferenceScreen>
|
Before Width: | Height: | Size: 387 B After Width: | Height: | Size: 387 B |
Before Width: | Height: | Size: 250 B After Width: | Height: | Size: 250 B |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 544 B After Width: | Height: | Size: 544 B |
|
@ -25,7 +25,7 @@
|
|||
android:background="@color/c_background"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
||||
android:fitsSystemWindows="true"
|
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
|
||||
app:layout_scrollFlags="enterAlwaysCollapsed"
|
||||
android:translationZ="3dp">
|
||||
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
|
@ -34,7 +34,7 @@
|
|||
app:scrimAnimationDuration="10"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
|
||||
app:layout_scrollFlags="enterAlwaysCollapsed"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
|
@ -45,7 +45,7 @@
|
|||
android:clipToPadding="true"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
|
||||
app:layout_scrollFlags="enterAlwaysCollapsed"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<LinearLayout
|
||||
|
@ -246,6 +246,7 @@
|
|||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/pWebLayoutView"
|
||||
android:paddingBottom="60dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="0dp"
|
||||
|
@ -742,6 +743,7 @@
|
|||
android:background="@xml/hx_border_left"
|
||||
android:ellipsize="end"
|
||||
android:gravity="start"
|
||||
android:alpha="0"
|
||||
android:maxHeight="250dp"
|
||||
android:maxLines="4"
|
||||
android:minHeight="80dp"
|
||||
|
@ -754,7 +756,6 @@
|
|||
android:textColor="@color/white"
|
||||
android:textFontWeight="5"
|
||||
android:textSize="14sp"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toTopOf="@+id/pSettings"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
|
|
@ -49,15 +49,16 @@
|
|||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="40dp"
|
||||
android:paddingStart="8dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:onClick="onOpenInfo"
|
||||
android:background="@xml/gx_ripple_gray_round_left"
|
||||
<ImageButton
|
||||
android:layout_width="45dp"
|
||||
android:layout_height="45dp"
|
||||
android:layout_marginStart="0dp"
|
||||
android:layout_marginEnd="3dp"
|
||||
android:layout_marginTop="1dp"
|
||||
android:background="@xml/gx_ripple_default_round"
|
||||
android:contentDescription="@string/GENERAL_TODO"
|
||||
android:src="@xml/ic_info"
|
||||
android:onClick="onOpenInfo"
|
||||
android:src="@xml/ic_gear"
|
||||
app:tint="@color/c_icon_tint_light" />
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
@ -3,11 +3,7 @@ apply plugin: 'com.android.library'
|
|||
android {
|
||||
compileSdkVersion 30
|
||||
buildToolsVersion '30.0.3'
|
||||
ndkVersion '21.4.7075529'
|
||||
defaultConfig {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 30
|
||||
}
|
||||
ndkVersion '21.3.6528147'
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
|
@ -15,14 +11,18 @@ android {
|
|||
}
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 30
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,31 +31,38 @@ android {
|
|||
}
|
||||
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
checkReleaseBuilds false
|
||||
abortOnError true
|
||||
|
||||
htmlReport true
|
||||
xmlReport false
|
||||
textReport false
|
||||
|
||||
lintConfig file("../lint.xml")
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
exclude 'assets/arm/obfs4proxy' //this is redundant
|
||||
exclude 'META-INF/androidx.localbroadcastmanager_localbroadcastmanager.version'
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation 'org.torproject:tor-android-binary:0.4.4.6'
|
||||
|
||||
implementation 'info.pluggabletransports.aptds:apt-dispatch-library:1.0.9'
|
||||
implementation 'info.pluggabletransports.aptds:apt-meek-obfs4-legacy:1.0.9'
|
||||
implementation 'info.pluggabletransports.aptds:jsocksAndroid:1.0.4'
|
||||
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
|
||||
implementation 'com.gitlab.guardianproject:jsocksandroid:1.0.4'
|
||||
|
||||
implementation 'com.jaredrummler:android-shell:1.0.0'
|
||||
implementation fileTree(dir: 'libs', include: ['.so'])
|
||||
//implementation fileTree(dir: 'libs', include: ['.so','.aar'])
|
||||
|
||||
implementation 'androidx.core:core:1.5.0'
|
||||
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
|
||||
implementation 'com.offbynull.portmapper:portmapper:2.0.5'
|
||||
|
||||
implementation 'info.guardianproject:jtorctl:0.4'
|
||||
implementation 'info.guardianproject:geoip:20191217'
|
||||
|
||||
api 'info.guardianproject:jtorctl:0.4.5.7'
|
||||
implementation 'info.guardianproject:tor-android:0.4.5.7'
|
||||
|
||||
implementation 'com.github.tladesignz:IPtProxy:1.0.0'
|
||||
}
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
-keep,includedescriptorclasses class net.sqlcipher.** { *; }
|
||||
-keep,includedescriptorclasses interface net.sqlcipher.** { *; }
|
||||
|
||||
-dontwarn javax.annotation.**
|
||||
-dontwarn org.codehaus.mojo.animal_sniffer.*
|
||||
-dontwarn okhttp3.internal.platform.ConscryptPlatform
|
||||
-dontwarn org.conscrypt.ConscryptHostnameVerifier
|
||||
-dontwarn okhttp3.*
|
||||
-dontwarn org.chromium.net.*
|
||||
|
||||
-keep class com.flurry.** { *; }
|
||||
-dontwarn com.flurry.**
|
||||
-keepattributes *Annotation*,EnclosingMethod,Signature
|
||||
-keepclasseswithmembers class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||
}
|
||||
-keepnames class * implements android.os.Parcelable {
|
||||
public static final ** CREATOR;
|
||||
}
|
||||
|
||||
-dontobfuscate
|
||||
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*,!code/allocation/variable
|
|
@ -1,4 +1,6 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.torproject.android.service">
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
|
||||
|
||||
</manifest>
|
||||
|
|
Before Width: | Height: | Size: 47 KiB |
|
@ -1,38 +0,0 @@
|
|||
/* Copyright (c) 2009, Nathan Freitas, Orbot/The Guardian Project - http://openideals.com/guardian */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
package org.torproject.android.proxy;
|
||||
|
||||
public interface OrbotConstants {
|
||||
|
||||
String TAG = "Orbot";
|
||||
|
||||
String PREF_OR = "pref_or";
|
||||
String PREF_OR_PORT = "pref_or_port";
|
||||
String PREF_OR_NICKNAME = "pref_or_nickname";
|
||||
String PREF_REACHABLE_ADDRESSES = "pref_reachable_addresses";
|
||||
String PREF_REACHABLE_ADDRESSES_PORTS = "pref_reachable_addresses_ports";
|
||||
|
||||
String PREF_DISABLE_NETWORK = "pref_disable_network";
|
||||
|
||||
String PREF_TOR_SHARED_PREFS = "org.torproject.android_preferences";
|
||||
|
||||
String PREF_SOCKS = "pref_socks";
|
||||
|
||||
String PREF_HTTP = "pref_http";
|
||||
|
||||
String PREF_ISOLATE_DEST = "pref_isolate_dest";
|
||||
|
||||
String PREF_CONNECTION_PADDING = "pref_connection_padding";
|
||||
String PREF_REDUCED_CONNECTION_PADDING = "pref_reduced_connection_padding";
|
||||
String PREF_CIRCUIT_PADDING = "pref_circuit_padding";
|
||||
String PREF_REDUCED_CIRCUIT_PADDING = "pref_reduced_circuit_padding";
|
||||
|
||||
String PREF_PREFER_IPV6 = "pref_prefer_ipv6";
|
||||
String PREF_DISABLE_IPV4 = "pref_disable_ipv4";
|
||||
|
||||
|
||||
String APP_TOR_KEY = "_app_tor";
|
||||
String APP_DATA_KEY = "_app_data";
|
||||
String APP_WIFI_KEY = "_app_wifi";
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
package org.torproject.android.proxy;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.torproject.android.proxy.util.Prefs;
|
||||
|
||||
|
||||
public class StartTorReceiver extends BroadcastReceiver implements TorServiceConstants {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
/* sanitize the Intent before forwarding it to OrbotService */
|
||||
Prefs.setContext(context);
|
||||
String action = intent.getAction();
|
||||
if (TextUtils.equals(action, ACTION_START)) {
|
||||
String packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME);
|
||||
if (Prefs.allowBackgroundStarts()) {
|
||||
Intent startTorIntent = new Intent(context, OrbotService.class);
|
||||
startTorIntent.setAction(action);
|
||||
if (packageName != null) {
|
||||
startTorIntent.putExtra(OrbotService.EXTRA_PACKAGE_NAME, packageName);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
context.startForegroundService(startTorIntent);
|
||||
} else {
|
||||
context.startService(startTorIntent);
|
||||
}
|
||||
} else if (!TextUtils.isEmpty(packageName)) {
|
||||
// let the requesting app know that the user has disabled
|
||||
// starting via Intent
|
||||
Intent startsDisabledIntent = new Intent(ACTION_STATUS);
|
||||
startsDisabledIntent.putExtra(EXTRA_STATUS, STATUS_STARTS_DISABLED);
|
||||
startsDisabledIntent.setPackage(packageName);
|
||||
context.sendBroadcast(startsDisabledIntent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,119 +0,0 @@
|
|||
/* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
package org.torproject.android.proxy;
|
||||
|
||||
import android.content.Intent;
|
||||
|
||||
public interface TorServiceConstants {
|
||||
|
||||
String DIRECTORY_TOR_DATA = "tordata";
|
||||
|
||||
String TOR_CONTROL_PORT_FILE = "control.txt";
|
||||
String TOR_PID_FILE = "torpid";
|
||||
|
||||
//torrc (tor config file)
|
||||
String TORRC_ASSET_KEY = "torrc";
|
||||
|
||||
String TOR_CONTROL_COOKIE = "control_auth_cookie";
|
||||
|
||||
//geoip data file asset key
|
||||
String GEOIP_ASSET_KEY = "geoip";
|
||||
String GEOIP6_ASSET_KEY = "geoip6";
|
||||
|
||||
String IP_LOCALHOST = "127.0.0.1";
|
||||
int TOR_TRANSPROXY_PORT_DEFAULT = 9040;
|
||||
|
||||
int TOR_DNS_PORT_DEFAULT = 5400;
|
||||
|
||||
String HTTP_PROXY_PORT_DEFAULT = "8125"; // like Privoxy!
|
||||
String SOCKS_PROXY_PORT_DEFAULT = "9055";
|
||||
|
||||
//control port
|
||||
String LOG_NOTICE_HEADER = "NOTICE";
|
||||
String LOG_NOTICE_BOOTSTRAPPED = "Bootstrapped";
|
||||
|
||||
/**
|
||||
* A request to Orbot to transparently start Tor services
|
||||
*/
|
||||
String ACTION_START = "org.torproject.android.intent.action.START";
|
||||
String ACTION_STOP = "org.torproject.android.intent.action.STOP";
|
||||
|
||||
String ACTION_START_VPN = "org.torproject.android.intent.action.START_VPN";
|
||||
String ACTION_STOP_VPN = "org.torproject.android.intent.action.STOP_VPN";
|
||||
|
||||
String ACTION_START_ON_BOOT = "org.torproject.android.intent.action.START_BOOT";
|
||||
|
||||
int REQUEST_VPN = 7777;
|
||||
|
||||
/**
|
||||
* {@link Intent} send by Orbot with {@code ON/OFF/STARTING/STOPPING} status
|
||||
*/
|
||||
String ACTION_STATUS = "org.torproject.android.intent.action.STATUS";
|
||||
/**
|
||||
* {@code String} that contains a status constant: {@link #STATUS_ON},
|
||||
* {@link #STATUS_OFF}, {@link #STATUS_STARTING}, or
|
||||
* {@link #STATUS_STOPPING}
|
||||
*/
|
||||
String EXTRA_STATUS = "org.torproject.android.intent.extra.STATUS";
|
||||
/**
|
||||
* A {@link String} {@code packageName} for Orbot to direct its status reply
|
||||
* to, used in {@link #ACTION_START} {@link Intent}s sent to Orbot
|
||||
*/
|
||||
String EXTRA_PACKAGE_NAME = "org.torproject.android.intent.extra.PACKAGE_NAME";
|
||||
/**
|
||||
* The SOCKS proxy settings in URL form.
|
||||
*/
|
||||
String EXTRA_SOCKS_PROXY = "org.torproject.android.intent.extra.SOCKS_PROXY";
|
||||
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";
|
||||
/**
|
||||
* The HTTP proxy settings in URL form.
|
||||
*/
|
||||
String EXTRA_HTTP_PROXY = "org.torproject.android.intent.extra.HTTP_PROXY";
|
||||
String EXTRA_HTTP_PROXY_HOST = "org.torproject.android.intent.extra.HTTP_PROXY_HOST";
|
||||
String EXTRA_HTTP_PROXY_PORT = "org.torproject.android.intent.extra.HTTP_PROXY_PORT";
|
||||
|
||||
String EXTRA_DNS_PORT = "org.torproject.android.intent.extra.DNS_PORT";
|
||||
String EXTRA_TRANS_PORT = "org.torproject.android.intent.extra.TRANS_PORT";
|
||||
|
||||
String LOCAL_ACTION_LOG = "log";
|
||||
String LOCAL_ACTION_BANDWIDTH = "bandwidth";
|
||||
String LOCAL_EXTRA_LOG = "log";
|
||||
String LOCAL_ACTION_PORTS = "ports";
|
||||
|
||||
/**
|
||||
* All tor-related services and daemons are stopped
|
||||
*/
|
||||
String STATUS_OFF = "OFF";
|
||||
/**
|
||||
* All tor-related services and daemons have completed starting
|
||||
*/
|
||||
String STATUS_ON = "ON";
|
||||
String STATUS_STARTING = "STARTING";
|
||||
String STATUS_STOPPING = "STOPPING";
|
||||
|
||||
/**
|
||||
* The user has disabled the ability for background starts triggered by
|
||||
* apps. Fallback to the old {@link Intent} action that brings up Orbot:
|
||||
* {@link org.torproject.android.OrbotMainActivity#INTENT_ACTION_REQUEST_START_TOR}
|
||||
*/
|
||||
String STATUS_STARTS_DISABLED = "STARTS_DISABLED";
|
||||
|
||||
// actions for internal command Intents
|
||||
String CMD_SIGNAL_HUP = "signal_hup";
|
||||
String CMD_NEWNYM = "newnym";
|
||||
String CMD_SETTING = "setting";
|
||||
String CMD_SET_EXIT = "setexit";
|
||||
String CMD_ACTIVE = "ACTIVE";
|
||||
|
||||
String PREF_BINARY_TOR_VERSION_INSTALLED = "BINARY_TOR_VERSION_INSTALLED";
|
||||
|
||||
//obfsproxy
|
||||
String OBFSCLIENT_ASSET_KEY = "obfs4proxy";
|
||||
|
||||
String HIDDEN_SERVICES_DIR = "hidden_services";
|
||||
String ONION_SERVICES_DIR = "v3_onion_services";
|
||||
String V3_CLIENT_AUTH_DIR = "v3_client_auth";
|
||||
|
||||
}
|
|
@ -1,128 +0,0 @@
|
|||
package org.torproject.android.proxy.util;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
public class CustomNativeLoader {
|
||||
|
||||
private final static String TAG = "CNL";
|
||||
|
||||
@SuppressLint("SetWorldReadable")
|
||||
private static boolean loadFromZip(Context context, String libname, File destLocalFile, String arch) {
|
||||
|
||||
|
||||
ZipFile zipFile = null;
|
||||
InputStream stream = null;
|
||||
|
||||
try {
|
||||
zipFile = new ZipFile(context.getApplicationInfo().sourceDir);
|
||||
ZipEntry entry = zipFile.getEntry("lib/" + arch + "/" + libname + ".so");
|
||||
if (entry == null) {
|
||||
entry = zipFile.getEntry("jni/" + arch + "/" + libname + ".so");
|
||||
if (entry == null)
|
||||
throw new Exception("Unable to find file in apk:" + "lib/" + arch + "/" + libname);
|
||||
}
|
||||
|
||||
//how we wrap this in another stream because the native .so is zipped itself
|
||||
stream = zipFile.getInputStream(entry);
|
||||
|
||||
OutputStream out = new FileOutputStream(destLocalFile);
|
||||
byte[] buf = new byte[4096];
|
||||
int len;
|
||||
while ((len = stream.read(buf)) > 0) {
|
||||
Thread.yield();
|
||||
out.write(buf, 0, len);
|
||||
}
|
||||
out.close();
|
||||
|
||||
destLocalFile.setReadable(true, false);
|
||||
destLocalFile.setExecutable(true, false);
|
||||
destLocalFile.setWritable(true);
|
||||
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
} finally {
|
||||
if (stream != null) {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
}
|
||||
}
|
||||
if (zipFile != null) {
|
||||
try {
|
||||
zipFile.close();
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static File loadNativeBinary(Context context, String libname, File destLocalFile) {
|
||||
|
||||
try {
|
||||
|
||||
|
||||
File fileNativeBin = new File(getNativeLibraryDir(context), libname + ".so");
|
||||
if (!fileNativeBin.exists())
|
||||
fileNativeBin = new File(getNativeLibraryDir(context), "lib" + libname + ".so");
|
||||
|
||||
if (fileNativeBin.exists()) {
|
||||
if (fileNativeBin.canExecute())
|
||||
return fileNativeBin;
|
||||
else {
|
||||
setExecutable(fileNativeBin);
|
||||
|
||||
if (fileNativeBin.canExecute())
|
||||
return fileNativeBin;
|
||||
}
|
||||
}
|
||||
|
||||
String folder = Build.CPU_ABI;
|
||||
|
||||
|
||||
String javaArch = System.getProperty("os.arch");
|
||||
if (javaArch != null && javaArch.contains("686")) {
|
||||
folder = "x86";
|
||||
}
|
||||
|
||||
if (loadFromZip(context, libname, destLocalFile, folder)) {
|
||||
return destLocalFile;
|
||||
}
|
||||
|
||||
} catch (Throwable e) {
|
||||
Log.e(TAG, e.getMessage(), e);
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void setExecutable(File fileBin) {
|
||||
fileBin.setReadable(true);
|
||||
fileBin.setExecutable(true);
|
||||
fileBin.setWritable(false);
|
||||
fileBin.setWritable(true, true);
|
||||
}
|
||||
|
||||
// Return Full path to the directory where native JNI libraries are stored.
|
||||
private static String getNativeLibraryDir(Context context) {
|
||||
ApplicationInfo appInfo = context.getApplicationInfo();
|
||||
return appInfo.nativeLibraryDir;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
package org.torproject.android.proxy.util;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import com.jaredrummler.android.shell.CommandResult;
|
||||
import com.jaredrummler.android.shell.Shell;
|
||||
import com.jaredrummler.android.shell.ShellExitCode;
|
||||
import com.jaredrummler.android.shell.StreamGobbler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class CustomShell extends Shell {
|
||||
|
||||
|
||||
@WorkerThread
|
||||
public static CommandResult run(@NonNull String shell, boolean waitFor, @Nullable Map<String, String> env, @NonNull String command) {
|
||||
List<String> stdout = Collections.synchronizedList(new ArrayList<>());
|
||||
List<String> stderr = Collections.synchronizedList(new ArrayList<>());
|
||||
int exitCode = -1;
|
||||
|
||||
try {
|
||||
|
||||
// setup our process, retrieve stdin stream, and stdout/stderr gobblers
|
||||
//Process process = runWithEnv(command, env);
|
||||
ProcessBuilder builder = new ProcessBuilder();
|
||||
|
||||
if (env != null && (!env.isEmpty()))
|
||||
builder.environment().putAll(env);
|
||||
|
||||
builder.command("/system/bin/" + shell, "-c", command);
|
||||
Process process = builder.start();
|
||||
|
||||
StreamGobbler stdoutGobbler = null;
|
||||
StreamGobbler stderrGobbler = null;
|
||||
|
||||
if (waitFor) {
|
||||
stdoutGobbler = new StreamGobbler(process.getInputStream(), stdout);
|
||||
stderrGobbler = new StreamGobbler(process.getErrorStream(), stderr);
|
||||
|
||||
// start gobbling and write our commands to the shell
|
||||
stdoutGobbler.start();
|
||||
stderrGobbler.start();
|
||||
}
|
||||
|
||||
// wait for our process to finish, while we gobble away in the background
|
||||
if (waitFor)
|
||||
exitCode = process.waitFor();
|
||||
else
|
||||
exitCode = 0;
|
||||
|
||||
// make sure our threads are done gobbling, our streams are closed, and the process is destroyed - while the
|
||||
// latter two shouldn't be needed in theory, and may even produce warnings, in "normal" Java they are required
|
||||
// for guaranteed cleanup of resources, so lets be safe and do this on Android as well
|
||||
/**
|
||||
try {
|
||||
stdin.close();
|
||||
} catch (IOException e) {
|
||||
// might be closed already
|
||||
}**/
|
||||
|
||||
if (waitFor) {
|
||||
stdoutGobbler.join();
|
||||
stderrGobbler.join();
|
||||
}
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
exitCode = ShellExitCode.WATCHDOG_EXIT;
|
||||
} catch (IOException e) {
|
||||
exitCode = ShellExitCode.SHELL_WRONG_UID;
|
||||
}
|
||||
|
||||
return new CommandResult(stdout, stderr, exitCode);
|
||||
}
|
||||
}
|
|
@ -1,184 +0,0 @@
|
|||
package org.torproject.android.proxy.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.util.Log;
|
||||
|
||||
import org.torproject.android.binary.TorServiceConstants;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
public class CustomTorResourceInstaller implements TorServiceConstants {
|
||||
|
||||
|
||||
private File installFolder;
|
||||
private Context context;
|
||||
|
||||
private File fileTorrc;
|
||||
private File fileTor;
|
||||
|
||||
public CustomTorResourceInstaller(Context context, File installFolder) {
|
||||
this.installFolder = installFolder;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
// Return Full path to the directory where native JNI libraries are stored.
|
||||
private static String getNativeLibraryDir(Context context) {
|
||||
ApplicationInfo appInfo = context.getApplicationInfo();
|
||||
return appInfo.nativeLibraryDir;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the inputstream contents to the file
|
||||
*/
|
||||
private static boolean streamToFile(InputStream stm, File outFile, boolean append, boolean zip) throws IOException {
|
||||
byte[] buffer = new byte[FILE_WRITE_BUFFER_SIZE];
|
||||
|
||||
int bytecount;
|
||||
|
||||
OutputStream stmOut = new FileOutputStream(outFile.getAbsolutePath(), append);
|
||||
ZipInputStream zis = null;
|
||||
|
||||
if (zip) {
|
||||
zis = new ZipInputStream(stm);
|
||||
ZipEntry ze = zis.getNextEntry();
|
||||
stm = zis;
|
||||
|
||||
}
|
||||
|
||||
while ((bytecount = stm.read(buffer)) > 0) {
|
||||
|
||||
stmOut.write(buffer, 0, bytecount);
|
||||
|
||||
}
|
||||
|
||||
stmOut.close();
|
||||
stm.close();
|
||||
|
||||
if (zis != null)
|
||||
zis.close();
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Extract the Tor binary from the APK file using ZIP
|
||||
*/
|
||||
|
||||
private static File[] listf(String directoryName) {
|
||||
|
||||
// .............list file
|
||||
File directory = new File(directoryName);
|
||||
|
||||
// get all the files from a directory
|
||||
File[] fList = directory.listFiles();
|
||||
|
||||
if (fList != null)
|
||||
for (File file : fList) {
|
||||
if (file.isFile()) {
|
||||
Log.d(TAG, file.getAbsolutePath());
|
||||
} else if (file.isDirectory()) {
|
||||
listf(file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
return fList;
|
||||
}
|
||||
|
||||
//
|
||||
/*
|
||||
* Extract the Tor resources from the APK file using ZIP
|
||||
*
|
||||
* @File path to the Tor executable
|
||||
*/
|
||||
public File installResources() throws IOException, TimeoutException {
|
||||
|
||||
fileTor = new File(installFolder, TOR_ASSET_KEY);
|
||||
|
||||
if (!installFolder.exists())
|
||||
installFolder.mkdirs();
|
||||
|
||||
installGeoIP();
|
||||
fileTorrc = assetToFile(COMMON_ASSET_KEY + TORRC_ASSET_KEY, TORRC_ASSET_KEY, false, false);
|
||||
|
||||
File fileNativeDir = new File(getNativeLibraryDir(context));
|
||||
fileTor = new File(fileNativeDir, TOR_ASSET_KEY + ".so");
|
||||
|
||||
if (fileTor.exists()) {
|
||||
if (fileTor.canExecute())
|
||||
return fileTor;
|
||||
else {
|
||||
setExecutable(fileTor);
|
||||
|
||||
if (fileTor.canExecute())
|
||||
return fileTor;
|
||||
}
|
||||
}
|
||||
|
||||
File fileTorBin = new File(installFolder, TOR_BINARY_KEY);
|
||||
|
||||
//it exists but we can't execute it, so copy it to a new path
|
||||
if (fileTor.exists()) {
|
||||
InputStream is = new FileInputStream(fileTor);
|
||||
streamToFile(is, fileTorBin, false, true);
|
||||
setExecutable(fileTorBin);
|
||||
|
||||
if (fileTorBin.exists() && fileTorBin.canExecute())
|
||||
return fileTorBin;
|
||||
}
|
||||
|
||||
//let's try another approach
|
||||
fileTor = CustomNativeLoader.loadNativeBinary(context, TOR_ASSET_KEY, fileTorBin);
|
||||
|
||||
if (fileTor != null && fileTor.exists())
|
||||
setExecutable(fileTor);
|
||||
|
||||
if (fileTor != null && fileTor.exists() && fileTor.canExecute())
|
||||
return fileTor;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean installGeoIP() throws IOException {
|
||||
|
||||
assetToFile(COMMON_ASSET_KEY + GEOIP_ASSET_KEY, GEOIP_ASSET_KEY, false, false);
|
||||
|
||||
assetToFile(COMMON_ASSET_KEY + GEOIP6_ASSET_KEY, GEOIP6_ASSET_KEY, false, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads file from assetPath/assetKey writes it to the install folder
|
||||
*/
|
||||
private File assetToFile(String assetPath, String assetKey, boolean isZipped, boolean isExecutable) throws IOException {
|
||||
InputStream is = context.getAssets().open(assetPath);
|
||||
File outFile = new File(installFolder, assetKey);
|
||||
streamToFile(is, outFile, false, isZipped);
|
||||
if (isExecutable) {
|
||||
setExecutable(outFile);
|
||||
}
|
||||
return outFile;
|
||||
}
|
||||
|
||||
private void setExecutable(File fileBin) {
|
||||
fileBin.setReadable(true);
|
||||
fileBin.setExecutable(true);
|
||||
fileBin.setWritable(false);
|
||||
fileBin.setWritable(true, true);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
package org.torproject.android.proxy.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
|
||||
/*
|
||||
* To combat background service being stopped/swiped
|
||||
*/
|
||||
public class DummyActivity extends Activity {
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
finish();
|
||||
}
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
package org.torproject.android.proxy.util;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.torproject.android.proxy.OrbotService;
|
||||
import org.torproject.android.proxy.TorEventHandler;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
|
||||
public class ExternalIPFetcher implements Runnable {
|
||||
|
||||
private final static String ONIONOO_BASE_URL = "https://onionoo.torproject.org/details?fields=country_name,as_name,or_addresses&lookup=";
|
||||
private OrbotService mService;
|
||||
private TorEventHandler.Node mNode;
|
||||
private int mLocalHttpProxyPort = 8125;
|
||||
|
||||
public ExternalIPFetcher(OrbotService service, TorEventHandler.Node node, int localProxyPort) {
|
||||
mService = service;
|
||||
mNode = node;
|
||||
mLocalHttpProxyPort = localProxyPort;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
|
||||
URLConnection conn;
|
||||
|
||||
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", mLocalHttpProxyPort));
|
||||
conn = new URL(ONIONOO_BASE_URL + mNode.id).openConnection(proxy);
|
||||
|
||||
conn.setRequestProperty("Connection", "Close");
|
||||
conn.setConnectTimeout(60000);
|
||||
conn.setReadTimeout(60000);
|
||||
|
||||
InputStream is = conn.getInputStream();
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||
|
||||
// getting JSON string from URL
|
||||
|
||||
StringBuffer json = new StringBuffer();
|
||||
String line;
|
||||
|
||||
while ((line = reader.readLine()) != null)
|
||||
json.append(line);
|
||||
|
||||
JSONObject jsonNodeInfo = new org.json.JSONObject(json.toString());
|
||||
|
||||
JSONArray jsonRelays = jsonNodeInfo.getJSONArray("relays");
|
||||
|
||||
if (jsonRelays.length() > 0) {
|
||||
mNode.ipAddress = jsonRelays.getJSONObject(0).getJSONArray("or_addresses").getString(0).split(":")[0];
|
||||
mNode.country = jsonRelays.getJSONObject(0).getString("country_name");
|
||||
mNode.organization = jsonRelays.getJSONObject(0).getString("as_name");
|
||||
|
||||
StringBuffer sbInfo = new StringBuffer();
|
||||
sbInfo.append(mNode.name).append("(");
|
||||
sbInfo.append(mNode.ipAddress).append(")");
|
||||
|
||||
if (mNode.country != null)
|
||||
sbInfo.append(' ').append(mNode.country);
|
||||
|
||||
if (mNode.organization != null)
|
||||
sbInfo.append(" (").append(mNode.organization).append(')');
|
||||
|
||||
mService.debug(sbInfo.toString());
|
||||
|
||||
}
|
||||
|
||||
reader.close();
|
||||
is.close();
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
// mService.debug ("Error getting node details from onionoo: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
package org.torproject.android.proxy.util;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
public class NativeLoader {
|
||||
|
||||
private final static String TAG = "TorNativeLoader";
|
||||
|
||||
@SuppressLint("SetWorldReadable")
|
||||
private static boolean loadFromZip(Context context, String libName, File destLocalFile, String folder) {
|
||||
|
||||
|
||||
ZipFile zipFile = null;
|
||||
InputStream stream = null;
|
||||
try {
|
||||
zipFile = new ZipFile(context.getApplicationInfo().sourceDir);
|
||||
|
||||
/**
|
||||
Enumeration<? extends ZipEntry> entries = zipFile.entries();
|
||||
while (entries.hasMoreElements())
|
||||
{
|
||||
ZipEntry entry = entries.nextElement();
|
||||
Log.d("Zip","entry: " + entry.getName());
|
||||
}
|
||||
**/
|
||||
|
||||
ZipEntry entry = zipFile.getEntry("lib/" + folder + "/" + libName + ".so");
|
||||
if (entry == null) {
|
||||
entry = zipFile.getEntry("lib/" + folder + "/" + libName);
|
||||
if (entry == null)
|
||||
throw new Exception("Unable to find file in apk:" + "lib/" + folder + "/" + libName);
|
||||
}
|
||||
stream = zipFile.getInputStream(entry);
|
||||
|
||||
OutputStream out = new FileOutputStream(destLocalFile);
|
||||
byte[] buf = new byte[4096];
|
||||
int len;
|
||||
while ((len = stream.read(buf)) > 0) {
|
||||
Thread.yield();
|
||||
out.write(buf, 0, len);
|
||||
}
|
||||
out.close();
|
||||
|
||||
destLocalFile.setReadable(true, false);
|
||||
destLocalFile.setExecutable(true, false);
|
||||
destLocalFile.setWritable(true);
|
||||
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
} finally {
|
||||
if (stream != null) {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
}
|
||||
}
|
||||
if (zipFile != null) {
|
||||
try {
|
||||
zipFile.close();
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static synchronized boolean initNativeLibs(Context context, String binaryName, File destLocalFile) {
|
||||
|
||||
try {
|
||||
String folder = Build.CPU_ABI;
|
||||
|
||||
String javaArch = System.getProperty("os.arch");
|
||||
if (javaArch != null && javaArch.contains("686")) {
|
||||
folder = "x86";
|
||||
}
|
||||
|
||||
return loadFromZip(context, binaryName, destLocalFile, folder);
|
||||
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
package org.torproject.android.proxy.util;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.offbynull.portmapper.PortMapperFactory;
|
||||
import com.offbynull.portmapper.gateway.Bus;
|
||||
import com.offbynull.portmapper.gateway.Gateway;
|
||||
import com.offbynull.portmapper.gateways.network.NetworkGateway;
|
||||
import com.offbynull.portmapper.gateways.network.internalmessages.KillNetworkRequest;
|
||||
import com.offbynull.portmapper.gateways.process.ProcessGateway;
|
||||
import com.offbynull.portmapper.gateways.process.internalmessages.KillProcessRequest;
|
||||
import com.offbynull.portmapper.mapper.MappedPort;
|
||||
import com.offbynull.portmapper.mapper.PortMapper;
|
||||
import com.offbynull.portmapper.mapper.PortType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class PortForwarder {
|
||||
|
||||
private boolean shutdown = false;
|
||||
private Thread mThread = null;
|
||||
|
||||
public void shutdown() {
|
||||
shutdown = true;
|
||||
}
|
||||
|
||||
public void forward(final int internalPort, final int externalPort, final long lifetime) throws InterruptedException {
|
||||
|
||||
mThread = new Thread() {
|
||||
public void run() {
|
||||
try {
|
||||
forwardSync(internalPort, externalPort, lifetime);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
mThread.start();
|
||||
}
|
||||
|
||||
|
||||
public void forwardSync(int internalPort, int externalPort, long lifetime) throws InterruptedException {
|
||||
// Start gateways
|
||||
Gateway network = NetworkGateway.create();
|
||||
Gateway process = ProcessGateway.create();
|
||||
Bus networkBus = network.getBus();
|
||||
Bus processBus = process.getBus();
|
||||
|
||||
// Discover port forwarding devices and take the first one found
|
||||
List<PortMapper> mappers = PortMapperFactory.discover(networkBus, processBus);
|
||||
PortMapper mapper = mappers.get(0);
|
||||
|
||||
// Map internal port 12345 to some external port (55555 preferred)
|
||||
//
|
||||
// IMPORTANT NOTE: Many devices prevent you from mapping ports that are <= 1024
|
||||
// (both internal and external ports). Be mindful of this when choosing which
|
||||
// ports you want to map.
|
||||
MappedPort mappedPort = mapper.mapPort(PortType.TCP, internalPort, externalPort, lifetime);
|
||||
Log.d(getClass().getName(), "Port mapping added: " + mappedPort);
|
||||
|
||||
// Refresh mapping half-way through the lifetime of the mapping (for example,
|
||||
// if the mapping is available for 40 seconds, refresh it every 20 seconds)
|
||||
while (!shutdown) {
|
||||
mappedPort = mapper.refreshPort(mappedPort, mappedPort.getLifetime() / 2L);
|
||||
Log.d(getClass().getName(), "Port mapping refreshed: " + mappedPort);
|
||||
Thread.sleep(mappedPort.getLifetime() * 1000L);
|
||||
}
|
||||
|
||||
// Unmap port 12345
|
||||
mapper.unmapPort(mappedPort);
|
||||
|
||||
// Stop gateways
|
||||
networkBus.send(new KillNetworkRequest());
|
||||
processBus.send(new KillProcessRequest()); // can kill this after discovery
|
||||
}
|
||||
}
|
|
@ -1,143 +0,0 @@
|
|||
package org.torproject.android.proxy.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import org.torproject.android.proxy.OrbotConstants;
|
||||
import org.torproject.android.proxy.wrapper.orbotLocalConstants;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class Prefs {
|
||||
|
||||
private final static String PREF_BRIDGES_ENABLED = "pref_bridges_enabled";
|
||||
private final static String PREF_BRIDGES_LIST = "pref_bridges_list";
|
||||
private final static String PREF_DEFAULT_LOCALE = "pref_default_locale";
|
||||
private final static String PREF_ENABLE_LOGGING = "pref_enable_logging";
|
||||
private final static String PREF_EXPANDED_NOTIFICATIONS = "pref_expanded_notifications";
|
||||
private final static String PREF_PERSIST_NOTIFICATIONS = "pref_persistent_notifications";
|
||||
private final static String PREF_START_ON_BOOT = "pref_start_boot";
|
||||
private final static String PREF_ALLOW_BACKGROUND_STARTS = "pref_allow_background_starts";
|
||||
private final static String PREF_OPEN_PROXY_ON_ALL_INTERFACES = "pref_open_proxy_on_all_interfaces";
|
||||
private final static String PREF_USE_VPN = "pref_vpn";
|
||||
private final static String PREF_EXIT_NODES = "pref_exit_nodes";
|
||||
private final static String PREF_BE_A_SNOWFLAKE = "pref_be_a_snowflake";
|
||||
|
||||
private static SharedPreferences prefs;
|
||||
|
||||
public static void setContext(Context context) {
|
||||
if (prefs == null)
|
||||
prefs = getSharedPrefs(context);
|
||||
}
|
||||
|
||||
private static void putBoolean(String key, boolean value) {
|
||||
prefs.edit().putBoolean(key, value).apply();
|
||||
}
|
||||
|
||||
private static void putString(String key, String value) {
|
||||
prefs.edit().putString(key, value).apply();
|
||||
}
|
||||
|
||||
public static boolean bridgesEnabled() {
|
||||
//if phone is in Farsi, enable bridges by default
|
||||
boolean bridgesEnabledDefault = Locale.getDefault().getLanguage().equals("fa");
|
||||
return prefs.getBoolean(PREF_BRIDGES_ENABLED, bridgesEnabledDefault);
|
||||
}
|
||||
|
||||
public static void putBridgesEnabled(boolean value) {
|
||||
putBoolean(PREF_BRIDGES_ENABLED, value);
|
||||
}
|
||||
|
||||
public static String getBridgesList() {
|
||||
String defaultBridgeType = "obfs4";
|
||||
if (Locale.getDefault().getLanguage().equals("fa"))
|
||||
defaultBridgeType = "meek"; //if Farsi, use meek as the default bridge type
|
||||
if(orbotLocalConstants.mIsManualBridge){
|
||||
if(!orbotLocalConstants.mManualBridgeType.equals("")){
|
||||
defaultBridgeType = orbotLocalConstants.mManualBridgeType;
|
||||
putString(PREF_BRIDGES_LIST, defaultBridgeType);
|
||||
return defaultBridgeType;
|
||||
}
|
||||
}else {
|
||||
if(orbotLocalConstants.mBridges.equals("obfs4")){
|
||||
defaultBridgeType = "obfs4";
|
||||
putString(PREF_BRIDGES_LIST, defaultBridgeType);
|
||||
return defaultBridgeType;
|
||||
}else if(orbotLocalConstants.mBridges.equals("meek")){
|
||||
defaultBridgeType = "meek";
|
||||
putString(PREF_BRIDGES_LIST, defaultBridgeType);
|
||||
return defaultBridgeType;
|
||||
}
|
||||
}
|
||||
|
||||
return prefs.getString(PREF_BRIDGES_LIST, defaultBridgeType);
|
||||
}
|
||||
|
||||
public static void setBridgesList(String value) {
|
||||
putString(PREF_BRIDGES_LIST, value);
|
||||
}
|
||||
|
||||
public static String getDefaultLocale() {
|
||||
return prefs.getString(PREF_DEFAULT_LOCALE, Locale.getDefault().getLanguage());
|
||||
}
|
||||
|
||||
public static boolean beSnowflakeProxy () {
|
||||
return prefs.getBoolean(PREF_BE_A_SNOWFLAKE,false);
|
||||
}
|
||||
|
||||
public static void setBeSnowflakeProxy (boolean beSnowflakeProxy) {
|
||||
putBoolean(PREF_BE_A_SNOWFLAKE,beSnowflakeProxy);
|
||||
}
|
||||
|
||||
public static void setDefaultLocale(String value) {
|
||||
putString(PREF_DEFAULT_LOCALE, value);
|
||||
}
|
||||
|
||||
public static boolean expandedNotifications() {
|
||||
return prefs.getBoolean(PREF_EXPANDED_NOTIFICATIONS, true);
|
||||
}
|
||||
|
||||
public static boolean useDebugLogging() {
|
||||
return false;//prefs.getBoolean(PREF_ENABLE_LOGGING, false);
|
||||
}
|
||||
|
||||
public static boolean persistNotifications() {
|
||||
return prefs.getBoolean(PREF_PERSIST_NOTIFICATIONS, true);
|
||||
}
|
||||
|
||||
public static boolean allowBackgroundStarts() {
|
||||
return prefs.getBoolean(PREF_ALLOW_BACKGROUND_STARTS, true);
|
||||
}
|
||||
|
||||
public static boolean openProxyOnAllInterfaces() {
|
||||
return prefs.getBoolean(PREF_OPEN_PROXY_ON_ALL_INTERFACES, false);
|
||||
}
|
||||
|
||||
public static boolean useVpn() {
|
||||
return prefs.getBoolean(PREF_USE_VPN, false);
|
||||
}
|
||||
|
||||
public static void putUseVpn(boolean value) {
|
||||
putBoolean(PREF_USE_VPN, value);
|
||||
}
|
||||
|
||||
public static boolean startOnBoot() {
|
||||
return prefs.getBoolean(PREF_START_ON_BOOT, true);
|
||||
}
|
||||
|
||||
public static void putStartOnBoot(boolean value) {
|
||||
putBoolean(PREF_START_ON_BOOT, value);
|
||||
}
|
||||
|
||||
public static String getExitNodes() {
|
||||
return prefs.getString(PREF_EXIT_NODES, "");
|
||||
}
|
||||
|
||||
public static void setExitNodes(String exits) {
|
||||
putString(PREF_EXIT_NODES, exits);
|
||||
}
|
||||
|
||||
public static SharedPreferences getSharedPrefs(Context context) {
|
||||
return context.getSharedPreferences(OrbotConstants.PREF_TOR_SHARED_PREFS, Context.MODE_MULTI_PROCESS);
|
||||
}
|
||||
}
|
|
@ -1,307 +0,0 @@
|
|||
package org.torproject.android.proxy.util;
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright (c) 2013, Sebastiano Gottardo
|
||||
* All rights reserved.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the MegaDevs nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEBASTIANO GOTTARDO BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Main class for the TCPSourceApp library.
|
||||
*
|
||||
* @author Sebastiano Gottardo
|
||||
*/
|
||||
public class TCPSourceApp {
|
||||
|
||||
/*
|
||||
* In a Linux-based OS, each active TCP socket is mapped in the following
|
||||
* two files. A socket may be mapped in the '/proc/net/tcp' file in case
|
||||
* of a simple IPv4 address, or in the '/proc/net/tcp6' if an IPv6 address
|
||||
* is available.
|
||||
*/
|
||||
private static final String TCP_4_FILE_PATH = "/proc/net/tcp";
|
||||
private static final String TCP_6_FILE_PATH = "/proc/net/tcp6";
|
||||
/*
|
||||
* Two regular expressions that are able to extract valuable informations
|
||||
* from the two /proc/net/tcp* files. More specifically, there are three
|
||||
* fields that are extracted:
|
||||
* - address
|
||||
* - port
|
||||
* - PID
|
||||
*/
|
||||
private static final String TCP_6_PATTERN = "\\d+:\\s([0-9A-F]{32}):([0-9A-F]{4})\\s[0-9A-F]{32}:[0-9A-F]{4}\\s[0-9A-F]{2}\\s[0-9]{8}:[0-9]{8}\\s[0-9]{2}:[0-9]{8}\\s[0-9]{8}\\s+([0-9]+)";
|
||||
private static final String TCP_4_PATTERN = "\\d+:\\s([0-9A-F]{8}):([0-9A-F]{4})\\s[0-9A-F]{8}:[0-9A-F]{4}\\s[0-9A-F]{2}\\s[0-9A-F]{8}:[0-9A-F]{8}\\s[0-9]{2}:[0-9]{8}\\s[0-9A-F]{8}\\s+([0-9]+)";
|
||||
//sargo:/ $ cat /proc/net/tcp6
|
||||
// sl local_address remote_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
|
||||
// 0: 00000000000000000000000000000000:C36A 00000000000000000000000000000000:0000 8A 00000000:00000000 00:00000000 00000000 1001 0 35059 1 0000000000000000 99 0 0 10 0
|
||||
// 1: 00000000000000000000000000000000:A64B 00000000000000000000000000000000:0000 8A 00000000:00000000 00:00000000 00000000 1001 0 910009 1 0000000000000000 99 0 0 10 0
|
||||
/*
|
||||
* Optimises the socket lookup by checking if the connected network
|
||||
* interface has a 'valid' IPv6 address (a global address, not a link-local
|
||||
* one).
|
||||
*/
|
||||
private static boolean checkConnectedIfaces = true;
|
||||
// sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
|
||||
// 0: 00000000:C368 00000000:0000 8A 00000000:00000000 00:00000000 00000000 1001 0 34999 1 0000000000000000 99 0 0 10 0
|
||||
|
||||
/**
|
||||
* The main method of the TCPSourceApp library. This method receives an
|
||||
* Android Context instance, which is used to access the PackageManager.
|
||||
* It parses the /proc/net/tcp* files, looking for a socket entry that
|
||||
* matches the given port. If it finds an entry, this method extracts the
|
||||
* PID value and it uses the PackageManager.getPackagesFromPid() method to
|
||||
* find the originating application.
|
||||
*
|
||||
* @param context a valid Android Context instance
|
||||
* @param daddr the (logical) address of the destination
|
||||
* @param dport the (logical) port of the destination
|
||||
* @return an AppDescriptor object, representing the found application; null
|
||||
* if no application could be found
|
||||
*/
|
||||
public static AppDescriptor getApplicationInfo(Context context, String saddr, int sport, String daddr, int dport) {
|
||||
|
||||
File tcp;
|
||||
BufferedReader reader;
|
||||
String line;
|
||||
StringBuilder builder;
|
||||
String content;
|
||||
|
||||
try {
|
||||
boolean hasIPv6 = true;
|
||||
|
||||
// if true, checks for a connected network interface with a valid
|
||||
// IPv4 / IPv6 address
|
||||
if (checkConnectedIfaces) {
|
||||
String ipv4Address = getIPAddress(true);
|
||||
String ipv6Address = getIPAddress(false);
|
||||
|
||||
hasIPv6 = (ipv6Address.length() > 0);
|
||||
}
|
||||
|
||||
tcp = new File(TCP_6_FILE_PATH);
|
||||
reader = new BufferedReader(new FileReader(tcp));
|
||||
builder = new StringBuilder();
|
||||
|
||||
while ((line = reader.readLine()) != null) {
|
||||
builder.append(line);
|
||||
}
|
||||
|
||||
content = builder.toString();
|
||||
|
||||
Matcher m6 = Pattern.compile(TCP_6_PATTERN, Pattern.CASE_INSENSITIVE | Pattern.UNIX_LINES | Pattern.DOTALL).matcher(content);
|
||||
|
||||
if (hasIPv6)
|
||||
while (m6.find()) {
|
||||
String addressEntry = m6.group(1);
|
||||
String portEntry = m6.group(2);
|
||||
int pidEntry = Integer.valueOf(m6.group(3));
|
||||
|
||||
if (Integer.parseInt(portEntry, 16) == dport) {
|
||||
PackageManager manager = context.getPackageManager();
|
||||
String[] packagesForUid = manager.getPackagesForUid(pidEntry);
|
||||
|
||||
if (packagesForUid != null) {
|
||||
String packageName = packagesForUid[0];
|
||||
PackageInfo pInfo = manager.getPackageInfo(packageName, 0);
|
||||
String version = pInfo.versionName;
|
||||
|
||||
return new AppDescriptor(pidEntry, packageName, version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// From here, no connection with the given port could be found in the tcp6 file
|
||||
// So let's try the tcp (IPv4) one
|
||||
|
||||
try {
|
||||
tcp = new File(TCP_4_FILE_PATH);
|
||||
reader = new BufferedReader(new FileReader(tcp));
|
||||
builder = new StringBuilder();
|
||||
|
||||
while ((line = reader.readLine()) != null) {
|
||||
builder.append(line);
|
||||
}
|
||||
|
||||
content = builder.toString();
|
||||
|
||||
Matcher m4 = Pattern.compile(TCP_4_PATTERN, Pattern.CASE_INSENSITIVE | Pattern.UNIX_LINES | Pattern.DOTALL).matcher(content);
|
||||
|
||||
while (m4.find()) {
|
||||
String addressEntry = m4.group(1);
|
||||
String portEntry = m4.group(2);
|
||||
int pidEntry = Integer.valueOf(m4.group(3));
|
||||
|
||||
if (Integer.parseInt(portEntry, 16) == dport) {
|
||||
PackageManager manager = context.getPackageManager();
|
||||
String[] packagesForUid = manager.getPackagesForUid(pidEntry);
|
||||
|
||||
if (packagesForUid != null) {
|
||||
String packageName = packagesForUid[0];
|
||||
PackageInfo pInfo = manager.getPackageInfo(packageName, 0);
|
||||
String version = pInfo.versionName;
|
||||
|
||||
return new AppDescriptor(pidEntry, packageName, version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressLint("DefaultLocale")
|
||||
public static String getIPAddress(boolean useIPv4) throws SocketException {
|
||||
|
||||
List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
|
||||
|
||||
for (NetworkInterface intf : interfaces) {
|
||||
List<InetAddress> addrs = Collections.list(intf.getInetAddresses());
|
||||
|
||||
for (InetAddress addr : addrs) {
|
||||
if (!addr.isLoopbackAddress()) {
|
||||
String sAddr = addr.getHostAddress().toUpperCase();
|
||||
|
||||
boolean isIPv4 = addr instanceof Inet4Address;
|
||||
|
||||
if (useIPv4) {
|
||||
if (isIPv4)
|
||||
return sAddr;
|
||||
} else {
|
||||
if (!isIPv4) {
|
||||
if (sAddr.startsWith("fe80") || sAddr.startsWith("FE80")) // skipping link-local addresses
|
||||
continue;
|
||||
|
||||
int delim = sAddr.indexOf('%'); // drop ip6 port suffix
|
||||
return delim < 0 ? sAddr : sAddr.substring(0, delim);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the connected interfaces optimisation.
|
||||
*/
|
||||
public static void setCheckConnectedIfaces(boolean value) {
|
||||
checkConnectedIfaces = value;
|
||||
}
|
||||
|
||||
/*
|
||||
* This class represents an Android application. Each application is
|
||||
* uniquely identified by its package name (e.g. com.megadevs.tcpsourceapp)
|
||||
* and its version (e.g. 1.0).
|
||||
*/
|
||||
public static class AppDescriptor {
|
||||
|
||||
private String packageName;
|
||||
private String version;
|
||||
private int uid;
|
||||
|
||||
public AppDescriptor(int uid, String pName, String ver) {
|
||||
this.uid = uid;
|
||||
packageName = pName;
|
||||
version = ver;
|
||||
}
|
||||
|
||||
public int getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public String getPackageName() {
|
||||
return packageName;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
/*
|
||||
* Override of the 'equals' method, in order to have a proper
|
||||
* comparison between two AppDescriptor objects.
|
||||
*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
|
||||
if (o instanceof AppDescriptor) {
|
||||
boolean c1 = ((AppDescriptor) o).packageName.compareTo(this.packageName) == 0;
|
||||
boolean c2 = ((AppDescriptor) o).version.compareTo(this.version) == 0;
|
||||
|
||||
return c1 && c2;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
/* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */
|
||||
/* See LICENSE for licensing information */
|
||||
package org.torproject.android.proxy.util;
|
||||
|
||||
import org.torproject.android.proxy.TorServiceConstants;
|
||||
|
||||
import java.net.ConnectException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
|
||||
public class TorServiceUtils implements TorServiceConstants {
|
||||
|
||||
public static boolean isPortOpen(final String ip, final int port, final int timeout) {
|
||||
try {
|
||||
Socket socket = new Socket();
|
||||
socket.connect(new InetSocketAddress(ip, port), timeout);
|
||||
socket.close();
|
||||
return true;
|
||||
} catch (ConnectException ce) {
|
||||
//ce.printStackTrace();
|
||||
return false;
|
||||
} catch (Exception ex) {
|
||||
//ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,183 +0,0 @@
|
|||
/* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
|
||||
package org.torproject.android.proxy.util;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
public class Utils {
|
||||
|
||||
|
||||
public static String readString(InputStream stream) {
|
||||
String line;
|
||||
|
||||
StringBuffer out = new StringBuffer();
|
||||
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
|
||||
|
||||
while ((line = reader.readLine()) != null) {
|
||||
out.append(line);
|
||||
out.append('\n');
|
||||
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return out.toString();
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Load the log file text
|
||||
*/
|
||||
public static String loadTextFile(String path) {
|
||||
String line;
|
||||
|
||||
StringBuffer out = new StringBuffer();
|
||||
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader((new FileReader(new File(path))));
|
||||
|
||||
while ((line = reader.readLine()) != null) {
|
||||
out.append(line);
|
||||
out.append('\n');
|
||||
|
||||
}
|
||||
|
||||
reader.close();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return out.toString();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Load the log file text
|
||||
*/
|
||||
public static boolean saveTextFile(String path, String contents) {
|
||||
|
||||
try {
|
||||
|
||||
FileWriter writer = new FileWriter(path, false);
|
||||
writer.write(contents);
|
||||
|
||||
writer.close();
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
} catch (IOException e) {
|
||||
// Log.d(TAG, "error writing file: " + path, e);
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Zips a file at a location and places the resulting zip file at the toLocation
|
||||
* Example: zipFileAtPath("downloads/myfolder", "downloads/myFolder.zip");
|
||||
*/
|
||||
|
||||
public static boolean zipFileAtPath(String sourcePath, String toLocation) {
|
||||
final int BUFFER = 2048;
|
||||
|
||||
File sourceFile = new File(sourcePath);
|
||||
try {
|
||||
BufferedInputStream origin;
|
||||
FileOutputStream dest = new FileOutputStream(toLocation);
|
||||
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(
|
||||
dest));
|
||||
if (sourceFile.isDirectory()) {
|
||||
zipSubFolder(out, sourceFile, sourceFile.getParent().length());
|
||||
} else {
|
||||
byte[] data = new byte[BUFFER];
|
||||
FileInputStream fi = new FileInputStream(sourcePath);
|
||||
origin = new BufferedInputStream(fi, BUFFER);
|
||||
ZipEntry entry = new ZipEntry(getLastPathComponent(sourcePath));
|
||||
entry.setTime(sourceFile.lastModified()); // to keep modification time after unzipping
|
||||
out.putNextEntry(entry);
|
||||
int count;
|
||||
while ((count = origin.read(data, 0, BUFFER)) != -1) {
|
||||
out.write(data, 0, count);
|
||||
}
|
||||
}
|
||||
out.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Zips a subfolder
|
||||
*
|
||||
*/
|
||||
|
||||
private static void zipSubFolder(ZipOutputStream out, File folder,
|
||||
int basePathLength) throws IOException {
|
||||
|
||||
final int BUFFER = 2048;
|
||||
|
||||
File[] fileList = folder.listFiles();
|
||||
BufferedInputStream origin;
|
||||
for (File file : fileList) {
|
||||
if (file.isDirectory()) {
|
||||
zipSubFolder(out, file, basePathLength);
|
||||
} else {
|
||||
byte[] data = new byte[BUFFER];
|
||||
String unmodifiedFilePath = file.getPath();
|
||||
String relativePath = unmodifiedFilePath
|
||||
.substring(basePathLength);
|
||||
FileInputStream fi = new FileInputStream(unmodifiedFilePath);
|
||||
origin = new BufferedInputStream(fi, BUFFER);
|
||||
ZipEntry entry = new ZipEntry(relativePath);
|
||||
entry.setTime(file.lastModified()); // to keep modification time after unzipping
|
||||
out.putNextEntry(entry);
|
||||
int count;
|
||||
while ((count = origin.read(data, 0, BUFFER)) != -1) {
|
||||
out.write(data, 0, count);
|
||||
}
|
||||
origin.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* gets the last path component
|
||||
*
|
||||
* Example: getLastPathComponent("downloads/example/fileToZip");
|
||||
* Result: "fileToZip"
|
||||
*/
|
||||
public static String getLastPathComponent(String filePath) {
|
||||
String[] segments = filePath.split("/");
|
||||
if (segments.length == 0)
|
||||
return "";
|
||||
return segments[segments.length - 1];
|
||||
}
|
||||
}
|
|
@ -1,408 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.torproject.android.proxy.vpn;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.net.VpnService;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.runjva.sourceforge.jsocks.protocol.ProxyServer;
|
||||
import com.runjva.sourceforge.jsocks.server.ServerAuthenticatorNone;
|
||||
|
||||
import org.torproject.android.proxy.OrbotConstants;
|
||||
import org.torproject.android.proxy.OrbotService;
|
||||
import org.torproject.android.proxy.TorServiceConstants;
|
||||
import org.torproject.android.proxy.util.CustomNativeLoader;
|
||||
import org.torproject.android.proxy.util.Prefs;
|
||||
import org.torproject.android.service.R;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintStream;
|
||||
import java.net.InetAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import static org.torproject.android.proxy.TorServiceConstants.ACTION_START;
|
||||
import static org.torproject.android.proxy.TorServiceConstants.ACTION_START_VPN;
|
||||
import static org.torproject.android.proxy.TorServiceConstants.ACTION_STOP_VPN;
|
||||
|
||||
public class OrbotVpnManager implements Handler.Callback {
|
||||
private static final String TAG = "OrbotVpnService";
|
||||
private final static int VPN_MTU = 1500;
|
||||
private final static boolean mIsLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
|
||||
private final static String PDNSD_BIN = "pdnsd";
|
||||
public static int sSocksProxyServerPort = -1;
|
||||
public static String sSocksProxyLocalhost = null;
|
||||
boolean isStarted = false;
|
||||
|
||||
File filePdnsPid;
|
||||
private Thread mThreadVPN;
|
||||
private final static String mSessionName = "OrbotVPN";
|
||||
private ParcelFileDescriptor mInterface;
|
||||
private int mTorSocks = -1;
|
||||
private int mTorDns = -1;
|
||||
private int pdnsdPort = 8091;
|
||||
private ProxyServer mSocksProxyServer;
|
||||
private final File filePdnsd;
|
||||
private boolean isRestart = false;
|
||||
private final VpnService mService;
|
||||
|
||||
public OrbotVpnManager(VpnService service) {
|
||||
mService = service;
|
||||
filePdnsd = CustomNativeLoader.loadNativeBinary(service.getApplicationContext(), PDNSD_BIN, new File(service.getFilesDir(), PDNSD_BIN));
|
||||
Tun2Socks.init();
|
||||
}
|
||||
|
||||
public static File makePdnsdConf(Context context, File fileDir, String torDnsHost, int torDnsPort, String pdnsdHost, int pdnsdPort) throws IOException {
|
||||
String conf = String.format(context.getString(R.string.pdnsd_conf), torDnsHost, torDnsPort, fileDir.getCanonicalPath(), pdnsdHost, pdnsdPort);
|
||||
|
||||
Log.d(TAG, "pdsnd conf:" + conf);
|
||||
|
||||
File fPid = new File(fileDir, pdnsdPort + "pdnsd.conf");
|
||||
|
||||
if (fPid.exists()) {
|
||||
fPid.delete();
|
||||
}
|
||||
|
||||
FileOutputStream fos = new FileOutputStream(fPid, false);
|
||||
PrintStream ps = new PrintStream(fos);
|
||||
ps.print(conf);
|
||||
ps.close();
|
||||
|
||||
File cache = new File(fileDir, "pdnsd.cache");
|
||||
|
||||
if (!cache.exists()) {
|
||||
try {
|
||||
cache.createNewFile();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
return fPid;
|
||||
}
|
||||
|
||||
public int handleIntent(VpnService.Builder builder, Intent intent) {
|
||||
if (intent != null) {
|
||||
String action = intent.getAction();
|
||||
|
||||
if (action != null) {
|
||||
if (action.equals(ACTION_START_VPN) || action.equals(ACTION_START)) {
|
||||
Log.d(TAG, "starting VPN");
|
||||
|
||||
isStarted = true;
|
||||
|
||||
// Stop the previous session by interrupting the thread.
|
||||
if (mThreadVPN != null && mThreadVPN.isAlive())
|
||||
stopVPN();
|
||||
|
||||
if (mTorSocks != -1) {
|
||||
if (!mIsLollipop) {
|
||||
startSocksBypass();
|
||||
}
|
||||
|
||||
setupTun2Socks(builder);
|
||||
}
|
||||
|
||||
} else if (action.equals(ACTION_STOP_VPN)) {
|
||||
isStarted = false;
|
||||
|
||||
Log.d(TAG, "stopping VPN");
|
||||
|
||||
stopVPN();
|
||||
} else if (action.equals(TorServiceConstants.LOCAL_ACTION_PORTS)) {
|
||||
Log.d(TAG, "setting VPN ports");
|
||||
|
||||
int torSocks = intent.getIntExtra(OrbotService.EXTRA_SOCKS_PROXY_PORT, -1);
|
||||
int torDns = intent.getIntExtra(OrbotService.EXTRA_DNS_PORT, -1);
|
||||
|
||||
//if running, we need to restart
|
||||
if ((torSocks != mTorSocks || torDns != mTorDns)) {
|
||||
|
||||
mTorSocks = torSocks;
|
||||
mTorDns = torDns;
|
||||
|
||||
if (!mIsLollipop) {
|
||||
stopSocksBypass();
|
||||
startSocksBypass();
|
||||
}
|
||||
|
||||
setupTun2Socks(builder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return Service.START_STICKY;
|
||||
}
|
||||
|
||||
private void startSocksBypass() {
|
||||
new Thread() {
|
||||
public void run() {
|
||||
|
||||
//generate the proxy port that the
|
||||
if (sSocksProxyServerPort == -1) {
|
||||
try {
|
||||
|
||||
sSocksProxyLocalhost = "127.0.0.1";// InetAddress.getLocalHost().getHostAddress();
|
||||
sSocksProxyServerPort = (int) ((Math.random() * 1000) + 10000);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Unable to access localhost", e);
|
||||
throw new RuntimeException("Unable to access localhost: " + e);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (mSocksProxyServer != null) {
|
||||
stopSocksBypass();
|
||||
}
|
||||
|
||||
try {
|
||||
mSocksProxyServer = new ProxyServer(new ServerAuthenticatorNone(null, null));
|
||||
ProxyServer.setVpnService(mService);
|
||||
mSocksProxyServer.start(sSocksProxyServerPort, 5, InetAddress.getLocalHost());
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "error getting host", e);
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
private synchronized void stopSocksBypass() {
|
||||
if (mSocksProxyServer != null) {
|
||||
mSocksProxyServer.stop();
|
||||
mSocksProxyServer = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void stopVPN() {
|
||||
if (mIsLollipop)
|
||||
stopSocksBypass();
|
||||
|
||||
Tun2Socks.Stop();
|
||||
|
||||
if (mInterface != null) {
|
||||
try {
|
||||
Log.d(TAG, "closing interface, destroying VPN interface");
|
||||
|
||||
mInterface.close();
|
||||
mInterface = null;
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, "error stopping tun2socks", e);
|
||||
} catch (Error e) {
|
||||
Log.d(TAG, "error stopping tun2socks", e);
|
||||
}
|
||||
}
|
||||
stopDns();
|
||||
mThreadVPN = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleMessage(Message message) {
|
||||
if (message != null) {
|
||||
Toast.makeText(mService, message.what, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private synchronized void setupTun2Socks(final VpnService.Builder builder) {
|
||||
if (mInterface != null) //stop tun2socks now to give it time to clean up
|
||||
{
|
||||
isRestart = true;
|
||||
Tun2Socks.Stop();
|
||||
|
||||
stopDns();
|
||||
|
||||
}
|
||||
|
||||
mThreadVPN = new Thread() {
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
|
||||
if (isRestart) {
|
||||
Log.d(TAG, "is a restart... let's wait for a few seconds");
|
||||
Thread.sleep(3000);
|
||||
}
|
||||
|
||||
final String vpnName = "GenesisVPN";
|
||||
final String localhost = "127.0.0.1";
|
||||
|
||||
final String virtualGateway = "10.10.10.1";
|
||||
final String virtualIP = "10.10.10.2";
|
||||
final String virtualNetMask = "255.255.255.0";
|
||||
final String dummyDNS = "8.8.8.8"; //this is intercepted by the tun2socks library, but we must put in a valid DNS to start
|
||||
final String defaultRoute = "0.0.0.0";
|
||||
|
||||
final String localSocks = localhost + ':' + mTorSocks;
|
||||
|
||||
builder.setMtu(VPN_MTU);
|
||||
builder.addAddress(virtualGateway, 32);
|
||||
|
||||
builder.setSession(vpnName);
|
||||
|
||||
//route all traffic through VPN (we might offer country specific exclude lists in the future)
|
||||
builder.addRoute(defaultRoute, 0);
|
||||
|
||||
builder.addDnsServer(dummyDNS);
|
||||
builder.addRoute(dummyDNS, 32);
|
||||
|
||||
//handle ipv6
|
||||
//builder.addAddress("fdfe:dcba:9876::1", 126);
|
||||
//builder.addRoute("::", 0);
|
||||
|
||||
if (mIsLollipop)
|
||||
doLollipopAppRouting(builder);
|
||||
|
||||
// https://developer.android.com/reference/android/net/VpnService.Builder#setMetered(boolean)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
builder.setMetered(false);
|
||||
}
|
||||
|
||||
// Create a new interface using the builder and save the parameters.
|
||||
ParcelFileDescriptor newInterface = builder.setSession(mSessionName)
|
||||
.setConfigureIntent(null) // previously this was set to a null member variable
|
||||
.establish();
|
||||
|
||||
if (mInterface != null) {
|
||||
Log.d(TAG, "Stopping existing VPN interface");
|
||||
mInterface.close();
|
||||
mInterface = null;
|
||||
}
|
||||
|
||||
mInterface = newInterface;
|
||||
|
||||
isRestart = false;
|
||||
|
||||
//start PDNSD daemon pointing to actual DNS
|
||||
if (filePdnsd != null) {
|
||||
|
||||
pdnsdPort++;
|
||||
startDNS(filePdnsd.getCanonicalPath(), localhost, mTorDns, virtualGateway, pdnsdPort);
|
||||
final boolean localDnsTransparentProxy = true;
|
||||
|
||||
Tun2Socks.Start(mService, mInterface, VPN_MTU, virtualIP, virtualNetMask, localSocks, virtualGateway + ":" + pdnsdPort, localDnsTransparentProxy);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, "tun2Socks has stopped", e);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
mThreadVPN.start();
|
||||
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
private void doLollipopAppRouting(VpnService.Builder builder) throws NameNotFoundException {
|
||||
SharedPreferences prefs = Prefs.getSharedPrefs(mService.getApplicationContext());
|
||||
ArrayList<TorifiedApp> apps = TorifiedApp.getApps(mService, prefs);
|
||||
|
||||
|
||||
boolean perAppEnabled = false;
|
||||
|
||||
for (TorifiedApp app : apps) {
|
||||
if (app.isTorified() && (!app.getPackageName().equals(mService.getPackageName()))) {
|
||||
if (prefs.getBoolean(app.getPackageName() + OrbotConstants.APP_TOR_KEY, true)) {
|
||||
|
||||
builder.addAllowedApplication(app.getPackageName());
|
||||
|
||||
}
|
||||
|
||||
perAppEnabled = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!perAppEnabled)
|
||||
builder.addDisallowedApplication(mService.getPackageName());
|
||||
|
||||
}
|
||||
|
||||
private void startDNS(String pdnsPath, String torDnsHost, int torDnsPort, String pdnsdHost, int pdnsdPort) throws IOException, TimeoutException {
|
||||
|
||||
File fileConf = makePdnsdConf(mService, mService.getFilesDir(), torDnsHost, torDnsPort, pdnsdHost, pdnsdPort);
|
||||
|
||||
String[] cmdString = {pdnsPath, "-c", fileConf.toString(), "-g", "-v2"};
|
||||
ProcessBuilder pb = new ProcessBuilder(cmdString);
|
||||
pb.redirectErrorStream(true);
|
||||
Process proc = pb.start();
|
||||
try {
|
||||
proc.waitFor();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
Log.i(TAG, "PDNSD: " + proc.exitValue());
|
||||
|
||||
if (proc.exitValue() != 0) {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
|
||||
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
Log.d(TAG, "pdnsd: " + line);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void stopDns() {
|
||||
if (filePdnsPid != null && filePdnsPid.exists()) {
|
||||
ArrayList<String> lines = new ArrayList<>();
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader(new FileReader(filePdnsPid));
|
||||
|
||||
String line = null;
|
||||
while ((line = reader.readLine())!= null)
|
||||
lines.add(line);
|
||||
|
||||
String dnsPid = lines.get(0);
|
||||
VpnUtils.killProcess(dnsPid, "");
|
||||
filePdnsPid.delete();
|
||||
filePdnsPid = null;
|
||||
} catch (Exception e) {
|
||||
Log.e("OrbotVPN", "error killing dns process", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isStarted() {
|
||||
return isStarted;
|
||||
}
|
||||
}
|
|
@ -1,260 +0,0 @@
|
|||
package org.torproject.android.proxy.vpn;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import static org.torproject.android.proxy.vpn.VpnPrefs.PREFS_KEY_TORIFIED;
|
||||
|
||||
public class TorifiedApp implements Comparable {
|
||||
|
||||
private boolean enabled;
|
||||
private int uid;
|
||||
private String username;
|
||||
private String procname;
|
||||
private String name;
|
||||
private Drawable icon;
|
||||
private String packageName;
|
||||
|
||||
private boolean torified = false;
|
||||
private boolean usesInternet = false;
|
||||
private int[] enabledPorts;
|
||||
|
||||
public static ArrayList<TorifiedApp> getApps(Context context, SharedPreferences prefs) {
|
||||
|
||||
String tordAppString = prefs.getString(PREFS_KEY_TORIFIED, "");
|
||||
String[] tordApps;
|
||||
|
||||
StringTokenizer st = new StringTokenizer(tordAppString, "|");
|
||||
tordApps = new String[st.countTokens()];
|
||||
int tordIdx = 0;
|
||||
while (st.hasMoreTokens()) {
|
||||
tordApps[tordIdx++] = st.nextToken();
|
||||
}
|
||||
|
||||
Arrays.sort(tordApps);
|
||||
|
||||
//else load the apps up
|
||||
PackageManager pMgr = context.getPackageManager();
|
||||
|
||||
List<ApplicationInfo> lAppInfo = pMgr.getInstalledApplications(0);
|
||||
|
||||
Iterator<ApplicationInfo> itAppInfo = lAppInfo.iterator();
|
||||
|
||||
ArrayList<TorifiedApp> apps = new ArrayList<>();
|
||||
|
||||
ApplicationInfo aInfo;
|
||||
|
||||
int appIdx = 0;
|
||||
TorifiedApp app;
|
||||
|
||||
while (itAppInfo.hasNext()) {
|
||||
aInfo = itAppInfo.next();
|
||||
|
||||
app = new TorifiedApp();
|
||||
|
||||
try {
|
||||
PackageInfo pInfo = pMgr.getPackageInfo(aInfo.packageName, PackageManager.GET_PERMISSIONS);
|
||||
|
||||
if (pInfo != null && pInfo.requestedPermissions != null) {
|
||||
for (String permInfo : pInfo.requestedPermissions) {
|
||||
if (permInfo.equals(Manifest.permission.INTERNET)) {
|
||||
app.setUsesInternet(true);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if ((aInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 1) {
|
||||
//System app
|
||||
app.setUsesInternet(true);
|
||||
}
|
||||
|
||||
|
||||
if (!app.usesInternet())
|
||||
continue;
|
||||
else {
|
||||
apps.add(app);
|
||||
}
|
||||
|
||||
|
||||
app.setEnabled(aInfo.enabled);
|
||||
app.setUid(aInfo.uid);
|
||||
app.setUsername(pMgr.getNameForUid(app.getUid()));
|
||||
app.setProcname(aInfo.processName);
|
||||
app.setPackageName(aInfo.packageName);
|
||||
|
||||
try {
|
||||
app.setName(pMgr.getApplicationLabel(aInfo).toString());
|
||||
} catch (Exception e) {
|
||||
app.setName(aInfo.packageName);
|
||||
}
|
||||
|
||||
|
||||
//app.setIcon(pMgr.getApplicationIcon(aInfo));
|
||||
|
||||
// check if this application is allowed
|
||||
if (Arrays.binarySearch(tordApps, app.getUsername()) >= 0) {
|
||||
app.setTorified(true);
|
||||
} else {
|
||||
app.setTorified(false);
|
||||
}
|
||||
|
||||
appIdx++;
|
||||
}
|
||||
|
||||
Collections.sort(apps);
|
||||
|
||||
return apps;
|
||||
}
|
||||
|
||||
public boolean usesInternet() {
|
||||
return usesInternet;
|
||||
}
|
||||
|
||||
public void setUsesInternet(boolean usesInternet) {
|
||||
this.usesInternet = usesInternet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the torified
|
||||
*/
|
||||
public boolean isTorified() {
|
||||
return torified;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param torified the torified to set
|
||||
*/
|
||||
public void setTorified(boolean torified) {
|
||||
this.torified = torified;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the enabledPorts
|
||||
*/
|
||||
public int[] getEnabledPorts() {
|
||||
return enabledPorts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param enabledPorts the enabledPorts to set
|
||||
*/
|
||||
public void setEnabledPorts(int[] enabledPorts) {
|
||||
this.enabledPorts = enabledPorts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the enabled
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param enabled the enabled to set
|
||||
*/
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the uid
|
||||
*/
|
||||
public int getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param uid the uid to set
|
||||
*/
|
||||
public void setUid(int uid) {
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the username
|
||||
*/
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param username the username to set
|
||||
*/
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the procname
|
||||
*/
|
||||
public String getProcname() {
|
||||
return procname;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param procname the procname to set
|
||||
*/
|
||||
public void setProcname(String procname) {
|
||||
this.procname = procname;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name the name to set
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Drawable getIcon() {
|
||||
return icon;
|
||||
}
|
||||
|
||||
public void setIcon(Drawable icon) {
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Object another) {
|
||||
return this.toString().compareToIgnoreCase(another.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
public String getPackageName() {
|
||||
return packageName;
|
||||
}
|
||||
|
||||
public void setPackageName(String packageName) {
|
||||
this.packageName = packageName;
|
||||
}
|
||||
}
|
|
@ -1,173 +0,0 @@
|
|||
package org.torproject.android.proxy.vpn;
|
||||
|
||||
/*
|
||||
* Copyright (c) 2013, Psiphon Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.os.Build;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.util.Log;
|
||||
|
||||
import org.torproject.android.proxy.util.TCPSourceApp;
|
||||
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.util.HashMap;
|
||||
|
||||
import static android.content.Context.CONNECTIVITY_SERVICE;
|
||||
|
||||
public class Tun2Socks {
|
||||
|
||||
private static final String TAG = Tun2Socks.class.getSimpleName();
|
||||
private static final boolean LOGD = true;
|
||||
|
||||
private static ParcelFileDescriptor mVpnInterfaceFileDescriptor;
|
||||
private static int mVpnInterfaceMTU;
|
||||
private static String mVpnIpAddress;
|
||||
private static String mVpnNetMask;
|
||||
private static String mSocksServerAddress;
|
||||
private static String mUdpgwServerAddress;
|
||||
private static boolean mUdpgwTransparentDNS;
|
||||
private static HashMap<Integer, String> mAppUidBlacklist = new HashMap<>();
|
||||
|
||||
static {
|
||||
System.loadLibrary("tun2socks");
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
}
|
||||
// Note: this class isn't a singleton, but you can't run more
|
||||
// than one instance due to the use of global state (the lwip
|
||||
// module, etc.) in the native code.
|
||||
|
||||
public static void Start(
|
||||
Context context,
|
||||
ParcelFileDescriptor vpnInterfaceFileDescriptor,
|
||||
int vpnInterfaceMTU,
|
||||
String vpnIpAddress,
|
||||
String vpnNetMask,
|
||||
String socksServerAddress,
|
||||
String udpgwServerAddress,
|
||||
boolean udpgwTransparentDNS) {
|
||||
|
||||
mVpnInterfaceFileDescriptor = vpnInterfaceFileDescriptor;
|
||||
mVpnInterfaceMTU = vpnInterfaceMTU;
|
||||
mVpnIpAddress = vpnIpAddress;
|
||||
mVpnNetMask = vpnNetMask;
|
||||
mSocksServerAddress = socksServerAddress;
|
||||
mUdpgwServerAddress = udpgwServerAddress;
|
||||
mUdpgwTransparentDNS = udpgwTransparentDNS;
|
||||
|
||||
if (mVpnInterfaceFileDescriptor != null)
|
||||
runTun2Socks(
|
||||
mVpnInterfaceFileDescriptor.detachFd(),
|
||||
mVpnInterfaceMTU,
|
||||
mVpnIpAddress,
|
||||
mVpnNetMask,
|
||||
mSocksServerAddress,
|
||||
mUdpgwServerAddress,
|
||||
mUdpgwTransparentDNS ? 1 : 0);
|
||||
}
|
||||
|
||||
public static void Stop() {
|
||||
|
||||
terminateTun2Socks();
|
||||
|
||||
}
|
||||
|
||||
public static void logTun2Socks(
|
||||
String level,
|
||||
String channel,
|
||||
String msg) {
|
||||
String logMsg = level + "(" + channel + "): " + msg;
|
||||
if (0 == level.compareTo("ERROR")) {
|
||||
Log.e(TAG, logMsg);
|
||||
} else {
|
||||
if (LOGD) Log.d(TAG, logMsg);
|
||||
}
|
||||
}
|
||||
|
||||
private native static int runTun2Socks(
|
||||
int vpnInterfaceFileDescriptor,
|
||||
int vpnInterfaceMTU,
|
||||
String vpnIpAddress,
|
||||
String vpnNetMask,
|
||||
String socksServerAddress,
|
||||
String udpgwServerAddress,
|
||||
int udpgwTransparentDNS);
|
||||
|
||||
private native static void terminateTun2Socks();
|
||||
|
||||
public static boolean checkIsAllowed(Context context, int protocol, String sourceAddr, int sourcePort, String destAddr, int destPort) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
return isAllowedQ(context, protocol, sourceAddr, sourcePort, destAddr, destPort);
|
||||
} else
|
||||
return isAllowed(context, protocol, sourceAddr, sourcePort, destAddr, destPort);
|
||||
}
|
||||
|
||||
public static boolean isAllowed(Context context, int protocol, String sourceAddr, int sourcePort, String destAddr, int destPort) {
|
||||
|
||||
TCPSourceApp.AppDescriptor aInfo = TCPSourceApp.getApplicationInfo(context, sourceAddr, sourcePort, destAddr, destPort);
|
||||
|
||||
if (aInfo != null) {
|
||||
int uid = aInfo.getUid();
|
||||
return mAppUidBlacklist.containsKey(uid);
|
||||
} else
|
||||
return true;
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.Q)
|
||||
public static boolean isAllowedQ(Context context, int protocol, String sourceAddr, int sourcePort, String destAddr, int destPort) {
|
||||
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(CONNECTIVITY_SERVICE);
|
||||
if (cm == null)
|
||||
return false;
|
||||
|
||||
InetSocketAddress local = new InetSocketAddress(sourceAddr, sourcePort);
|
||||
InetSocketAddress remote = new InetSocketAddress(destAddr, destPort);
|
||||
|
||||
int uid = cm.getConnectionOwnerUid(protocol, local, remote);
|
||||
return mAppUidBlacklist.containsKey(uid);
|
||||
}
|
||||
|
||||
public static void setBlacklist(HashMap<Integer, String> appUidBlacklist) {
|
||||
mAppUidBlacklist = appUidBlacklist;
|
||||
}
|
||||
|
||||
public static void clearBlacklist() {
|
||||
mAppUidBlacklist.clear();
|
||||
}
|
||||
|
||||
public static void addToBlacklist(int uid, String pkgId) {
|
||||
mAppUidBlacklist.put(uid, pkgId);
|
||||
}
|
||||
|
||||
public static void removeFromBlacklist(int uid) {
|
||||
mAppUidBlacklist.remove(uid);
|
||||
}
|
||||
|
||||
public interface IProtectSocket {
|
||||
boolean doVpnProtect(Socket socket);
|
||||
|
||||
boolean doVpnProtect(DatagramSocket socket);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
package org.torproject.android.proxy.vpn;
|
||||
|
||||
public interface VpnPrefs {
|
||||
|
||||
String PREFS_DNS_PORT = "PREFS_DNS_PORT";
|
||||
|
||||
String PREFS_KEY_TORIFIED = "PrefTord";
|
||||
}
|
|
@ -1,136 +0,0 @@
|
|||
package org.torproject.android.proxy.vpn;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.List;
|
||||
|
||||
import static java.lang.Runtime.getRuntime;
|
||||
|
||||
public class VpnUtils {
|
||||
|
||||
public static int findProcessId(String command) throws IOException {
|
||||
|
||||
String[] cmds = {"ps -ef", "ps -A", "toolbox ps"};
|
||||
|
||||
for (int i = 0; i < cmds.length; i++) {
|
||||
Process procPs = getRuntime().exec(cmds[i]);
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(procPs.getInputStream()));
|
||||
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (!line.contains("PID") && line.contains(command)) {
|
||||
String[] lineParts = line.split("\\s+");
|
||||
try {
|
||||
return Integer.parseInt(lineParts[1]); //for most devices it is the second
|
||||
} catch (NumberFormatException e) {
|
||||
return Integer.parseInt(lineParts[0]); //but for samsungs it is the first
|
||||
} finally {
|
||||
try {
|
||||
procPs.destroy();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static void killProcess(File fileProcBin) throws Exception {
|
||||
killProcess(fileProcBin, "-9"); // this is -KILL
|
||||
}
|
||||
|
||||
public static int killProcess(File fileProcBin, String signal) throws Exception {
|
||||
|
||||
int procId = -1;
|
||||
int killAttempts = 0;
|
||||
|
||||
while ((procId = findProcessId(fileProcBin.getName())) != -1) {
|
||||
killAttempts++;
|
||||
String pidString = String.valueOf(procId);
|
||||
boolean itBeDead = killProcess(pidString, signal);
|
||||
|
||||
if (!itBeDead) {
|
||||
|
||||
String[] cmds = {"", "busybox ", "toolbox "};
|
||||
|
||||
for (int i = 0; i < cmds.length; i++) {
|
||||
|
||||
Process proc;
|
||||
|
||||
try {
|
||||
proc = getRuntime().exec(cmds[i] + "killall " + signal + " " + fileProcBin.getName
|
||||
());
|
||||
int exitValue = proc.waitFor();
|
||||
if (exitValue == 0)
|
||||
break;
|
||||
|
||||
} catch (IOException ioe) {
|
||||
}
|
||||
try {
|
||||
proc = getRuntime().exec(cmds[i] + "killall " + signal + " " + fileProcBin.getCanonicalPath());
|
||||
int exitValue = proc.waitFor();
|
||||
if (exitValue == 0)
|
||||
break;
|
||||
|
||||
} catch (IOException ioe) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
// ignored
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (killAttempts > 4)
|
||||
throw new Exception("Cannot kill: " + fileProcBin.getAbsolutePath());
|
||||
}
|
||||
|
||||
return procId;
|
||||
}
|
||||
|
||||
public static boolean killProcess(String pidString, String signal) throws Exception {
|
||||
|
||||
String[] cmds = {"", "toolbox ", "busybox "};
|
||||
|
||||
for (int i = 0; i < cmds.length; i++) {
|
||||
try {
|
||||
Process proc = getRuntime().exec(cmds[i] + "kill " + signal + " " + pidString);
|
||||
int exitVal = proc.waitFor();
|
||||
List<String> lineErrors = IOUtils.readLines(proc.getErrorStream());
|
||||
List<String> lineInputs = IOUtils.readLines(proc.getInputStream());
|
||||
|
||||
if (exitVal != 0) {
|
||||
Log.d("Orbot.killProcess", "exit=" + exitVal);
|
||||
for (String line : lineErrors)
|
||||
Log.d("Orbot.killProcess", line);
|
||||
|
||||
for (String line : lineInputs)
|
||||
Log.d("Orbot.killProcess", line);
|
||||
|
||||
} else {
|
||||
//it worked, let's exit
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} catch (IOException ioe) {
|
||||
Log.e("Orbot.killprcess", "error killing process: " + pidString, ioe);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -6,7 +6,6 @@ import android.content.Intent;
|
|||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.torproject.android.proxy.OrbotService;
|
||||
import org.torproject.android.service.util.Prefs;
|
||||
|
||||
|
||||
|
|
|
@ -1,18 +1,15 @@
|
|||
package org.torproject.android.proxy;
|
||||
package org.torproject.android.service;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import net.freehaven.tor.control.EventHandler;
|
||||
|
||||
import org.torproject.android.proxy.util.ExternalIPFetcher;
|
||||
import org.torproject.android.proxy.util.Prefs;
|
||||
import org.torproject.android.service.R;
|
||||
import org.torproject.android.proxy.wrapper.orbotLocalConstants;
|
||||
import org.torproject.android.service.util.ExternalIPFetcher;
|
||||
import org.torproject.android.service.util.Prefs;
|
||||
import org.torproject.android.service.wrapper.orbotLocalConstants;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
|
@ -21,18 +18,15 @@ import java.util.StringTokenizer;
|
|||
public class TorEventHandler implements EventHandler, TorServiceConstants {
|
||||
|
||||
private final static int BW_THRESDHOLD = 10000;
|
||||
private OrbotService mService;
|
||||
private final OrbotService mService;
|
||||
private long lastRead = -1;
|
||||
private long lastWritten = -1;
|
||||
private long mTotalTrafficWritten = 0;
|
||||
private long mTotalTrafficRead = 0;
|
||||
private NumberFormat mNumberFormat;
|
||||
private HashMap<String, Node> hmBuiltNodes = new HashMap<>();
|
||||
private final HashMap<String, Node> hmBuiltNodes = new HashMap<>();
|
||||
|
||||
public TorEventHandler(OrbotService service) {
|
||||
mService = service;
|
||||
mNumberFormat = NumberFormat.getInstance(Locale.getDefault()); //localized numbers!
|
||||
|
||||
}
|
||||
|
||||
public HashMap<String, Node> getNodes() {
|
||||
|
@ -41,7 +35,6 @@ public class TorEventHandler implements EventHandler, TorServiceConstants {
|
|||
|
||||
@Override
|
||||
public void message(String severity, String msg) {
|
||||
|
||||
if (severity.equalsIgnoreCase("debug"))
|
||||
mService.debug(severity + ": " + msg);
|
||||
else
|
||||
|
@ -91,27 +84,19 @@ public class TorEventHandler implements EventHandler, TorServiceConstants {
|
|||
|
||||
if (lastWritten > BW_THRESDHOLD || lastRead > BW_THRESDHOLD) {
|
||||
|
||||
int iconId = R.mipmap.ic_stat_tor_logo;
|
||||
int iconId = R.drawable.ic_stat_starting_tor_logo;
|
||||
|
||||
if (read > 0 || written > 0){
|
||||
if(orbotLocalConstants.mIsTorInitialized){
|
||||
if (read > 0 || written > 0 || OrbotService.getServiceObject().getConnectivity())
|
||||
iconId = R.mipmap.ic_stat_tor_logo;
|
||||
}else {
|
||||
iconId = R.drawable.ic_stat_starting_tor_logo;
|
||||
}
|
||||
}
|
||||
|
||||
String sb = formatCount(read) +
|
||||
" \u2193" +
|
||||
" / " +
|
||||
formatCount(written) +
|
||||
" \u2191";
|
||||
mService.showToolbarNotification(sb, mService.getNotifyId(), iconId);
|
||||
String sb = OrbotService.formatBandwidthCount(mService, read) + " \u2193" + " / " +
|
||||
OrbotService.formatBandwidthCount(mService, written) + " \u2191";
|
||||
mService.showToolbarNotification(sb, OrbotService.NOTIFY_ID, iconId);
|
||||
|
||||
mTotalTrafficWritten += written;
|
||||
mTotalTrafficRead += read;
|
||||
|
||||
mService.sendCallbackBandwidth(lastWritten, lastRead, mTotalTrafficWritten, mTotalTrafficRead);
|
||||
mService.sendCallbackBandwidth(written, read, mTotalTrafficWritten, mTotalTrafficRead);
|
||||
|
||||
lastWritten = 0;
|
||||
lastRead = 0;
|
||||
|
@ -122,26 +107,10 @@ public class TorEventHandler implements EventHandler, TorServiceConstants {
|
|||
|
||||
}
|
||||
|
||||
private String formatCount(long count) {
|
||||
// Converts the supplied argument into a string.
|
||||
|
||||
// Under 2Mb, returns "xxx.xKb"
|
||||
// Over 2Mb, returns "xxx.xxMb"
|
||||
if (mNumberFormat != null)
|
||||
if (count < 1e6)
|
||||
return mNumberFormat.format(Math.round((float) ((int) (count * 10 / 1024)) / 10)) + "kbps";
|
||||
else
|
||||
return mNumberFormat.format(Math.round((float) ((int) (count * 100 / 1024 / 1024)) / 100)) + "mbps";
|
||||
else
|
||||
return "";
|
||||
|
||||
//return count+" kB";
|
||||
}
|
||||
|
||||
public void circuitStatus(String status, String circID, String path) {
|
||||
|
||||
/* once the first circuit is complete, then announce that Orbot is on*/
|
||||
if (mService.getCurrentStatus() == STATUS_STARTING && TextUtils.equals(status, "BUILT")) {
|
||||
if (mService.getCurrentStatus() == STATUS_STARTING && TextUtils.equals(status, "BUILT")){
|
||||
mService.sendCallbackStatus(STATUS_ON);
|
||||
}
|
||||
|
|
@ -9,14 +9,6 @@ public interface TorServiceConstants {
|
|||
|
||||
String DIRECTORY_TOR_DATA = "tordata";
|
||||
|
||||
String TOR_CONTROL_PORT_FILE = "control.txt";
|
||||
String TOR_PID_FILE = "torpid";
|
||||
|
||||
//torrc (tor config file)
|
||||
String TORRC_ASSET_KEY = "torrc";
|
||||
|
||||
String TOR_CONTROL_COOKIE = "control_auth_cookie";
|
||||
|
||||
//geoip data file asset key
|
||||
String GEOIP_ASSET_KEY = "geoip";
|
||||
String GEOIP6_ASSET_KEY = "geoip6";
|
||||
|
@ -26,8 +18,8 @@ public interface TorServiceConstants {
|
|||
|
||||
int TOR_DNS_PORT_DEFAULT = 5400;
|
||||
|
||||
String HTTP_PROXY_PORT_DEFAULT = "8125"; // like Privoxy!
|
||||
String SOCKS_PROXY_PORT_DEFAULT = "9055";
|
||||
String HTTP_PROXY_PORT_DEFAULT = "8118"; // like Privoxy!
|
||||
String SOCKS_PROXY_PORT_DEFAULT = "9050";
|
||||
|
||||
//control port
|
||||
String LOG_NOTICE_HEADER = "NOTICE";
|
||||
|
@ -101,17 +93,16 @@ public interface TorServiceConstants {
|
|||
String STATUS_STARTS_DISABLED = "STARTS_DISABLED";
|
||||
|
||||
// actions for internal command Intents
|
||||
String CMD_SIGNAL_HUP = "signal_hup";
|
||||
String CMD_NEWNYM = "newnym";
|
||||
String CMD_SET_EXIT = "setexit";
|
||||
String CMD_ACTIVE = "ACTIVE";
|
||||
|
||||
String PREF_BINARY_TOR_VERSION_INSTALLED = "BINARY_TOR_VERSION_INSTALLED";
|
||||
|
||||
String CMD_NEWNYM = "newnym";
|
||||
String CMD_SETTING = "setting";
|
||||
//obfsproxy
|
||||
String OBFSCLIENT_ASSET_KEY = "obfs4proxy";
|
||||
|
||||
String HIDDEN_SERVICES_DIR = "hidden_services";
|
||||
|
||||
String ONION_SERVICES_DIR = "v3_onion_services";
|
||||
String V3_CLIENT_AUTH_DIR = "v3_client_auth";
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.torproject.android.service.util;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.os.Build;
|
||||
|
@ -16,6 +17,7 @@ public class CustomNativeLoader {
|
|||
|
||||
private final static String TAG = "CNL";
|
||||
|
||||
@SuppressLint("SetWorldReadable")
|
||||
private static boolean loadFromZip(Context context, String libname, File destLocalFile, String arch) {
|
||||
|
||||
|
||||
|
|
|
@ -4,27 +4,23 @@ import android.content.Context;
|
|||
import android.content.pm.ApplicationInfo;
|
||||
import android.util.Log;
|
||||
|
||||
import org.torproject.android.binary.TorServiceConstants;
|
||||
import org.torproject.android.service.TorServiceConstants;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
public class CustomTorResourceInstaller implements TorServiceConstants {
|
||||
public class CustomTorResourceInstaller {
|
||||
|
||||
private static final String TAG = "CustomTorResourceInstaller";
|
||||
|
||||
private File installFolder;
|
||||
private Context context;
|
||||
|
||||
private File fileTorrc;
|
||||
private File fileTor;
|
||||
|
||||
public CustomTorResourceInstaller(Context context, File installFolder) {
|
||||
this.installFolder = installFolder;
|
||||
this.context = context;
|
||||
|
@ -40,7 +36,7 @@ public class CustomTorResourceInstaller implements TorServiceConstants {
|
|||
* Write the inputstream contents to the file
|
||||
*/
|
||||
private static boolean streamToFile(InputStream stm, File outFile, boolean append, boolean zip) throws IOException {
|
||||
byte[] buffer = new byte[FILE_WRITE_BUFFER_SIZE];
|
||||
byte[] buffer = new byte[1024];
|
||||
|
||||
int bytecount;
|
||||
|
||||
|
@ -98,67 +94,14 @@ public class CustomTorResourceInstaller implements TorServiceConstants {
|
|||
return fList;
|
||||
}
|
||||
|
||||
//
|
||||
/*
|
||||
* Extract the Tor resources from the APK file using ZIP
|
||||
*
|
||||
* @File path to the Tor executable
|
||||
*/
|
||||
public File installResources() throws IOException, TimeoutException {
|
||||
|
||||
fileTor = new File(installFolder, TOR_ASSET_KEY);
|
||||
|
||||
public void installGeoIP() throws IOException {
|
||||
if (!installFolder.exists())
|
||||
installFolder.mkdirs();
|
||||
|
||||
installGeoIP();
|
||||
fileTorrc = assetToFile(COMMON_ASSET_KEY + TORRC_ASSET_KEY, TORRC_ASSET_KEY, false, false);
|
||||
|
||||
File fileNativeDir = new File(getNativeLibraryDir(context));
|
||||
fileTor = new File(fileNativeDir, TOR_ASSET_KEY + ".so");
|
||||
|
||||
if (fileTor.exists()) {
|
||||
if (fileTor.canExecute())
|
||||
return fileTor;
|
||||
else {
|
||||
setExecutable(fileTor);
|
||||
|
||||
if (fileTor.canExecute())
|
||||
return fileTor;
|
||||
}
|
||||
}
|
||||
|
||||
File fileTorBin = new File(installFolder, TOR_BINARY_KEY);
|
||||
|
||||
//it exists but we can't execute it, so copy it to a new path
|
||||
if (fileTor.exists()) {
|
||||
InputStream is = new FileInputStream(fileTor);
|
||||
streamToFile(is, fileTorBin, false, true);
|
||||
setExecutable(fileTorBin);
|
||||
|
||||
if (fileTorBin.exists() && fileTorBin.canExecute())
|
||||
return fileTorBin;
|
||||
}
|
||||
|
||||
//let's try another approach
|
||||
fileTor = CustomNativeLoader.loadNativeBinary(context, TOR_ASSET_KEY, fileTorBin);
|
||||
|
||||
if (fileTor != null && fileTor.exists())
|
||||
setExecutable(fileTor);
|
||||
|
||||
if (fileTor != null && fileTor.exists() && fileTor.canExecute())
|
||||
return fileTor;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean installGeoIP() throws IOException {
|
||||
|
||||
assetToFile(COMMON_ASSET_KEY + GEOIP_ASSET_KEY, GEOIP_ASSET_KEY, false, false);
|
||||
|
||||
assetToFile(COMMON_ASSET_KEY + GEOIP6_ASSET_KEY, GEOIP6_ASSET_KEY, false, false);
|
||||
|
||||
return true;
|
||||
assetToFile(TorServiceConstants.GEOIP_ASSET_KEY, TorServiceConstants.GEOIP_ASSET_KEY, false, false);
|
||||
assetToFile(TorServiceConstants.GEOIP6_ASSET_KEY, TorServiceConstants.GEOIP6_ASSET_KEY, false, false);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -2,8 +2,8 @@ package org.torproject.android.service.util;
|
|||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.torproject.android.proxy.OrbotService;
|
||||
import org.torproject.android.proxy.TorEventHandler;
|
||||
import org.torproject.android.service.OrbotService;
|
||||
import org.torproject.android.service.TorEventHandler;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
|
@ -18,7 +18,7 @@ public class ExternalIPFetcher implements Runnable {
|
|||
private final static String ONIONOO_BASE_URL = "https://onionoo.torproject.org/details?fields=country_name,as_name,or_addresses&lookup=";
|
||||
private OrbotService mService;
|
||||
private TorEventHandler.Node mNode;
|
||||
private int mLocalHttpProxyPort = 8125;
|
||||
private int mLocalHttpProxyPort = 8118;
|
||||
|
||||
public ExternalIPFetcher(OrbotService service, TorEventHandler.Node node, int localProxyPort) {
|
||||
mService = service;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.torproject.android.service.util;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
@ -15,6 +16,7 @@ public class NativeLoader {
|
|||
|
||||
private final static String TAG = "TorNativeLoader";
|
||||
|
||||
@SuppressLint("SetWorldReadable")
|
||||
private static boolean loadFromZip(Context context, String libName, File destLocalFile, String folder) {
|
||||
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@ package org.torproject.android.service.util;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import org.torproject.android.service.OrbotConstants;
|
||||
import org.torproject.android.service.wrapper.orbotLocalConstants;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
|
@ -20,6 +20,7 @@ public class Prefs {
|
|||
private final static String PREF_OPEN_PROXY_ON_ALL_INTERFACES = "pref_open_proxy_on_all_interfaces";
|
||||
private final static String PREF_USE_VPN = "pref_vpn";
|
||||
private final static String PREF_EXIT_NODES = "pref_exit_nodes";
|
||||
private final static String PREF_BE_A_SNOWFLAKE = "pref_be_a_snowflake";
|
||||
|
||||
private static SharedPreferences prefs;
|
||||
|
||||
|
@ -50,6 +51,24 @@ public class Prefs {
|
|||
String defaultBridgeType = "obfs4";
|
||||
if (Locale.getDefault().getLanguage().equals("fa"))
|
||||
defaultBridgeType = "meek"; //if Farsi, use meek as the default bridge type
|
||||
if(orbotLocalConstants.mIsManualBridge){
|
||||
if(!orbotLocalConstants.mManualBridgeType.equals("")){
|
||||
defaultBridgeType = orbotLocalConstants.mManualBridgeType;
|
||||
putString(PREF_BRIDGES_LIST, defaultBridgeType);
|
||||
return defaultBridgeType;
|
||||
}
|
||||
}else {
|
||||
if(orbotLocalConstants.mBridges.equals("obfs4")){
|
||||
defaultBridgeType = "obfs4";
|
||||
putString(PREF_BRIDGES_LIST, defaultBridgeType);
|
||||
return defaultBridgeType;
|
||||
}else if(orbotLocalConstants.mBridges.equals("meek")){
|
||||
defaultBridgeType = "meek";
|
||||
putString(PREF_BRIDGES_LIST, defaultBridgeType);
|
||||
return defaultBridgeType;
|
||||
}
|
||||
}
|
||||
|
||||
return prefs.getString(PREF_BRIDGES_LIST, defaultBridgeType);
|
||||
}
|
||||
|
||||
|
@ -61,6 +80,14 @@ public class Prefs {
|
|||
return prefs.getString(PREF_DEFAULT_LOCALE, Locale.getDefault().getLanguage());
|
||||
}
|
||||
|
||||
public static boolean beSnowflakeProxy () {
|
||||
return prefs.getBoolean(PREF_BE_A_SNOWFLAKE,false);
|
||||
}
|
||||
|
||||
public static void setBeSnowflakeProxy (boolean beSnowflakeProxy) {
|
||||
putBoolean(PREF_BE_A_SNOWFLAKE,beSnowflakeProxy);
|
||||
}
|
||||
|
||||
public static void setDefaultLocale(String value) {
|
||||
putString(PREF_DEFAULT_LOCALE, value);
|
||||
}
|
||||
|
@ -70,16 +97,10 @@ public class Prefs {
|
|||
}
|
||||
|
||||
public static boolean useDebugLogging() {
|
||||
if(prefs == null){
|
||||
return false;
|
||||
}
|
||||
return prefs.getBoolean(PREF_ENABLE_LOGGING, false);
|
||||
return false;//prefs.getBoolean(PREF_ENABLE_LOGGING, false);
|
||||
}
|
||||
|
||||
public static boolean persistNotifications() {
|
||||
if(prefs==null){
|
||||
return false;
|
||||
}
|
||||
return prefs.getBoolean(PREF_PERSIST_NOTIFICATIONS, true);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,9 +34,8 @@ import android.widget.Toast;
|
|||
import com.runjva.sourceforge.jsocks.protocol.ProxyServer;
|
||||
import com.runjva.sourceforge.jsocks.server.ServerAuthenticatorNone;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.torproject.android.proxy.OrbotService;
|
||||
import org.torproject.android.service.OrbotConstants;
|
||||
import org.torproject.android.service.OrbotService;
|
||||
import org.torproject.android.service.R;
|
||||
import org.torproject.android.service.TorServiceConstants;
|
||||
import org.torproject.android.service.util.CustomNativeLoader;
|
||||
|
@ -44,7 +43,6 @@ import org.torproject.android.service.util.Prefs;
|
|||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
|
@ -52,7 +50,6 @@ import java.io.InputStreamReader;
|
|||
import java.io.PrintStream;
|
||||
import java.net.InetAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import static org.torproject.android.service.TorServiceConstants.ACTION_START;
|
||||
|
@ -69,17 +66,17 @@ public class OrbotVpnManager implements Handler.Callback {
|
|||
boolean isStarted = false;
|
||||
File filePdnsPid;
|
||||
private Thread mThreadVPN;
|
||||
private String mSessionName = "OrbotVPN";
|
||||
private final static String mSessionName = "OrbotVPN";
|
||||
private ParcelFileDescriptor mInterface;
|
||||
private int mTorSocks = -1;
|
||||
private int mTorDns = -1;
|
||||
private int pdnsdPort = 8091;
|
||||
private ProxyServer mSocksProxyServer;
|
||||
private File filePdnsd;
|
||||
private final File filePdnsd;
|
||||
private boolean isRestart = false;
|
||||
private VpnService mService;
|
||||
private final VpnService mService;
|
||||
|
||||
public OrbotVpnManager(VpnService service) throws IOException, TimeoutException {
|
||||
public OrbotVpnManager(VpnService service) {
|
||||
mService = service;
|
||||
filePdnsd = CustomNativeLoader.loadNativeBinary(service.getApplicationContext(), PDNSD_BIN, new File(service.getFilesDir(), PDNSD_BIN));
|
||||
Tun2Socks.init();
|
||||
|
@ -116,7 +113,7 @@ public class OrbotVpnManager implements Handler.Callback {
|
|||
if (intent != null) {
|
||||
String action = intent.getAction();
|
||||
|
||||
if (!TextUtils.isEmpty(action)) {
|
||||
if (action != null) {
|
||||
if (action.equals(ACTION_START_VPN) || action.equals(ACTION_START)) {
|
||||
Log.d(TAG, "starting VPN");
|
||||
|
||||
|
@ -291,6 +288,11 @@ public class OrbotVpnManager implements Handler.Callback {
|
|||
if (mIsLollipop)
|
||||
doLollipopAppRouting(builder);
|
||||
|
||||
// https://developer.android.com/reference/android/net/VpnService.Builder#setMetered(boolean)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
builder.setMetered(false);
|
||||
}
|
||||
|
||||
// Create a new interface using the builder and save the parameters.
|
||||
ParcelFileDescriptor newInterface = builder.setSession(mSessionName)
|
||||
.setConfigureIntent(null) // previously this was set to a null member variable
|
||||
|
@ -380,11 +382,16 @@ public class OrbotVpnManager implements Handler.Callback {
|
|||
|
||||
}
|
||||
|
||||
private boolean stopDns() {
|
||||
private void stopDns() {
|
||||
if (filePdnsPid != null && filePdnsPid.exists()) {
|
||||
List<String> lines;
|
||||
ArrayList<String> lines = new ArrayList<>();
|
||||
try {
|
||||
lines = IOUtils.readLines(new FileReader(filePdnsPid));
|
||||
BufferedReader reader = new BufferedReader(new FileReader(filePdnsPid));
|
||||
|
||||
String line = null;
|
||||
while ((line = reader.readLine())!= null)
|
||||
lines.add(line);
|
||||
|
||||
String dnsPid = lines.get(0);
|
||||
VpnUtils.killProcess(dnsPid, "");
|
||||
filePdnsPid.delete();
|
||||
|
@ -393,7 +400,6 @@ public class OrbotVpnManager implements Handler.Callback {
|
|||
Log.e("OrbotVPN", "error killing dns process", e);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isStarted() {
|
||||
|
|
|
@ -50,7 +50,7 @@ public class Tun2Socks {
|
|||
private static HashMap<Integer, String> mAppUidBlacklist = new HashMap<>();
|
||||
|
||||
static {
|
||||
System.loadLibrary("tun2socks");
|
||||
//System.loadLibrary("tun2socks");
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package org.torproject.android.proxy.wrapper;
|
||||
package org.torproject.android.service.wrapper;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Build;
|
||||
import org.torproject.android.proxy.util.Prefs;
|
||||
import org.torproject.android.service.util.Prefs;
|
||||
|
||||
import java.util.Locale;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.torproject.android.proxy.wrapper;
|
||||
package org.torproject.android.service.wrapper;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.torproject.android.proxy.wrapper;
|
||||
package org.torproject.android.service.wrapper;
|
||||
|
||||
public class logRowModel {
|
||||
/*Private Variables*/
|
|
@ -1,4 +1,4 @@
|
|||
package org.torproject.android.proxy.wrapper;
|
||||
package org.torproject.android.service.wrapper;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
|
@ -1 +0,0 @@
|
|||
libs
|
|
@ -0,0 +1 @@
|
|||
/home/morgan/Downloads/orbot-master/orbotservice/src/main/libs
|
After Width: | Height: | Size: 675 B |
After Width: | Height: | Size: 251 B |
After Width: | Height: | Size: 578 B |
After Width: | Height: | Size: 251 B |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 202 B |
After Width: | Height: | Size: 426 B |
After Width: | Height: | Size: 628 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.4 KiB |