diff --git a/app/build.gradle b/app/build.gradle index c5b8ded9..7629b10f 100755 --- a/app/build.gradle +++ b/app/build.gradle @@ -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" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 48ad5e19..e498b729 100755 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -233,10 +233,6 @@ android:resource="@xml/provider_paths" /> - --> @@ -250,11 +246,27 @@ android:resource="@xml/provider_paths" /> + + + + + + + diff --git a/app/src/main/java/com/darkweb/genesissearchengine/appManager/activityContextManager.java b/app/src/main/java/com/darkweb/genesissearchengine/appManager/activityContextManager.java index 3c01b1a3..2dae71b6 100755 --- a/app/src/main/java/com/darkweb/genesissearchengine/appManager/activityContextManager.java +++ b/app/src/main/java/com/darkweb/genesissearchengine/appManager/activityContextManager.java @@ -179,6 +179,16 @@ public class activityContextManager } } + public void onResetLanguage(){ + for(int mCounter=0;mCounter - { - mSession.stop(); - mSession.loadUri(mSession.getCurrentURL()); - }, 500); + mSession.stop(); + 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); diff --git a/app/src/main/java/com/darkweb/genesissearchengine/appManager/homeManager/geckoManager/geckoSession.java b/app/src/main/java/com/darkweb/genesissearchengine/appManager/homeManager/geckoManager/geckoSession.java index 44583635..76e7e717 100644 --- a/app/src/main/java/com/darkweb/genesissearchengine/appManager/homeManager/geckoManager/geckoSession.java +++ b/app/src/main/java/com/darkweb/genesissearchengine/appManager/homeManager/geckoManager/geckoSession.java @@ -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); } } diff --git a/app/src/main/java/com/darkweb/genesissearchengine/appManager/homeManager/geckoManager/selectionActionDelegate.java b/app/src/main/java/com/darkweb/genesissearchengine/appManager/homeManager/geckoManager/selectionActionDelegate.java index e62f0034..2d3752d3 100644 --- a/app/src/main/java/com/darkweb/genesissearchengine/appManager/homeManager/geckoManager/selectionActionDelegate.java +++ b/app/src/main/java/com/darkweb/genesissearchengine/appManager/homeManager/geckoManager/selectionActionDelegate.java @@ -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); diff --git a/app/src/main/java/com/darkweb/genesissearchengine/appManager/homeManager/hintManager/hintAdapter.java b/app/src/main/java/com/darkweb/genesissearchengine/appManager/homeManager/hintManager/hintAdapter.java index 7b3851cf..ef4856db 100644 --- a/app/src/main/java/com/darkweb/genesissearchengine/appManager/homeManager/hintManager/hintAdapter.java +++ b/app/src/main/java/com/darkweb/genesissearchengine/appManager/homeManager/hintManager/hintAdapter.java @@ -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= 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; diff --git a/app/src/main/java/com/darkweb/genesissearchengine/appManager/homeManager/homeController/homeController.java b/app/src/main/java/com/darkweb/genesissearchengine/appManager/homeManager/homeController/homeController.java index 250b01d4..ebcf2570 100644 --- a/app/src/main/java/com/darkweb/genesissearchengine/appManager/homeManager/homeController/homeController.java +++ b/app/src/main/java/com/darkweb/genesissearchengine/appManager/homeManager/homeController/homeController.java @@ -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){ - 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(); + 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(); + }, 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,12 +1940,12 @@ 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<=height/2){ - mHomeViewController.expandTopBar(true, mGeckoView.getMaxY()); - }else { - mHomeViewController.shrinkTopBar(true, mGeckoView.getMaxY()); + if(rectf.top>0 && rectf.top + height!=0){ + if(rectf.top<=height/2){ + mHomeViewController.expandTopBar(true, mGeckoView.getMaxY()); + }else { + mHomeViewController.shrinkTopBar(true, mGeckoView.getMaxY()); + } } } } @@ -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); } diff --git a/app/src/main/java/com/darkweb/genesissearchengine/appManager/homeManager/homeController/homeViewController.java b/app/src/main/java/com/darkweb/genesissearchengine/appManager/homeManager/homeController/homeViewController.java index e444155d..6458fbc9 100644 --- a/app/src/main/java/com/darkweb/genesissearchengine/appManager/homeManager/homeController/homeViewController.java +++ b/app/src/main/java/com/darkweb/genesissearchengine/appManager/homeManager/homeController/homeViewController.java @@ -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,13 +642,13 @@ 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); + 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(); + initStatusBarColor(false); mProgressBarIndeterminate.animate().setStartDelay(350).setDuration(250).alpha(0).withEndAction(() -> { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - initStatusBarColor(false); - } - 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); diff --git a/app/src/main/java/com/darkweb/genesissearchengine/appManager/kotlinHelperLibraries/defaultBrowser.kt b/app/src/main/java/com/darkweb/genesissearchengine/appManager/kotlinHelperLibraries/defaultBrowser.kt new file mode 100644 index 00000000..dff3f491 --- /dev/null +++ b/app/src/main/java/com/darkweb/genesissearchengine/appManager/kotlinHelperLibraries/defaultBrowser.kt @@ -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" diff --git a/app/src/main/java/com/darkweb/genesissearchengine/appManager/languageManager/languageController.java b/app/src/main/java/com/darkweb/genesissearchengine/appManager/languageManager/languageController.java index 8f5b16bc..14b82ad5 100644 --- a/app/src/main/java/com/darkweb/genesissearchengine/appManager/languageManager/languageController.java +++ b/app/src/main/java/com/darkweb/genesissearchengine/appManager/languageManager/languageController.java @@ -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); diff --git a/app/src/main/java/com/darkweb/genesissearchengine/appManager/orbotLogManager/orbotLogAdapter.java b/app/src/main/java/com/darkweb/genesissearchengine/appManager/orbotLogManager/orbotLogAdapter.java index 818b31aa..ef376154 100644 --- a/app/src/main/java/com/darkweb/genesissearchengine/appManager/orbotLogManager/orbotLogAdapter.java +++ b/app/src/main/java/com/darkweb/genesissearchengine/appManager/orbotLogManager/orbotLogAdapter.java @@ -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; diff --git a/app/src/main/java/com/darkweb/genesissearchengine/appManager/orbotLogManager/orbotLogController.java b/app/src/main/java/com/darkweb/genesissearchengine/appManager/orbotLogManager/orbotLogController.java index 8344aa80..7f6676ca 100644 --- a/app/src/main/java/com/darkweb/genesissearchengine/appManager/orbotLogManager/orbotLogController.java +++ b/app/src/main/java/com/darkweb/genesissearchengine/appManager/orbotLogManager/orbotLogController.java @@ -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; diff --git a/app/src/main/java/com/darkweb/genesissearchengine/appManager/orbotLogManager/orbotLogModel.java b/app/src/main/java/com/darkweb/genesissearchengine/appManager/orbotLogManager/orbotLogModel.java index 277795c6..1be3fa6d 100644 --- a/app/src/main/java/com/darkweb/genesissearchengine/appManager/orbotLogManager/orbotLogModel.java +++ b/app/src/main/java/com/darkweb/genesissearchengine/appManager/orbotLogManager/orbotLogModel.java @@ -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; diff --git a/app/src/main/java/com/darkweb/genesissearchengine/appManager/settingManager/clearManager/settingClearController.java b/app/src/main/java/com/darkweb/genesissearchengine/appManager/settingManager/clearManager/settingClearController.java index ed2627e6..a346e8b0 100644 --- a/app/src/main/java/com/darkweb/genesissearchengine/appManager/settingManager/clearManager/settingClearController.java +++ b/app/src/main/java/com/darkweb/genesissearchengine/appManager/settingManager/clearManager/settingClearController.java @@ -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)); diff --git a/app/src/main/java/com/darkweb/genesissearchengine/appManager/settingManager/generalManager/settingGeneralController.java b/app/src/main/java/com/darkweb/genesissearchengine/appManager/settingManager/generalManager/settingGeneralController.java index efb5a7ae..71242d32 100644 --- a/app/src/main/java/com/darkweb/genesissearchengine/appManager/settingManager/generalManager/settingGeneralController.java +++ b/app/src/main/java/com/darkweb/genesissearchengine/appManager/settingManager/generalManager/settingGeneralController.java @@ -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() { diff --git a/app/src/main/java/com/darkweb/genesissearchengine/appManager/settingManager/settingHomeManager/settingHomeController.java b/app/src/main/java/com/darkweb/genesissearchengine/appManager/settingManager/settingHomeManager/settingHomeController.java index 2600661f..2233ff19 100644 --- a/app/src/main/java/com/darkweb/genesissearchengine/appManager/settingManager/settingHomeManager/settingHomeController.java +++ b/app/src/main/java/com/darkweb/genesissearchengine/appManager/settingManager/settingHomeManager/settingHomeController.java @@ -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); } } diff --git a/app/src/main/java/com/darkweb/genesissearchengine/constants/enums.java b/app/src/main/java/com/darkweb/genesissearchengine/constants/enums.java index 88a5e6f9..40dbea9d 100755 --- a/app/src/main/java/com/darkweb/genesissearchengine/constants/enums.java +++ b/app/src/main/java/com/darkweb/genesissearchengine/constants/enums.java @@ -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 } diff --git a/app/src/main/java/com/darkweb/genesissearchengine/constants/status.java b/app/src/main/java/com/darkweb/genesissearchengine/constants/status.java index 101f8598..7eb15b78 100755 --- a/app/src/main/java/com/darkweb/genesissearchengine/constants/status.java +++ b/app/src/main/java/com/darkweb/genesissearchengine/constants/status.java @@ -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)); } diff --git a/app/src/main/java/com/darkweb/genesissearchengine/dataManager/dataController.java b/app/src/main/java/com/darkweb/genesissearchengine/dataManager/dataController.java index 7822b822..e09d20fd 100755 --- a/app/src/main/java/com/darkweb/genesissearchengine/dataManager/dataController.java +++ b/app/src/main/java/com/darkweb/genesissearchengine/dataManager/dataController.java @@ -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)); diff --git a/app/src/main/java/com/darkweb/genesissearchengine/dataManager/tabDataModel.java b/app/src/main/java/com/darkweb/genesissearchengine/dataManager/tabDataModel.java index 78f50018..83eb06ae 100644 --- a/app/src/main/java/com/darkweb/genesissearchengine/dataManager/tabDataModel.java +++ b/app/src/main/java/com/darkweb/genesissearchengine/dataManager/tabDataModel.java @@ -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; } diff --git a/app/src/main/java/com/darkweb/genesissearchengine/helperManager/helperMethod.java b/app/src/main/java/com/darkweb/genesissearchengine/helperManager/helperMethod.java index a971c952..59517294 100755 --- a/app/src/main/java/com/darkweb/genesissearchengine/helperManager/helperMethod.java +++ b/app/src/main/java/com/darkweb/genesissearchengine/helperManager/helperMethod.java @@ -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); diff --git a/app/src/main/java/com/darkweb/genesissearchengine/libs/clientauth/ClientAuthContentProvider.java b/app/src/main/java/com/darkweb/genesissearchengine/libs/providers/ClientAuthContentProviderGenesis.java similarity index 93% rename from app/src/main/java/com/darkweb/genesissearchengine/libs/clientauth/ClientAuthContentProvider.java rename to app/src/main/java/com/darkweb/genesissearchengine/libs/providers/ClientAuthContentProviderGenesis.java index a5b8fb76..4612a226 100644 --- a/app/src/main/java/com/darkweb/genesissearchengine/libs/clientauth/ClientAuthContentProvider.java +++ b/app/src/main/java/com/darkweb/genesissearchengine/libs/providers/ClientAuthContentProviderGenesis.java @@ -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; @@ -101,4 +101,4 @@ public class ClientAuthContentProvider extends ContentProvider { ENABLED = "enabled"; } -} +} \ No newline at end of file diff --git a/app/src/main/java/com/darkweb/genesissearchengine/libs/clientauth/ClientAuthDatabase.java b/app/src/main/java/com/darkweb/genesissearchengine/libs/providers/ClientAuthDatabase.java similarity index 94% rename from app/src/main/java/com/darkweb/genesissearchengine/libs/clientauth/ClientAuthDatabase.java rename to app/src/main/java/com/darkweb/genesissearchengine/libs/providers/ClientAuthDatabase.java index 305f926d..eea4273b 100644 --- a/app/src/main/java/com/darkweb/genesissearchengine/libs/clientauth/ClientAuthDatabase.java +++ b/app/src/main/java/com/darkweb/genesissearchengine/libs/providers/ClientAuthDatabase.java @@ -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; diff --git a/app/src/main/java/com/darkweb/genesissearchengine/libs/providers/CookieContentProvider.java b/app/src/main/java/com/darkweb/genesissearchengine/libs/providers/CookieContentProvider.java new file mode 100644 index 00000000..8029fc33 --- /dev/null +++ b/app/src/main/java/com/darkweb/genesissearchengine/libs/providers/CookieContentProvider.java @@ -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() { + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/darkweb/genesissearchengine/libs/providers/HSContentProvider.java b/app/src/main/java/com/darkweb/genesissearchengine/libs/providers/HSContentProvider.java new file mode 100644 index 00000000..37ec23ac --- /dev/null +++ b/app/src/main/java/com/darkweb/genesissearchengine/libs/providers/HSContentProvider.java @@ -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() { + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/darkweb/genesissearchengine/libs/providers/HSDatabase.java b/app/src/main/java/com/darkweb/genesissearchengine/libs/providers/HSDatabase.java new file mode 100644 index 00000000..c08171bf --- /dev/null +++ b/app/src/main/java/com/darkweb/genesissearchengine/libs/providers/HSDatabase.java @@ -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"); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/darkweb/genesissearchengine/libs/providers/OnionServiceContentProvider.java b/app/src/main/java/com/darkweb/genesissearchengine/libs/providers/OnionServiceContentProvider.java new file mode 100644 index 00000000..12e537a5 --- /dev/null +++ b/app/src/main/java/com/darkweb/genesissearchengine/libs/providers/OnionServiceContentProvider.java @@ -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 + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/darkweb/genesissearchengine/libs/providers/OnionServiceDatabase.java b/app/src/main/java/com/darkweb/genesissearchengine/libs/providers/OnionServiceDatabase.java new file mode 100644 index 00000000..3a037b6d --- /dev/null +++ b/app/src/main/java/com/darkweb/genesissearchengine/libs/providers/OnionServiceDatabase.java @@ -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"); + } + } + + +} diff --git a/app/src/main/java/com/darkweb/genesissearchengine/pluginManager/adPluginManager/adManager.java b/app/src/main/java/com/darkweb/genesissearchengine/pluginManager/adPluginManager/adManager.java index e9e62817..fd53651c 100644 --- a/app/src/main/java/com/darkweb/genesissearchengine/pluginManager/adPluginManager/adManager.java +++ b/app/src/main/java/com/darkweb/genesissearchengine/pluginManager/adPluginManager/adManager.java @@ -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); } }); } diff --git a/app/src/main/java/com/darkweb/genesissearchengine/pluginManager/downloadPluginManager/downloadReciever.java b/app/src/main/java/com/darkweb/genesissearchengine/pluginManager/downloadPluginManager/downloadReciever.java index 8e53452b..354a356e 100644 --- a/app/src/main/java/com/darkweb/genesissearchengine/pluginManager/downloadPluginManager/downloadReciever.java +++ b/app/src/main/java/com/darkweb/genesissearchengine/pluginManager/downloadPluginManager/downloadReciever.java @@ -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; diff --git a/app/src/main/java/com/darkweb/genesissearchengine/pluginManager/langPluginManager/langManager.java b/app/src/main/java/com/darkweb/genesissearchengine/pluginManager/langPluginManager/langManager.java index 71707201..107b8852 100644 --- a/app/src/main/java/com/darkweb/genesissearchengine/pluginManager/langPluginManager/langManager.java +++ b/app/src/main/java/com/darkweb/genesissearchengine/pluginManager/langPluginManager/langManager.java @@ -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){ - 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); - } - } 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); - } - } - } + private boolean initLocale(){ + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + Locale mSystemLocaleTemp = Resources.getSystem().getConfiguration().getLocales().get(0); + mEvent.invokeObserver(Collections.singletonList(mSystemLocaleTemp), pluginEnums.eLangManager.M_UPDATE_LOCAL); + mSystemLocale = mSystemLocaleTemp; + } else { + 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)) diff --git a/app/src/main/java/com/darkweb/genesissearchengine/pluginManager/orbotPluginManager/orbotManager.java b/app/src/main/java/com/darkweb/genesissearchengine/pluginManager/orbotPluginManager/orbotManager.java index 0a65aa38..32e8b726 100644 --- a/app/src/main/java/com/darkweb/genesissearchengine/pluginManager/orbotPluginManager/orbotManager.java +++ b/app/src/main/java/com/darkweb/genesissearchengine/pluginManager/orbotPluginManager/orbotManager.java @@ -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,7 +221,9 @@ public class orbotManager } private void newCircuit(){ - OrbotService.getServiceObject().newIdentity(); + if(OrbotService.getServiceObject()!=null){ + OrbotService.getServiceObject().newIdentity(); + } } private String getOrbotStatus(){ diff --git a/app/src/main/res/anim/fade_in_lang.xml b/app/src/main/res/anim/fade_in_lang.xml index 0a08b417..97f216cc 100644 --- a/app/src/main/res/anim/fade_in_lang.xml +++ b/app/src/main/res/anim/fade_in_lang.xml @@ -1,7 +1,7 @@ diff --git a/app/src/main/res/anim/fade_out_lang.xml b/app/src/main/res/anim/fade_out_lang.xml index 60fe9202..f4421c36 100644 --- a/app/src/main/res/anim/fade_out_lang.xml +++ b/app/src/main/res/anim/fade_out_lang.xml @@ -1,6 +1,6 @@ diff --git a/app/src/main/res/custom-xml/home/xml/hox_splash_gradient_back.xml b/app/src/main/res/custom-xml/home/xml/hox_splash_gradient_back.xml new file mode 100644 index 00000000..48af58ff --- /dev/null +++ b/app/src/main/res/custom-xml/home/xml/hox_splash_gradient_back.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/custom-xml/home/xml/splash_back.xml b/app/src/main/res/custom-xml/home/xml/splash_back.xml new file mode 100644 index 00000000..624ed13a --- /dev/null +++ b/app/src/main/res/custom-xml/home/xml/splash_back.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-hdpi/ic_refresh_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_refresh_white_24dp.png old mode 100755 new mode 100644 diff --git a/app/src/main/res/drawable-hdpi/icon_ban.webp b/app/src/main/res/drawable-hdpi/icon_ban.webp old mode 100755 new mode 100644 diff --git a/app/src/main/res/drawable-hdpi/icon_loading.webp b/app/src/main/res/drawable-hdpi/icon_loading.webp old mode 100755 new mode 100644 diff --git a/app/src/main/res/drawable-hdpi/menu_item.webp b/app/src/main/res/drawable-hdpi/menu_item.webp old mode 100755 new mode 100644 diff --git a/app/src/main/res/layouts/home/layout/home_view.xml b/app/src/main/res/layouts/home/layout/home_view.xml index 2e4b4b12..46267256 100644 --- a/app/src/main/res/layouts/home/layout/home_view.xml +++ b/app/src/main/res/layouts/home/layout/home_view.xml @@ -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"> - diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml old mode 100755 new mode 100644 diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml old mode 100755 new mode 100644 diff --git a/orbotmanager.tar.gz b/orbotmanager.tar.gz new file mode 100644 index 00000000..215d83bb Binary files /dev/null and b/orbotmanager.tar.gz differ diff --git a/orbotmanager/build.gradle b/orbotmanager/build.gradle index edf0e14c..378653ed 100644 --- a/orbotmanager/build.gradle +++ b/orbotmanager/build.gradle @@ -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' } diff --git a/orbotmanager/proguard-rules.pro b/orbotmanager/proguard-rules.pro index 97110cde..e69de29b 100644 --- a/orbotmanager/proguard-rules.pro +++ b/orbotmanager/proguard-rules.pro @@ -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 (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 diff --git a/orbotmanager/src/main/AndroidManifest.xml b/orbotmanager/src/main/AndroidManifest.xml index 801a9c18..589ee334 100644 --- a/orbotmanager/src/main/AndroidManifest.xml +++ b/orbotmanager/src/main/AndroidManifest.xml @@ -1,4 +1,6 @@ + + diff --git a/orbotmanager/src/main/ic_launcher-playstore.png b/orbotmanager/src/main/ic_launcher-playstore.png deleted file mode 100644 index 24889790..00000000 Binary files a/orbotmanager/src/main/ic_launcher-playstore.png and /dev/null differ diff --git a/orbotmanager/src/main/java/org/torproject/android/proxy/OrbotConstants.java b/orbotmanager/src/main/java/org/torproject/android/proxy/OrbotConstants.java deleted file mode 100644 index 9dd461d2..00000000 --- a/orbotmanager/src/main/java/org/torproject/android/proxy/OrbotConstants.java +++ /dev/null @@ -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"; -} diff --git a/orbotmanager/src/main/java/org/torproject/android/proxy/StartTorReceiver.java b/orbotmanager/src/main/java/org/torproject/android/proxy/StartTorReceiver.java deleted file mode 100644 index 8e50e3b9..00000000 --- a/orbotmanager/src/main/java/org/torproject/android/proxy/StartTorReceiver.java +++ /dev/null @@ -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); - } - } - } -} diff --git a/orbotmanager/src/main/java/org/torproject/android/proxy/TorServiceConstants.java b/orbotmanager/src/main/java/org/torproject/android/proxy/TorServiceConstants.java deleted file mode 100644 index 0d54bdf9..00000000 --- a/orbotmanager/src/main/java/org/torproject/android/proxy/TorServiceConstants.java +++ /dev/null @@ -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"; - -} diff --git a/orbotmanager/src/main/java/org/torproject/android/proxy/util/CustomNativeLoader.java b/orbotmanager/src/main/java/org/torproject/android/proxy/util/CustomNativeLoader.java deleted file mode 100644 index 9b22adfe..00000000 --- a/orbotmanager/src/main/java/org/torproject/android/proxy/util/CustomNativeLoader.java +++ /dev/null @@ -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; - } - -} - diff --git a/orbotmanager/src/main/java/org/torproject/android/proxy/util/CustomShell.java b/orbotmanager/src/main/java/org/torproject/android/proxy/util/CustomShell.java deleted file mode 100644 index 299a6218..00000000 --- a/orbotmanager/src/main/java/org/torproject/android/proxy/util/CustomShell.java +++ /dev/null @@ -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 env, @NonNull String command) { - List stdout = Collections.synchronizedList(new ArrayList<>()); - List 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); - } -} diff --git a/orbotmanager/src/main/java/org/torproject/android/proxy/util/CustomTorResourceInstaller.java b/orbotmanager/src/main/java/org/torproject/android/proxy/util/CustomTorResourceInstaller.java deleted file mode 100644 index c2b8ac7f..00000000 --- a/orbotmanager/src/main/java/org/torproject/android/proxy/util/CustomTorResourceInstaller.java +++ /dev/null @@ -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); - } -} - diff --git a/orbotmanager/src/main/java/org/torproject/android/proxy/util/DummyActivity.java b/orbotmanager/src/main/java/org/torproject/android/proxy/util/DummyActivity.java deleted file mode 100644 index 8ec51831..00000000 --- a/orbotmanager/src/main/java/org/torproject/android/proxy/util/DummyActivity.java +++ /dev/null @@ -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(); - } -} \ No newline at end of file diff --git a/orbotmanager/src/main/java/org/torproject/android/proxy/util/ExternalIPFetcher.java b/orbotmanager/src/main/java/org/torproject/android/proxy/util/ExternalIPFetcher.java deleted file mode 100644 index af0bed23..00000000 --- a/orbotmanager/src/main/java/org/torproject/android/proxy/util/ExternalIPFetcher.java +++ /dev/null @@ -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()); - } - } -} diff --git a/orbotmanager/src/main/java/org/torproject/android/proxy/util/NativeLoader.java b/orbotmanager/src/main/java/org/torproject/android/proxy/util/NativeLoader.java deleted file mode 100644 index dc04bdf1..00000000 --- a/orbotmanager/src/main/java/org/torproject/android/proxy/util/NativeLoader.java +++ /dev/null @@ -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 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; - } -} diff --git a/orbotmanager/src/main/java/org/torproject/android/proxy/util/PortForwarder.java b/orbotmanager/src/main/java/org/torproject/android/proxy/util/PortForwarder.java deleted file mode 100644 index 216d098c..00000000 --- a/orbotmanager/src/main/java/org/torproject/android/proxy/util/PortForwarder.java +++ /dev/null @@ -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 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 - } -} diff --git a/orbotmanager/src/main/java/org/torproject/android/proxy/util/Prefs.java b/orbotmanager/src/main/java/org/torproject/android/proxy/util/Prefs.java deleted file mode 100644 index a87e9692..00000000 --- a/orbotmanager/src/main/java/org/torproject/android/proxy/util/Prefs.java +++ /dev/null @@ -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); - } -} diff --git a/orbotmanager/src/main/java/org/torproject/android/proxy/util/TCPSourceApp.java b/orbotmanager/src/main/java/org/torproject/android/proxy/util/TCPSourceApp.java deleted file mode 100644 index 83af3e3b..00000000 --- a/orbotmanager/src/main/java/org/torproject/android/proxy/util/TCPSourceApp.java +++ /dev/null @@ -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 interfaces = Collections.list(NetworkInterface.getNetworkInterfaces()); - - for (NetworkInterface intf : interfaces) { - List 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; - } - - } - -} \ No newline at end of file diff --git a/orbotmanager/src/main/java/org/torproject/android/proxy/util/TorServiceUtils.java b/orbotmanager/src/main/java/org/torproject/android/proxy/util/TorServiceUtils.java deleted file mode 100644 index 155869f8..00000000 --- a/orbotmanager/src/main/java/org/torproject/android/proxy/util/TorServiceUtils.java +++ /dev/null @@ -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; - } - } -} diff --git a/orbotmanager/src/main/java/org/torproject/android/proxy/util/Utils.java b/orbotmanager/src/main/java/org/torproject/android/proxy/util/Utils.java deleted file mode 100644 index 6e3bbbb9..00000000 --- a/orbotmanager/src/main/java/org/torproject/android/proxy/util/Utils.java +++ /dev/null @@ -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]; - } -} diff --git a/orbotmanager/src/main/java/org/torproject/android/proxy/vpn/OrbotVpnManager.java b/orbotmanager/src/main/java/org/torproject/android/proxy/vpn/OrbotVpnManager.java deleted file mode 100644 index b58bdc52..00000000 --- a/orbotmanager/src/main/java/org/torproject/android/proxy/vpn/OrbotVpnManager.java +++ /dev/null @@ -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 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 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; - } -} diff --git a/orbotmanager/src/main/java/org/torproject/android/proxy/vpn/TorifiedApp.java b/orbotmanager/src/main/java/org/torproject/android/proxy/vpn/TorifiedApp.java deleted file mode 100644 index a144cd33..00000000 --- a/orbotmanager/src/main/java/org/torproject/android/proxy/vpn/TorifiedApp.java +++ /dev/null @@ -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 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 lAppInfo = pMgr.getInstalledApplications(0); - - Iterator itAppInfo = lAppInfo.iterator(); - - ArrayList 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; - } -} diff --git a/orbotmanager/src/main/java/org/torproject/android/proxy/vpn/Tun2Socks.java b/orbotmanager/src/main/java/org/torproject/android/proxy/vpn/Tun2Socks.java deleted file mode 100644 index 0d2f0bad..00000000 --- a/orbotmanager/src/main/java/org/torproject/android/proxy/vpn/Tun2Socks.java +++ /dev/null @@ -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 . - * - */ - -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 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 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); - } - -} \ No newline at end of file diff --git a/orbotmanager/src/main/java/org/torproject/android/proxy/vpn/VpnPrefs.java b/orbotmanager/src/main/java/org/torproject/android/proxy/vpn/VpnPrefs.java deleted file mode 100644 index 135ff967..00000000 --- a/orbotmanager/src/main/java/org/torproject/android/proxy/vpn/VpnPrefs.java +++ /dev/null @@ -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"; -} diff --git a/orbotmanager/src/main/java/org/torproject/android/proxy/vpn/VpnUtils.java b/orbotmanager/src/main/java/org/torproject/android/proxy/vpn/VpnUtils.java deleted file mode 100644 index 0ce7e5ae..00000000 --- a/orbotmanager/src/main/java/org/torproject/android/proxy/vpn/VpnUtils.java +++ /dev/null @@ -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 lineErrors = IOUtils.readLines(proc.getErrorStream()); - List 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; - } -} diff --git a/orbotmanager/src/main/java/org/torproject/android/proxy/OrbotService.java b/orbotmanager/src/main/java/org/torproject/android/service/OrbotService.java similarity index 64% rename from orbotmanager/src/main/java/org/torproject/android/proxy/OrbotService.java rename to orbotmanager/src/main/java/org/torproject/android/service/OrbotService.java index 97474b27..39f1a6a9 100644 --- a/orbotmanager/src/main/java/org/torproject/android/proxy/OrbotService.java +++ b/orbotmanager/src/main/java/org/torproject/android/service/OrbotService.java @@ -5,7 +5,7 @@ * Copyright (C) 2009-2010 Rodrigo Zechin Rosauro */ -package org.torproject.android.proxy; +package org.torproject.android.service; import android.annotation.SuppressLint; import android.app.Application; @@ -15,12 +15,14 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.content.IntentFilter; +import android.content.ServiceConnection; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.database.Cursor; @@ -30,28 +32,16 @@ import android.net.Uri; import android.net.VpnService; import android.os.Build; import android.os.Handler; +import android.os.HandlerThread; import android.os.IBinder; +import android.os.Looper; import android.provider.BaseColumns; import android.text.TextUtils; import android.util.Log; -import androidx.annotation.RequiresApi; -import androidx.core.app.NotificationCompat; -import androidx.core.app.NotificationManagerCompat; -import androidx.localbroadcastmanager.content.LocalBroadcastManager; - -import com.jaredrummler.android.shell.CommandResult; - -import net.freehaven.tor.control.ConfigEntry; import net.freehaven.tor.control.TorControlCommands; import net.freehaven.tor.control.TorControlConnection; -import org.apache.commons.io.FileUtils; -import org.torproject.android.service.R; -import org.torproject.android.proxy.wrapper.localHelperMethod; -import org.torproject.android.proxy.wrapper.logRowModel; -import org.torproject.android.proxy.wrapper.orbotLocalConstants; -import org.torproject.android.service.util.CustomShell; import org.torproject.android.service.util.CustomTorResourceInstaller; import org.torproject.android.service.util.DummyActivity; import org.torproject.android.service.util.Prefs; @@ -59,61 +49,95 @@ import org.torproject.android.service.util.TorServiceUtils; import org.torproject.android.service.util.Utils; import org.torproject.android.service.vpn.OrbotVpnManager; import org.torproject.android.service.vpn.VpnPrefs; +import org.torproject.android.service.wrapper.localHelperMethod; +import org.torproject.android.service.wrapper.logRowModel; +import org.torproject.android.service.wrapper.orbotLocalConstants; +import org.torproject.jni.TorService; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.io.FileReader; +import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.io.PrintWriter; -import java.io.Reader; -import java.io.StringReader; -import java.net.Socket; +import java.text.NumberFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.Date; import java.util.HashMap; -import java.util.Iterator; import java.util.List; +import java.util.Locale; +import java.util.Objects; import java.util.Random; import java.util.StringTokenizer; +import java.util.UUID; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeoutException; -import info.pluggabletransports.dispatch.util.TransportListener; -import info.pluggabletransports.dispatch.util.TransportManager; +import IPtProxy.IPtProxy; +import androidx.annotation.RequiresApi; +import androidx.core.app.NotificationCompat; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; public class OrbotService extends VpnService implements TorServiceConstants, OrbotConstants { - public final static String BINARY_TOR_VERSION = org.torproject.android.binary.TorServiceConstants.BINARY_TOR_VERSION; - private final static int CONTROL_SOCKET_TIMEOUT = 60000; + public final static String BINARY_TOR_VERSION = TorService.VERSION_NAME; + static final int NOTIFY_ID = 1; private static final int ERROR_NOTIFY_ID = 3; private static final int HS_NOTIFY_ID = 4; - private static final Uri HS_CONTENT_URI = Uri.parse("content://org.torproject.android.ui.hiddenservices.providers/hs"); + private static final Uri V2_HS_CONTENT_URI = Uri.parse("content://org.torproject.android.ui.hiddenservices.providers/hs"); + private static final Uri V3_ONION_SERVICES_CONTENT_URI = Uri.parse("content://org.torproject.android.ui.v3onionservice/v3"); private static final Uri COOKIE_CONTENT_URI = Uri.parse("content://org.torproject.android.ui.hiddenservices.providers.cookie/cookie"); + private static final Uri V3_CLIENT_AUTH_URI = Uri.parse("content://org.torproject.android.ui.v3onionservice.clientauth/v3auth"); private final static String NOTIFICATION_CHANNEL_ID = "orbot_channel_1"; - private final static String RESET_STRING = "=\"\""; + private static final String[] LEGACY_V2_ONION_SERVICE_PROJECTION = new String[]{ + OnionService._ID, + OnionService.NAME, + OnionService.DOMAIN, + OnionService.PORT, + OnionService.AUTH_COOKIE, + OnionService.AUTH_COOKIE_VALUE, + OnionService.ONION_PORT, + OnionService.ENABLED, + OnionService.PATH}; + private static final String[] V3_ONION_SERVICE_PROJECTION = new String[]{ + OnionService._ID, + OnionService.NAME, + OnionService.DOMAIN, + OnionService.PORT, + OnionService.ONION_PORT, + OnionService.ENABLED, + OnionService.PATH + }; + private static final String[] LEGACY_COOKIE_PROJECTION = new String[]{ + ClientCookie._ID, + ClientCookie.DOMAIN, + ClientCookie.AUTH_COOKIE_VALUE, + ClientCookie.ENABLED}; + private static final String[] V3_CLIENT_AUTH_PROJECTION = new String[]{ + V3ClientAuth._ID, + V3ClientAuth.DOMAIN, + V3ClientAuth.HASH, + V3ClientAuth.ENABLED + }; + + public boolean isAppClosed = false; public static int mPortSOCKS = -1; public static int mPortHTTP = -1; public static int mPortDns = TOR_DNS_PORT_DEFAULT; public static int mPortTrans = TOR_TRANSPROXY_PORT_DEFAULT; public static File appBinHome; public static File appCacheHome; - public static File fileTor; - public static File fileObfsclient; - public boolean isAppClosed = false; - public static File fileTorRc; + private final ExecutorService mExecutor = Executors.newCachedThreadPool(); boolean mIsLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; TorEventHandler mEventHandler; OrbotVpnManager mVpnManager; @@ -123,30 +147,14 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb ActionBroadcastReceiver mActionBroadcastReceiver; private String mCurrentStatus = STATUS_OFF; private TorControlConnection conn = null; - private int mLastProcessId = -1; - private ArrayList configBuffer = null; - private ArrayList resetBuffer = null; - private File fileControlPort, filePid; + private ServiceConnection torServiceConnection; + private TorService torService; + private boolean shouldUnbindTorService; private NotificationManager mNotificationManager = null; private NotificationCompat.Builder mNotifyBuilder; private boolean mNotificationShowing = false; - private final ExecutorService mExecutor = Executors.newFixedThreadPool(3); - private File mHSBasePath; + private File mHSBasePath, mV3OnionBasePath, mV3AuthBasePath; private ArrayList alBridges = null; - private final String[] hsProjection = new String[]{ - HiddenService._ID, - HiddenService.NAME, - HiddenService.DOMAIN, - HiddenService.PORT, - HiddenService.AUTH_COOKIE, - HiddenService.AUTH_COOKIE_VALUE, - HiddenService.ONION_PORT, - HiddenService.ENABLED}; - private final String[] cookieProjection = new String[]{ - ClientCookie._ID, - ClientCookie.DOMAIN, - ClientCookie.AUTH_COOKIE_VALUE, - ClientCookie.ENABLED}; /** * @param bridgeList bridges that were manually entered into Orbot settings @@ -159,19 +167,13 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb } public void debug(String msg) { - Log.d(OrbotConstants.TAG, msg); if (Prefs.useDebugLogging()) { sendCallbackLogMessage(msg); - } } - public int getNotifyId() { - return NOTIFY_ID; - } - public void logException(String msg, Exception e) { if (Prefs.useDebugLogging()) { Log.e(OrbotConstants.TAG, msg, e); @@ -186,34 +188,13 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb } private void showConnectedToTorNetworkNotification() { - showToolbarNotification(getString(R.string.status_activated), NOTIFY_ID, R.drawable.ic_stat_tor); + showToolbarNotification(getString(R.string.status_activated), NOTIFY_ID, R.mipmap.ic_stat_tor_logo); } - private boolean findExistingTorDaemon() { - try { - mLastProcessId = initControlConnection(3, true); - - if (mLastProcessId != -1 && conn != null) { - sendCallbackLogMessage(getString(R.string.found_existing_tor_process)); - sendCallbackStatus(STATUS_ON); - showConnectedToTorNetworkNotification(); - return true; - } - } catch (Exception e) { - Log.i("sda","ASd"); - } - return false; - } - - /* (non-Javadoc) - * @see android.app.Service#onLowMemory() - */ @Override public void onLowMemory() { super.onLowMemory(); - logNotice("Low Memory Warning!"); - } private void clearNotifications() { @@ -223,7 +204,6 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb if (mEventHandler != null) mEventHandler.getNodes().clear(); - NotificationManagerCompat.from(this).cancelAll(); mNotificationShowing = false; } @@ -265,7 +245,7 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); mNotifyBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID) .setContentTitle(getString(R.string.app_name)) - .setSmallIcon(R.drawable.ic_stat_tor) + .setSmallIcon(R.mipmap.ic_stat_tor_logo) .setContentIntent(pendIntent) .setCategory(Notification.CATEGORY_SERVICE) .setOngoing(Prefs.persistNotifications()); @@ -299,22 +279,20 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb } else { mNotificationManager.notify(NOTIFY_ID, notification); } - }catch (Exception ignored){} + }catch (Exception ex){ + Log.i("sad","asd"); + } mNotificationShowing = true; mToolbarUpdating = false; } - /* (non-Javadoc) - * @see android.app.Service#onStart(android.content.Intent, int) - */ public int onStartCommand(Intent intent, int flags, int startId) { + showToolbarNotification("", NOTIFY_ID, R.mipmap.ic_stat_tor_logo); + self = this; - - showToolbarNotification("", NOTIFY_ID, R.drawable.ic_stat_tor); - if (intent != null) - exec(new IncomingIntentRouter(intent)); + mExecutor.execute(new IncomingIntentRouter(intent)); else Log.d(OrbotConstants.TAG, "Got null onStartCommand() intent"); @@ -342,6 +320,7 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb unregisterReceiver(mNetworkStateReceiver); unregisterReceiver(mActionBroadcastReceiver); }catch (Exception ex){ + Log.i("sad","asd"); ex.printStackTrace(); } @@ -363,33 +342,6 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb super.onDestroy(); } - - private void stopTor() { - new Thread(this::stopTorAsync).start(); - } - - private void stopTorAsync() { - Log.i("OrbotService", "stopTor"); - try { - sendCallbackStatus(STATUS_STOPPING); - sendCallbackLogMessage(getString(R.string.status_shutting_down)); - - killAllDaemons(); - - //stop the foreground priority and make sure to remove the persistant notification - stopForeground(true); - - sendCallbackLogMessage(getString(R.string.status_disabled)); - } catch (Exception e) { - logNotice("An error occured stopping Tor: " + e.getMessage()); - sendCallbackLogMessage(getString(R.string.something_bad_happened)); - } - clearNotifications(); - sendCallbackStatus(STATUS_OFF); - - - } - private void killAllDaemons() throws Exception { if (conn != null) { @@ -407,24 +359,143 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb } } - private void requestTorRereadConfig() { - try { - if (conn != null) - conn.signal("HUP"); + private void stopTorAsync() { - } catch (IOException e) { - e.printStackTrace(); + Log.i("OrbotService", "stopTor"); + try { + sendCallbackStatus(STATUS_STOPPING); + sendCallbackLogMessage(getString(R.string.status_shutting_down)); + + if (useIPtObfsMeekProxy()) + IPtProxy.stopObfs4Proxy(); + + if (useIPtSnowflakeProxy()) + IPtProxy.stopSnowflake(); + + stopTor(); + + //stop the foreground priority and make sure to remove the persistant notification + stopForeground(true); + + sendCallbackLogMessage(getString(R.string.status_disabled)); + } catch (Exception e) { + logNotice("An error occured stopping Tor: " + e.getMessage()); + sendCallbackLogMessage(getString(R.string.something_bad_happened)); } - /** - // if that fails, try again using native utils - try { - killProcess(fileTor, "-1"); // this is -HUP - } catch (Exception e) { - e.printStackTrace(); - }**/ + clearNotifications(); + sendCallbackStatus(STATUS_OFF); } - public void logNotice(String msg) { + private void stopTorOnError(String message) { + stopTorAsync(); + showToolbarNotification( + getString(R.string.unable_to_start_tor) + ": " + message, + ERROR_NOTIFY_ID, R.drawable.ic_stat_notifyerr); + } + + private static boolean useIPtObfsMeekProxy() { + String bridgeList = Prefs.getBridgesList(); + return bridgeList.contains("obfs") || bridgeList.contains("meek"); + } + + private static boolean useIPtSnowflakeProxy() { + String bridgeList = Prefs.getBridgesList(); + return bridgeList.contains("snowflake"); + } + + private static HashMap mFronts; + + public static void loadCdnFronts (Context context) { + if (mFronts == null) { + mFronts = new HashMap<>(); + + try { + BufferedReader reader = new BufferedReader(new InputStreamReader(context.getAssets().open("fronts"))); + String line; + while ((line = reader.readLine())!=null) { + String[] front = line.split(" "); + + //add some code to test the connection here + + mFronts.put(front[0],front[1]); + } + } catch (IOException e) { + Log.i("sad","asd"); + e.printStackTrace(); + } + } + } + + public static String getCdnFront(String service) { + return mFronts.get(service); + } + + + private void startSnowflakeClient() { + //this is using the current, default Tor snowflake infrastructure + String target = getCdnFront("snowflake-target"); + String front = getCdnFront("snowflake-front"); + String stunServer = getCdnFront("snowflake-stun"); + + IPtProxy.startSnowflake(stunServer, target, front, + null, true, false, true, 3); + + } + + /* + This is to host a snowflake entrance node / bridge + */ + private void runSnowflakeProxy () { + int capacity = 3; + String broker = "https://snowflake-broker.bamsoftware.com/"; + String relay = "wss://snowflake.bamsoftware.com/"; + String stun = "stun:stun.stunprotocol.org:3478"; + String logFile = null; + boolean keepLocalAddresses = true; + boolean unsafeLogging = false; + IPtProxy.startSnowflakeProxy(capacity, broker, relay, stun, logFile, keepLocalAddresses, unsafeLogging); + } + + private void stopSnowflakeProxy () { + IPtProxy.stopSnowflakeProxy(); + } + /** + * if someone stops during startup, we may have to wait for the conn port to be setup, so we can properly shutdown tor + */ + private synchronized void stopTor() throws Exception { + + if (conn != null) { + logNotice("Using control port to shutdown Tor"); + + try { + logNotice("sending HALT signal to Tor process"); + conn.shutdownTor(TorControlCommands.SIGNAL_SHUTDOWN); + + } catch (IOException e) { + Log.d(OrbotConstants.TAG, "error shutting down Tor via connection", e); + } + + if (shouldUnbindTorService) { + unbindService(torServiceConnection); + shouldUnbindTorService = false; + } + + conn = null; + } + } + + private void requestTorRereadConfig() { + try { + if (conn != null) { + conn.signal(TorControlCommands.SIGNAL_RELOAD); + } + } catch (IOException e) { + Log.i("sad","asd"); + e.printStackTrace(); + } + } + + protected void logNotice(String msg) { if (msg != null && msg.trim().length() > 0) { if (Prefs.useDebugLogging()) Log.d(OrbotConstants.TAG, msg); @@ -453,32 +524,17 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb if (!appCacheHome.exists()) appCacheHome.mkdirs(); - - debug("listing files in DataDirectory: " + appCacheHome.getAbsolutePath()); - Iterator files = FileUtils.iterateFiles(appCacheHome, null, true); - while (files.hasNext()) { - File fileNext = files.next(); - debug(fileNext.getAbsolutePath() - + " length=" + fileNext.length() - + " rw=" + fileNext.canRead() + "/" + fileNext.canWrite() - + " lastMod=" + new Date(fileNext.lastModified()).toLocaleString() - - ); - } - - fileTorRc = new File(appBinHome, TORRC_ASSET_KEY); - fileControlPort = new File(getFilesDir(), TOR_CONTROL_PORT_FILE); - filePid = new File(getFilesDir(), TOR_PID_FILE); - - mHSBasePath = new File( - getFilesDir().getAbsolutePath(), - TorServiceConstants.HIDDEN_SERVICES_DIR - ); - + mHSBasePath = new File(getFilesDir().getAbsolutePath(), TorServiceConstants.HIDDEN_SERVICES_DIR); if (!mHSBasePath.isDirectory()) mHSBasePath.mkdirs(); - mEventHandler = new TorEventHandler(this); + mV3OnionBasePath = new File(getFilesDir().getAbsolutePath(), TorServiceConstants.ONION_SERVICES_DIR); + if (!mV3OnionBasePath.isDirectory()) + mV3OnionBasePath.mkdirs(); + + mV3AuthBasePath = new File(getFilesDir().getAbsolutePath(), TorServiceConstants.V3_CLIENT_AUTH_DIR); + if (!mV3AuthBasePath.isDirectory()) + mV3AuthBasePath.mkdirs(); if (mNotificationManager == null) { mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); @@ -497,27 +553,15 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb if (Build.VERSION.SDK_INT >= 26) createNotificationChannel(); - torUpgradeAndConfig(); + CustomTorResourceInstaller installer = new CustomTorResourceInstaller(this, appBinHome); + installer.installGeoIP(); pluggableTransportInstall(); - new Thread(() -> { - try { - findExistingTorDaemon(); - } catch (Exception e) { - Log.e(OrbotConstants.TAG, "error onBind", e); - logNotice("error finding exiting process: " + e.toString()); - } + mVpnManager = new OrbotVpnManager(this); - }).start(); + loadCdnFronts(this); - try { - mVpnManager = new OrbotVpnManager(this); - } catch (IOException e) { - e.printStackTrace(); - } catch (TimeoutException e) { - e.printStackTrace(); - } } catch (Exception e) { //what error here Log.e(OrbotConstants.TAG, "Error installing Orbot binaries", e); @@ -527,50 +571,19 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb Log.i("OrbotService", "onCreate end"); } - public String getCurrentStatus() { + protected String getCurrentStatus() { return mCurrentStatus; } private boolean pluggableTransportInstall() { - fileObfsclient = new TransportManager() { - @Override - public void startTransportSync(TransportListener transportListener) { - - } - }.installTransport(this, OBFSCLIENT_ASSET_KEY); - - if (fileObfsclient != null && fileObfsclient.exists()) { - - fileObfsclient.setReadable(true); - fileObfsclient.setExecutable(true); - fileObfsclient.setWritable(false); - fileObfsclient.setWritable(true, true); - - return fileObfsclient.canExecute(); - } - - return false; - } - - private boolean torUpgradeAndConfig() throws IOException, TimeoutException { - - SharedPreferences prefs = Prefs.getSharedPrefs(getApplicationContext()); - String version = prefs.getString(PREF_BINARY_TOR_VERSION_INSTALLED, null); - - logNotice("checking binary version: " + version); - - CustomTorResourceInstaller installer = new CustomTorResourceInstaller(this, appBinHome); - logNotice("upgrading binaries to latest version: " + BINARY_TOR_VERSION); - - fileTor = installer.installResources(); - - if (fileTor != null && fileTor.canExecute()) { - prefs.edit().putString(PREF_BINARY_TOR_VERSION_INSTALLED, BINARY_TOR_VERSION).apply(); - - fileTorRc = new File(appBinHome, "torrc");//installer.getTorrcFile(); - return fileTorRc.exists(); - } + File fileCacheDir = new File(getCacheDir(), "pt"); + if (!fileCacheDir.exists()) + //noinspection ResultOfMethodCallIgnored + fileCacheDir.mkdir(); + IPtProxy.setStateLocation(fileCacheDir.getAbsolutePath()); + String fileTestState = IPtProxy.getStateLocation(); + debug("IPtProxy state: " + fileTestState); return false; } @@ -581,12 +594,9 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb StringBuffer extraLines = new StringBuffer(); extraLines.append("\n"); - extraLines.append("ControlPortWriteToFile").append(' ').append(fileControlPort.getCanonicalPath()).append('\n'); - extraLines.append("PidFile").append(' ').append(filePid.getCanonicalPath()).append('\n'); - - extraLines.append("RunAsDaemon 1").append('\n'); - extraLines.append("AvoidDiskWrites 1").append('\n'); + extraLines.append("RunAsDaemon 0").append('\n'); + extraLines.append("AvoidDiskWrites 0").append('\n'); String socksPortPref = prefs.getString(OrbotConstants.PREF_SOCKS, (TorServiceConstants.SOCKS_PROXY_PORT_DEFAULT)); @@ -677,15 +687,9 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb debug("torrc.custom=" + extraLines.toString()); - File fileTorRcCustom = new File(fileTorRc.getAbsolutePath() + ".custom"); - boolean success = updateTorConfigCustom(fileTorRcCustom, extraLines.toString()); - - if (success && fileTorRcCustom.exists()) { - logNotice("success."); - return fileTorRcCustom; - } else - return null; - + File fileTorRcCustom = TorService.getTorrc(this); + updateTorConfigCustom(fileTorRcCustom, extraLines.toString()); + return fileTorRcCustom; } private String checkPortOrAuto(String portString) { @@ -699,13 +703,10 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb if (isPortUsed) //the specified port is not available, so let Tor find one instead port++; } - - return port + ""; } return portString; - } public boolean updateTorConfigCustom(File fileTorRcCustom, String extraLines) throws IOException, TimeoutException { @@ -752,39 +753,24 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb * The entire process for starting tor and related services is run from this method. */ private void startTor() { - - String torProcId = null; - - try { - if (conn != null) torProcId = conn.getInfo("process/pid"); - } catch (Exception e) { - Log.i("sda","ASd"); - } - try { // STATUS_STARTING is set in onCreate() - if (mCurrentStatus == STATUS_STOPPING) { + if (mCurrentStatus.equals(STATUS_STOPPING)) { // these states should probably be handled better sendCallbackLogMessage("Ignoring start request, currently " + mCurrentStatus); return; - } else if (mCurrentStatus == STATUS_ON && (torProcId != null)) { + } else if (mCurrentStatus.equals(STATUS_ON)) { showConnectedToTorNetworkNotification(); sendCallbackLogMessage("Ignoring start request, already started."); - // setTorNetworkEnabled (true); - return; } + sendCallbackStatus(STATUS_STARTING); // make sure there are no stray daemons running - killAllDaemons(); + stopTor(); - SharedPreferences prefs = Prefs.getSharedPrefs(getApplicationContext()); - String version = prefs.getString(PREF_BINARY_TOR_VERSION_INSTALLED, null); - logNotice("checking binary version: " + version); - - sendCallbackStatus(STATUS_STARTING); showToolbarNotification(getString(R.string.status_starting_up), NOTIFY_ID, R.drawable.ic_stat_starting_tor_logo); //sendCallbackLogMessage(getString(R.string.status_starting_up)); //logNotice(getString(R.string.status_starting_up)); @@ -796,62 +782,91 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb customEnv.add("TOR_PT_PROXY=socks5://" + OrbotVpnManager.sSocksProxyLocalhost + ":" + OrbotVpnManager.sSocksProxyServerPort); } - boolean success = runTorShellCmd(); + startTorService(); - if (success) { + /* if (Prefs.hostOnionServicesEnabled()) { try { - updateOnionNames(); + updateLegacyV2OnionNames(); } catch (SecurityException se) { - logNotice("unable to upload onion names"); + logNotice("unable to upload legacy v2 onion names"); } - } - + try { + updateV3OnionNames(); + } catch (SecurityException se) { + logNotice("unable to upload v3 onion names"); + } + } */ } catch (Exception e) { + Log.i("sad","asd"); logException("Unable to start Tor: " + e.toString(), e); - stopTor(); - showToolbarNotification( - getString(R.string.unable_to_start_tor) + ": " + e.getMessage(), - ERROR_NOTIFY_ID, R.drawable.ic_stat_notifyerr); - + stopTorOnError(e.getLocalizedMessage()); } } - private void updateOnionNames() throws SecurityException { + + private void updateV3OnionNames() throws SecurityException { + ContentResolver contentResolver = getApplicationContext().getContentResolver(); + Cursor onionServices = contentResolver.query(V3_ONION_SERVICES_CONTENT_URI, null, null, null, null); + if (onionServices != null) { + try { + while (onionServices.moveToNext()) { + String domain = onionServices.getString(onionServices.getColumnIndex(OnionService.DOMAIN)); + if (domain == null || TextUtils.isEmpty(domain)) { + String path = onionServices.getString(onionServices.getColumnIndex(OnionService.PATH)); + String v3OnionDirPath = new File(mV3OnionBasePath.getAbsolutePath(), path).getCanonicalPath(); + File hostname = new File(v3OnionDirPath, "hostname"); + if (hostname.exists()) { + int id = onionServices.getInt(onionServices.getColumnIndex(OnionService._ID)); + domain = Utils.readString(new FileInputStream(hostname)).trim(); + ContentValues fields = new ContentValues(); + fields.put(OnionService.DOMAIN, domain); + contentResolver.update(V3_ONION_SERVICES_CONTENT_URI, fields, OnionService._ID + "=" + id, null); + } + } + + } + } catch (Exception e) { + Log.i("sad","asd"); + e.printStackTrace(); + } + onionServices.close(); + } + } + + private void updateLegacyV2OnionNames() throws SecurityException { // Tor is running, update new .onion names at db ContentResolver mCR = getApplicationContext().getContentResolver(); - Cursor hidden_services = mCR.query(HS_CONTENT_URI, hsProjection, null, null, null); + Cursor hidden_services = mCR.query(V2_HS_CONTENT_URI, LEGACY_V2_ONION_SERVICE_PROJECTION, null, null, null); if (hidden_services != null) { try { while (hidden_services.moveToNext()) { - String HSDomain = hidden_services.getString(hidden_services.getColumnIndex(HiddenService.DOMAIN)); - Integer HSLocalPort = hidden_services.getInt(hidden_services.getColumnIndex(HiddenService.PORT)); - Integer HSAuthCookie = hidden_services.getInt(hidden_services.getColumnIndex(HiddenService.AUTH_COOKIE)); - String HSAuthCookieValue = hidden_services.getString(hidden_services.getColumnIndex(HiddenService.AUTH_COOKIE_VALUE)); - + String HSDomain = hidden_services.getString(hidden_services.getColumnIndex(OnionService.DOMAIN)); + int HSAuthCookie = hidden_services.getInt(hidden_services.getColumnIndex(OnionService.AUTH_COOKIE)); + String HSAuthCookieValue = hidden_services.getString(hidden_services.getColumnIndex(OnionService.AUTH_COOKIE_VALUE)); // Update only new domains or restored from backup with auth cookie if ((HSDomain == null || HSDomain.length() < 1) || (HSAuthCookie == 1 && (HSAuthCookieValue == null || HSAuthCookieValue.length() < 1))) { - String hsDirPath = new File(mHSBasePath.getAbsolutePath(), "hs" + HSLocalPort).getCanonicalPath(); + String hsDirPath = new File(mHSBasePath.getAbsolutePath(), hidden_services.getString(hidden_services.getColumnIndex(OnionService.PATH))).getCanonicalPath(); File file = new File(hsDirPath, "hostname"); if (file.exists()) { ContentValues fields = new ContentValues(); try { + int id = hidden_services.getInt(hidden_services.getColumnIndex(OnionService._ID)); String onionHostname = Utils.readString(new FileInputStream(file)).trim(); if (HSAuthCookie == 1) { String[] aux = onionHostname.split(" "); onionHostname = aux[0]; - fields.put(HiddenService.AUTH_COOKIE_VALUE, aux[1]); + fields.put(OnionService.AUTH_COOKIE_VALUE, aux[1]); } - fields.put(HiddenService.DOMAIN, onionHostname); - mCR.update(HS_CONTENT_URI, fields, "port=" + HSLocalPort, null); + fields.put(OnionService.DOMAIN, onionHostname); + mCR.update(V2_HS_CONTENT_URI, fields, OnionService._ID + "=" + id, null); } catch (FileNotFoundException e) { logException("unable to read onion hostname file", e); showToolbarNotification(getString(R.string.unable_to_read_hidden_service_name), HS_NOTIFY_ID, R.drawable.ic_stat_notifyerr); } } else { showToolbarNotification(getString(R.string.unable_to_read_hidden_service_name), HS_NOTIFY_ID, R.drawable.ic_stat_notifyerr); - } } } @@ -866,507 +881,135 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb } } - private boolean runTorShellCmd() throws Exception { - boolean result = true; + private synchronized void startTorService() throws Exception { + updateTorConfigCustom(TorService.getDefaultsTorrc(this), + "DNSPort 0\n" + + "TransPort 0\n" + + "DisableNetwork 1\n"); File fileTorrcCustom = updateTorrcCustomFile(); - - //make sure Tor exists and we can execute it - if (fileTor == null || (!fileTor.exists()) || (!fileTor.canExecute())) - return false; - - if ((!fileTorRc.exists()) || (!fileTorRc.canRead())) - return false; - if ((!fileTorrcCustom.exists()) || (!fileTorrcCustom.canRead())) - return false; + return; sendCallbackLogMessage(getString(R.string.status_starting_up)); - String torCmdString = fileTor.getAbsolutePath() - + " DataDirectory " + appCacheHome.getAbsolutePath() - + " --defaults-torrc " + fileTorRc.getAbsolutePath() - + " -f " + fileTorrcCustom.getAbsolutePath(); + torServiceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName componentName, IBinder iBinder) { + torService = ((TorService.LocalBinder) iBinder).getService(); + try { + conn = torService.getTorControlConnection(); + while (conn == null) { + Log.v(TAG, "Waiting for Tor Control Connection..."); + Thread.sleep(500); + conn = torService.getTorControlConnection(); + } + mEventHandler = new TorEventHandler(OrbotService.this); + logNotice("adding control port event handler"); + conn.setEventHandler(mEventHandler); + ArrayList events = new ArrayList<>(Arrays.asList( + TorControlCommands.EVENT_OR_CONN_STATUS, + TorControlCommands.EVENT_CIRCUIT_STATUS, + TorControlCommands.EVENT_NOTICE_MSG, + TorControlCommands.EVENT_WARN_MSG, + TorControlCommands.EVENT_ERR_MSG, + TorControlCommands.EVENT_BANDWIDTH_USED, + TorControlCommands.EVENT_NEW_DESC, + TorControlCommands.EVENT_ADDRMAP)); + if (Prefs.useDebugLogging()) { + events.add(TorControlCommands.EVENT_DEBUG_MSG); + events.add(TorControlCommands.EVENT_INFO_MSG); + } - int exitCode = -1; + int mDelay = 3000; + if(orbotLocalConstants.mIsTorInitialized){ + mDelay = 0; + } + Thread.sleep(mDelay); - try { - exitCode = exec(torCmdString + " --verify-config", true); - } catch (Exception e) { - logNotice("Tor configuration did not verify: " + e.getMessage()); - return false; + conn.setEvents(events); + logNotice("SUCCESS added control port event handler"); + } catch (InterruptedException | IOException e) { + e.printStackTrace(); + stopTorOnError(e.getLocalizedMessage()); + conn = null; + } + } + + @Override + public void onServiceDisconnected(ComponentName componentName) { + conn = null; + torService = null; + mEventHandler = null; + } + + @Override + public void onNullBinding(ComponentName componentName) { + stopTorOnError("Tor was unable to start: " + "onNullBinding"); + conn = null; + torService = null; + mEventHandler = null; + } + + @Override + public void onBindingDied(ComponentName componentName) { + stopTorOnError("Tor was unable to start: " + "onBindingDied"); + conn = null; + torService = null; + mEventHandler = null; + } + }; + + BroadcastReceiver receiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (TorService.ACTION_STATUS.equals(intent.getAction()) + && TorService.STATUS_ON.equals(intent.getStringExtra(TorService.EXTRA_STATUS))) { + initControlConnection(); + unregisterReceiver(this); + } + } + }; + // run the BroadcastReceiver in its own thread + HandlerThread handlerThread = new HandlerThread(receiver.getClass().getSimpleName()); + handlerThread.start(); + Looper looper = handlerThread.getLooper(); + Handler handler = new Handler(looper); + registerReceiver(receiver, new IntentFilter(TorService.ACTION_STATUS), null, handler); + + Intent serviceIntent = new Intent(this, TorService.class); + if (Build.VERSION.SDK_INT < 29) { + shouldUnbindTorService = bindService(serviceIntent, torServiceConnection, BIND_AUTO_CREATE); + } else { + shouldUnbindTorService = bindService(serviceIntent, BIND_AUTO_CREATE, mExecutor, torServiceConnection); } - - if (exitCode == 0) { - logNotice("Tor configuration VERIFIED."); - try { - exitCode = exec(torCmdString, false); - } catch (Exception e) { - logNotice("Tor was unable to start: " + e.getMessage()); - - throw new Exception("Tor was unable to start: " + e.getMessage()); - - } - - if (exitCode != 0) { - logNotice("Tor did not start. Exit:" + exitCode); - return false; - } - - //now try to connect - mLastProcessId = initControlConnection(10, false); - - if (mLastProcessId == -1) { - logNotice(getString(R.string.couldn_t_start_tor_process_) + "; exit=" + exitCode); - throw new Exception(getString(R.string.couldn_t_start_tor_process_) + "; exit=" + exitCode); - } else { - - logNotice("Tor started; process id=" + mLastProcessId); - result = true; - } - } - - return result; } - public void exec(Runnable runn) { + protected void exec(Runnable runn) { mExecutor.execute(runn); } - private int exec(String cmd, boolean wait) throws Exception { - HashMap mapEnv = new HashMap<>(); - mapEnv.put("HOME", appBinHome.getAbsolutePath()); - - CommandResult result = CustomShell.run("sh", wait, mapEnv, cmd); - debug("executing: " + cmd); - debug("stdout: " + result.getStdout()); - debug("stderr: " + result.getStderr()); - - return result.exitCode; + public int getNotifyId() { + return NOTIFY_ID; } - private int initControlConnection(int maxTries, boolean isReconnect) throws Exception { - int controlPort = -1; - int attempt = 0; - - logNotice("Waiting for control port..."); - - while (conn == null && attempt++ < maxTries && (mCurrentStatus != STATUS_OFF)) { - try { - - controlPort = getControlPort(); - - if (controlPort != -1) { - logNotice("Connecting to control port: " + controlPort); - - - break; - } - - } catch (Exception ce) { - conn = null; - // logException( "Error connecting to Tor local control port: " + ce.getMessage(),ce); - - } - - - try { - // logNotice("waiting..."); - Thread.sleep(2000); - } catch (Exception e) { - Log.i("sda","ASd"); - } - } - - - if (controlPort != -1) { - Socket torConnSocket = new Socket(IP_LOCALHOST, controlPort); - torConnSocket.setSoTimeout(CONTROL_SOCKET_TIMEOUT); - - conn = new TorControlConnection(torConnSocket); - - conn.launchThread(true);//is daemon - - } - - if (conn != null) { - - logNotice("SUCCESS connected to Tor control port."); - - File fileCookie = new File(appCacheHome, TOR_CONTROL_COOKIE); - - if (fileCookie.exists()) { - - // We extend NullEventHandler so that we don't need to provide empty - // implementations for all the events we don't care about. - logNotice("adding control port event handler"); - - conn.setEventHandler(mEventHandler); - - logNotice("SUCCESS added control port event handler"); - byte[] cookie = new byte[(int) fileCookie.length()]; - DataInputStream fis = new DataInputStream(new FileInputStream(fileCookie)); - fis.read(cookie); - fis.close(); - conn.authenticate(cookie); - - logNotice("SUCCESS - authenticated to control port."); - - // conn.setEvents(Arrays.asList(new String[]{"DEBUG","STATUS_CLIENT","STATUS_GENERAL","BW"})); - - if (Prefs.useDebugLogging()) - conn.setEvents(Arrays.asList("CIRC", "STREAM", "ORCONN", "BW", "INFO", "NOTICE", "WARN", "DEBUG", "ERR", "NEWDESC", "ADDRMAP")); - else - conn.setEvents(Arrays.asList("CIRC", "STREAM", "ORCONN", "BW", "NOTICE", "ERR", "NEWDESC", "ADDRMAP")); - - // sendCallbackLogMessage(getString(R.string.tor_process_starting) + ' ' + getString(R.string.tor_process_complete)); - - String torProcId = conn.getInfo("process/pid"); - - String confSocks = conn.getInfo("net/listeners/socks"); - StringTokenizer st = new StringTokenizer(confSocks, " "); - - confSocks = st.nextToken().split(":")[1]; - confSocks = confSocks.substring(0, confSocks.length() - 1); - mPortSOCKS = Integer.parseInt(confSocks); - - String confHttp = conn.getInfo("net/listeners/httptunnel"); - st = new StringTokenizer(confHttp, " "); - - confHttp = st.nextToken().split(":")[1]; - confHttp = confHttp.substring(0, confHttp.length() - 1); - mPortHTTP = Integer.parseInt(confHttp); - - String confDns = conn.getInfo("net/listeners/dns"); - st = new StringTokenizer(confDns, " "); - if (st.hasMoreTokens()) { - confDns = st.nextToken().split(":")[1]; - confDns = confDns.substring(0, confDns.length() - 1); - mPortDns = Integer.parseInt(confDns); - Prefs.getSharedPrefs(getApplicationContext()).edit().putInt(VpnPrefs.PREFS_DNS_PORT, mPortDns).apply(); - } - - String confTrans = conn.getInfo("net/listeners/trans"); - st = new StringTokenizer(confTrans, " "); - if (st.hasMoreTokens()) { - confTrans = st.nextToken().split(":")[1]; - confTrans = confTrans.substring(0, confTrans.length() - 1); - mPortTrans = Integer.parseInt(confTrans); - } - - sendCallbackPorts(mPortSOCKS, mPortHTTP, mPortDns, mPortTrans); - - setTorNetworkEnabled(true); - - return Integer.parseInt(torProcId); - - } else { - logNotice("Tor authentication cookie does not exist yet"); - conn = null; - - } - } - - throw new Exception("Tor control port could not be found"); + public String getProxyStatus() { + return mCurrentStatus; } - private int getControlPort() { - int result = -1; + private static OrbotService self = null; - try { - if (fileControlPort.exists()) { - debug("Reading control port config file: " + fileControlPort.getCanonicalPath()); - BufferedReader bufferedReader = new BufferedReader(new FileReader(fileControlPort)); - String line = bufferedReader.readLine(); - - if (line != null) { - String[] lineParts = line.split(":"); - result = Integer.parseInt(lineParts[1]); - } - - - bufferedReader.close(); - - //store last valid control port - SharedPreferences prefs = Prefs.getSharedPrefs(getApplicationContext()); - prefs.edit().putInt("controlport", result).apply(); - } else { - debug("Control Port config file does not yet exist (waiting for tor): " + fileControlPort.getCanonicalPath()); - } - } catch (FileNotFoundException e) { - debug("unable to get control port; file not found"); - } catch (Exception e) { - debug("unable to read control port config file"); - } - - return result; + public static OrbotService getServiceObject(){ + return self; } - /** - * Returns the port number that the HTTP proxy is running on - */ - public int getHTTPPort() { - return mPortHTTP; - } - - /** - * Returns the port number that the HTTP proxy is running on - */ - public int getSOCKSPort() { - return mPortSOCKS; - } - - public String getInfo(String key) { - try { - if (conn != null) { - return conn.getInfo(key); - } - } catch (Exception ioe) { - // Log.e(TAG,"Unable to get Tor information",ioe); - logNotice("Unable to get Tor information" + ioe.getMessage()); - } - return null; - } - - public String getConfiguration(String name) { - try { - if (conn != null) { - StringBuffer result = new StringBuffer(); - - List listCe = conn.getConf(name); - - Iterator itCe = listCe.iterator(); - ConfigEntry ce; - - - while (itCe.hasNext()) { - ce = itCe.next(); - - result.append(ce.key); - result.append(' '); - result.append(ce.value); - result.append('\n'); - } - - return result.toString(); - } - } catch (Exception ioe) { - - logException("Unable to get Tor configuration: " + ioe.getMessage(), ioe); - } - - return null; - } - - /** - * Set configuration - **/ - public boolean updateConfiguration(String name, String value, boolean saveToDisk) { - - - if (configBuffer == null) - configBuffer = new ArrayList<>(); - - if (resetBuffer == null) - resetBuffer = new ArrayList<>(); - - if (value == null || value.length() == 0) { - resetBuffer.add(name + RESET_STRING); - - } else { - - String sbConf = name + - ' ' + - value; - configBuffer.add(sbConf); - } - - return false; - } - - - public void setTorNetworkEnabled(final boolean isEnabled) throws IOException { - - //it is possible to not have a connection yet, and someone might try to newnym - if (conn != null) { - new Thread() { - public void run() { - try { - - final String newValue = isEnabled ? "0" : "1"; - conn.setConf("DisableNetwork", newValue); - } catch (Exception ioe) { - debug("error requesting newnym: " + ioe.getLocalizedMessage()); - } - } - }.start(); - } - - } - - public void sendSignalActive() { - if (conn != null && mCurrentStatus == STATUS_ON) { - try { - conn.signal("ACTIVE"); - } catch (IOException e) { - debug("error send active: " + e.getLocalizedMessage()); - } - } - } - - public void newIdentity() { - //it is possible to not have a connection yet, and someone might try to newnym - if (conn != null) { - new Thread() { - public void run() { - try { - int iconId = R.drawable.ic_stat_tor; - - if (conn != null && mCurrentStatus == STATUS_ON && Prefs.expandedNotifications() && mConnectivity) - showToolbarNotification(getString(R.string.newnym), NOTIFY_ID, R.drawable.ic_stat_starting_tor_logo); - - conn.signal(TorControlCommands.SIGNAL_NEWNYM); - - sleep(1000); - if(mConnectivity) - enableNotification(); - - } catch (Exception ioe) { - debug("error requesting newnym: " + ioe.getLocalizedMessage()); - } - } - }.start(); - } - } - - public boolean saveConfiguration() { - try { - if (conn != null) { - - if (resetBuffer != null && resetBuffer.size() > 0) { - for (String value : configBuffer) { - - // debug("removing torrc conf: " + value); - - - } - - // conn.resetConf(resetBuffer); - resetBuffer = null; - } - - if (configBuffer != null && configBuffer.size() > 0) { - - for (String value : configBuffer) { - - debug("Setting torrc conf: " + value); - - - } - - conn.setConf(configBuffer); - - configBuffer = null; - } - - // Flush the configuration to disk. - //this is doing bad things right now NF 22/07/10 - //conn.saveConf(); - - return true; - } - } catch (Exception ioe) { - logException("Unable to update Tor configuration: " + ioe.getMessage(), ioe); - } - - return false; - } - - public void sendCallbackBandwidth(long upload, long download, long written, long read) { - Intent intent = new Intent(LOCAL_ACTION_BANDWIDTH); - - intent.putExtra("up", upload); - intent.putExtra("down", download); - intent.putExtra("written", written); - intent.putExtra("read", read); - intent.putExtra(EXTRA_STATUS, mCurrentStatus); - - LocalBroadcastManager.getInstance(this).sendBroadcast(intent); - } - - private void sendCallbackLogMessage(String logMessage) - { - - if(logMessage.contains("Bootstrapped 100%")){ - orbotLocalConstants.mIsTorInitialized = true; - } - mHandler.post(() -> { - Intent intent = new Intent(LOCAL_ACTION_LOG); - intent.putExtra(LOCAL_EXTRA_LOG, logMessage); - intent.putExtra(EXTRA_STATUS, mCurrentStatus); - orbotLocalConstants.mTorLogsHistory.add(new logRowModel(logMessage, localHelperMethod.getCurrentTime())); - - if(!mConnectivity){ - orbotLocalConstants.mTorLogsStatus = "No internet connection"; - }else { - orbotLocalConstants.mTorLogsStatus = logMessage; - } - LocalBroadcastManager.getInstance(this).sendBroadcast(intent); - }); - - } - - private void sendCallbackPorts(int socksPort, int httpPort, int dnsPort, int transPort) { - - Intent intent = new Intent(LOCAL_ACTION_PORTS); - // You can also include some extra data. - intent.putExtra(EXTRA_SOCKS_PROXY_PORT, socksPort); - intent.putExtra(EXTRA_HTTP_PROXY_PORT, httpPort); - intent.putExtra(EXTRA_DNS_PORT, dnsPort); - intent.putExtra(EXTRA_TRANS_PORT, transPort); - - LocalBroadcastManager.getInstance(this).sendBroadcast(intent); - - if (Prefs.useVpn()) - mVpnManager.handleIntent(new Builder(), intent); - - } - - public void sendCallbackStatus(String currentStatus) { - mCurrentStatus = currentStatus; - Intent intent = getActionStatusIntent(currentStatus); - sendBroadcastOnlyToOrbot(intent); // send for Orbot internals, using secure local broadcast - sendBroadcast(intent); // send for any apps that are interested - } - - /** - * Send a secure broadcast only to Orbot itself - * - * @see {@link ContextWrapper#sendBroadcast(Intent)} - * @see {@link LocalBroadcastManager} - */ - private boolean sendBroadcastOnlyToOrbot(Intent intent) { - return LocalBroadcastManager.getInstance(this).sendBroadcast(intent); - } - - private Intent getActionStatusIntent(String currentStatus) { - Intent intent = new Intent(ACTION_STATUS); - intent.putExtra(EXTRA_STATUS, currentStatus); - return intent; - } - - /* - * Another way to do this would be to use the Observer pattern by defining the - * BroadcastReciever in the Android manifest. - */ - private boolean mConnectivity = true; private int mNetworkType = -1; private final BroadcastReceiver mNetworkStateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - SharedPreferences prefs = org.torproject.android.proxy.util.Prefs.getSharedPrefs(getApplicationContext()); + SharedPreferences prefs = Prefs.getSharedPrefs(getApplicationContext()); if(prefs==null){ } @@ -1376,7 +1019,7 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb final ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); final NetworkInfo netInfo = cm.getActiveNetworkInfo(); - boolean newConnectivityState = false; + boolean newConnectivityState; int newNetType = -1; if (netInfo!=null) @@ -1411,7 +1054,7 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb orbotLocalConstants.mTorLogsStatus = "No internet connection"; if(orbotLocalConstants.mNotificationStatus!=0){ showToolbarNotification(getString(R.string.newnym), getNotifyId(), R.drawable.ic_stat_tor_off); - showToolbarNotification("Genesis is sleeping",NOTIFY_ID,R.drawable.ic_stat_tor_off); + showToolbarNotification("Genesis is sleeping | Internet connectivity issue",NOTIFY_ID,R.drawable.ic_stat_tor_off); } } else @@ -1427,28 +1070,179 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb } }; + private void initControlConnection() { + if (conn != null) { + logNotice("SUCCESS connected to Tor control port."); + try { + String confSocks = conn.getInfo("net/listeners/socks"); + StringTokenizer st = new StringTokenizer(confSocks, " "); + + confSocks = st.nextToken().split(":")[1]; + confSocks = confSocks.substring(0, confSocks.length() - 1); + mPortSOCKS = Integer.parseInt(confSocks); + + String confHttp = conn.getInfo("net/listeners/httptunnel"); + st = new StringTokenizer(confHttp, " "); + + confHttp = st.nextToken().split(":")[1]; + confHttp = confHttp.substring(0, confHttp.length() - 1); + mPortHTTP = Integer.parseInt(confHttp); + + String confDns = conn.getInfo("net/listeners/dns"); + st = new StringTokenizer(confDns, " "); + if (st.hasMoreTokens()) { + confDns = st.nextToken().split(":")[1]; + confDns = confDns.substring(0, confDns.length() - 1); + mPortDns = Integer.parseInt(confDns); + Prefs.getSharedPrefs(getApplicationContext()).edit().putInt(VpnPrefs.PREFS_DNS_PORT, mPortDns).apply(); + } + + String confTrans = conn.getInfo("net/listeners/trans"); + st = new StringTokenizer(confTrans, " "); + if (st.hasMoreTokens()) { + confTrans = st.nextToken().split(":")[1]; + confTrans = confTrans.substring(0, confTrans.length() - 1); + mPortTrans = Integer.parseInt(confTrans); + } + + sendCallbackPorts(mPortSOCKS, mPortHTTP, mPortDns, mPortTrans); + orbotLocalConstants.mIsTorInitialized = true; + + } catch (IOException e) { + Log.i("sad","asd"); + e.printStackTrace(); + stopTorOnError(e.getLocalizedMessage()); + conn = null; + } + } + } + + public void sendSignalActive() { + if (conn != null && mCurrentStatus == STATUS_ON) { + try { + conn.signal("ACTIVE"); + } catch (IOException e) { + debug("error send active: " + e.getLocalizedMessage()); + } + } + } + + public void newIdentity() { + //it is possible to not have a connection yet, and someone might try to newnym + if (conn != null) { + new Thread() { + public void run() { + try { + int iconId = R.mipmap.ic_stat_tor_logo; + + if (conn != null && mCurrentStatus == STATUS_ON && Prefs.expandedNotifications() && mConnectivity) + showToolbarNotification(getString(R.string.newnym), NOTIFY_ID, R.drawable.ic_stat_starting_tor_logo); + + conn.signal(TorControlCommands.SIGNAL_NEWNYM); + + sleep(1000); + if(mConnectivity) + enableNotification(); + + } catch (Exception ioe) { + debug("error requesting newnym: " + ioe.getLocalizedMessage()); + } + } + }.start(); + } + } + + protected void sendCallbackBandwidth(long lastWritten, long lastRead, long totalWritten, long totalRead) { + Intent intent = new Intent(LOCAL_ACTION_BANDWIDTH); + + intent.putExtra("totalWritten", totalWritten); + intent.putExtra("totalRead", totalRead); + intent.putExtra("lastWritten", lastWritten); + intent.putExtra("lastRead", lastRead); + intent.putExtra(EXTRA_STATUS, mCurrentStatus); + + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + } + + int e=0; + private void sendCallbackLogMessage(String logMessage) + { + + if(logMessage.contains("Bootstrapped 100%")){ + orbotLocalConstants.mIsTorInitialized = true; + } + mHandler.post(() -> { + Intent intent = new Intent(LOCAL_ACTION_LOG); + intent.putExtra(LOCAL_EXTRA_LOG, logMessage); + intent.putExtra(EXTRA_STATUS, mCurrentStatus); + orbotLocalConstants.mTorLogsHistory.add(new logRowModel(logMessage, localHelperMethod.getCurrentTime())); + + if(!mConnectivity){ + orbotLocalConstants.mTorLogsStatus = "No internet connection"; + }else { + orbotLocalConstants.mTorLogsStatus = logMessage; + } + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + }); + + } + + public boolean getConnectivity(){ + return mConnectivity; + } + + private void sendCallbackPorts(int socksPort, int httpPort, int dnsPort, int transPort) { + Intent intent = new Intent(LOCAL_ACTION_PORTS); // You can also include some extra data. + intent.putExtra(EXTRA_SOCKS_PROXY_PORT, socksPort); + intent.putExtra(EXTRA_HTTP_PROXY_PORT, httpPort); + intent.putExtra(EXTRA_DNS_PORT, dnsPort); + intent.putExtra(EXTRA_TRANS_PORT, transPort); + + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + + if (Prefs.useVpn()) + mVpnManager.handleIntent(new Builder(), intent); + + } + + protected void sendCallbackStatus(String currentStatus) { + mCurrentStatus = currentStatus; + Intent intent = getActionStatusIntent(currentStatus); + sendBroadcastOnlyToOrbot(intent); // send for Orbot internals, using secure local broadcast + sendBroadcast(intent); // send for any apps that are interested + } + + /** + * Send a secure broadcast only to Orbot itself + * + * @see {@link ContextWrapper#sendBroadcast(Intent)} + * @see {@link LocalBroadcastManager} + */ + private boolean sendBroadcastOnlyToOrbot(Intent intent) { + return LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + } + + private Intent getActionStatusIntent(String currentStatus) { + Intent intent = new Intent(ACTION_STATUS); + intent.putExtra(EXTRA_STATUS, currentStatus); + return intent; + } + private StringBuffer processSettingsImpl(StringBuffer extraLines) throws IOException { logNotice(getString(R.string.updating_settings_in_tor_service)); - SharedPreferences prefs = Prefs.getSharedPrefs(getApplicationContext()); boolean useBridges = Prefs.bridgesEnabled(); - boolean becomeRelay = prefs.getBoolean(OrbotConstants.PREF_OR, false); boolean ReachableAddresses = prefs.getBoolean(OrbotConstants.PREF_REACHABLE_ADDRESSES, false); - boolean enableStrictNodes = prefs.getBoolean("pref_strict_nodes", false); String entranceNodes = prefs.getString("pref_entrance_nodes", ""); String exitNodes = prefs.getString("pref_exit_nodes", ""); String excludeNodes = prefs.getString("pref_exclude_nodes", ""); if (!useBridges) { - extraLines.append("UseBridges 0").append('\n'); - - if (Prefs.useVpn()) //set the proxy here if we aren't using a bridge - { - + if (Prefs.useVpn()) { //set the proxy here if we aren't using a bridge if (!mIsLollipop) { String proxyType = "socks5"; extraLines.append(proxyType + "Proxy" + ' ' + OrbotVpnManager.sSocksProxyLocalhost + ':' + OrbotVpnManager.sSocksProxyServerPort).append('\n'); @@ -1463,159 +1257,203 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb String proxyPass = prefs.getString("pref_proxy_password", null); if ((proxyHost != null && proxyHost.length() > 0) && (proxyPort != null && proxyPort.length() > 0)) { - extraLines.append(proxyType + "Proxy" + ' ' + proxyHost + ':' + proxyPort).append('\n'); + extraLines.append(proxyType).append("Proxy").append(' ').append(proxyHost).append(':').append(proxyPort).append('\n'); if (proxyUser != null && proxyPass != null) { if (proxyType.equalsIgnoreCase("socks5")) { - extraLines.append("Socks5ProxyUsername" + ' ' + proxyUser).append('\n'); - extraLines.append("Socks5ProxyPassword" + ' ' + proxyPass).append('\n'); + extraLines.append("Socks5ProxyUsername").append(' ').append(proxyUser).append('\n'); + extraLines.append("Socks5ProxyPassword").append(' ').append(proxyPass).append('\n'); } else - extraLines.append(proxyType + "ProxyAuthenticator" + ' ' + proxyUser + ':' + proxyPort).append('\n'); + extraLines.append(proxyType).append("ProxyAuthenticator").append(' ').append(proxyUser).append(':').append(proxyPort).append('\n'); } else if (proxyPass != null) - extraLines.append(proxyType + "ProxyAuthenticator" + ' ' + proxyUser + ':' + proxyPort).append('\n'); - - + extraLines.append(proxyType).append("ProxyAuthenticator").append(' ').append(proxyUser).append(':').append(proxyPort).append('\n'); } } } } else { - if (fileObfsclient != null - && fileObfsclient.exists() - && fileObfsclient.canExecute()) { - loadBridgeDefaults(); + loadBridgeDefaults(); + extraLines.append("UseBridges 1").append('\n'); + // extraLines.append("UpdateBridgesFromAuthority 1").append('\n'); - extraLines.append("UseBridges 1").append('\n'); - // extraLines.append("UpdateBridgesFromAuthority 1").append('\n'); + String bridgeList = Prefs.getBridgesList(); - String bridgeList = Prefs.getBridgesList(); - boolean obfs3Bridges = bridgeList.contains("obfs3"); - boolean obfs4Bridges = bridgeList.contains("obfs4"); - boolean meekBridges = bridgeList.contains("meek"); + String builtInBridgeType = null; - //check if any PT bridges are needed - if (obfs3Bridges) - extraLines.append("ClientTransportPlugin obfs3 exec ") - .append(fileObfsclient.getAbsolutePath()).append('\n'); + //check if any PT bridges are needed + if (bridgeList.contains("obfs")) { - if (obfs4Bridges) - extraLines.append("ClientTransportPlugin obfs4 exec ") - .append(fileObfsclient.getAbsolutePath()).append('\n'); + extraLines.append("ClientTransportPlugin obfs3 socks5 127.0.0.1:" + IPtProxy.obfs3Port()).append('\n'); + extraLines.append("ClientTransportPlugin obfs4 socks5 127.0.0.1:" + IPtProxy.obfs4Port()).append('\n'); - if (meekBridges) - extraLines.append("ClientTransportPlugin meek_lite exec " + fileObfsclient.getCanonicalPath()).append('\n'); + if (bridgeList.equals("obfs4")) + builtInBridgeType = "obfs4"; + } - if (bridgeList != null && bridgeList.length() > 5) //longer then 1 = some real values here - { - String[] bridgeListLines = parseBridgesFromSettings(bridgeList); - int bridgeIdx = (int) Math.floor(Math.random() * ((double) bridgeListLines.length)); - String bridgeLine = bridgeListLines[bridgeIdx]; - extraLines.append("Bridge "); - extraLines.append(bridgeLine); - extraLines.append("\n"); - /** - for (String bridgeConfigLine : bridgeListLines) { - if (!TextUtils.isEmpty(bridgeConfigLine)) { - extraLines.append("Bridge "); - extraLines.append(bridgeConfigLine.trim()); - extraLines.append("\n"); - } + if (bridgeList.equals("meek")) { + extraLines.append("ClientTransportPlugin meek_lite socks5 127.0.0.1:" + IPtProxy.meekPort()).append('\n'); + builtInBridgeType = "meek_lite"; + } - }**/ - } else { + if (bridgeList.equals("snowflake")) { + extraLines.append("ClientTransportPlugin snowflake socks5 127.0.0.1:" + IPtProxy.snowflakePort()).append('\n'); + builtInBridgeType = "snowflake"; + } - String type = "obfs4"; - - if (meekBridges) - type = "meek_lite"; - - getBridges(type, extraLines); - - } - } else { - throw new IOException("Bridge binary does not exist: " + fileObfsclient.getCanonicalPath()); + if (!TextUtils.isEmpty(builtInBridgeType)) + getBridges(builtInBridgeType, extraLines); + else { + String[] bridgeListLines = parseBridgesFromSettings(bridgeList); + int bridgeIdx = (int) Math.floor(Math.random() * ((double) bridgeListLines.length)); + String bridgeLine = bridgeListLines[bridgeIdx]; + extraLines.append("Bridge "); + extraLines.append(bridgeLine); + extraLines.append("\n"); } } - //only apply GeoIP if you need it File fileGeoIP = new File(appBinHome, GEOIP_ASSET_KEY); File fileGeoIP6 = new File(appBinHome, GEOIP6_ASSET_KEY); if (fileGeoIP.exists()) { - extraLines.append("GeoIPFile" + ' ' + fileGeoIP.getCanonicalPath()).append('\n'); - extraLines.append("GeoIPv6File" + ' ' + fileGeoIP6.getCanonicalPath()).append('\n'); + extraLines.append("GeoIPFile" + ' ').append(fileGeoIP.getCanonicalPath()).append('\n'); + extraLines.append("GeoIPv6File" + ' ').append(fileGeoIP6.getCanonicalPath()).append('\n'); } if (!TextUtils.isEmpty(entranceNodes)) - extraLines.append("EntryNodes" + ' ' + entranceNodes).append('\n'); + extraLines.append("EntryNodes" + ' ').append(entranceNodes).append('\n'); if (!TextUtils.isEmpty(exitNodes)) - extraLines.append("ExitNodes" + ' ' + exitNodes).append('\n'); + extraLines.append("ExitNodes" + ' ').append(exitNodes).append('\n'); if (!TextUtils.isEmpty(excludeNodes)) - extraLines.append("ExcludeNodes" + ' ' + excludeNodes).append('\n'); + extraLines.append("ExcludeNodes" + ' ').append(excludeNodes).append('\n'); - extraLines.append("StrictNodes" + ' ' + (enableStrictNodes ? "1" : "0")).append('\n'); + extraLines.append("StrictNodes" + ' ').append(enableStrictNodes ? "1" : "0").append('\n'); try { if (ReachableAddresses) { - String ReachableAddressesPorts = - prefs.getString(OrbotConstants.PREF_REACHABLE_ADDRESSES_PORTS, "*:80,*:443"); - - extraLines.append("ReachableAddresses" + ' ' + ReachableAddressesPorts).append('\n'); - + String ReachableAddressesPorts = prefs.getString(OrbotConstants.PREF_REACHABLE_ADDRESSES_PORTS, "*:80,*:443"); + extraLines.append("ReachableAddresses" + ' ').append(ReachableAddressesPorts).append('\n'); } } catch (Exception e) { showToolbarNotification(getString(R.string.your_reachableaddresses_settings_caused_an_exception_), ERROR_NOTIFY_ID, R.drawable.ic_stat_notifyerr); - return null; } try { if (becomeRelay && (!useBridges) && (!ReachableAddresses)) { - int ORPort = Integer.parseInt(prefs.getString(OrbotConstants.PREF_OR_PORT, "9001")); + int ORPort = Integer.parseInt(Objects.requireNonNull(prefs.getString(OrbotConstants.PREF_OR_PORT, "9001"))); String nickname = prefs.getString(OrbotConstants.PREF_OR_NICKNAME, "Orbot"); - String dnsFile = writeDNSFile(); - extraLines.append("ServerDNSResolvConfFile" + ' ' + dnsFile).append('\n'); - extraLines.append("ORPort" + ' ' + ORPort).append('\n'); - extraLines.append("Nickname" + ' ' + nickname).append('\n'); - extraLines.append("ExitPolicy" + ' ' + "reject *:*").append('\n'); + extraLines.append("ServerDNSResolvConfFile").append(' ').append(dnsFile).append('\n'); + extraLines.append("ORPort").append(' ').append(ORPort).append('\n'); + extraLines.append("Nickname").append(' ').append(nickname).append('\n'); + extraLines.append("ExitPolicy").append(' ').append("reject *:*").append('\n'); } } catch (Exception e) { showToolbarNotification(getString(R.string.your_relay_settings_caused_an_exception_), ERROR_NOTIFY_ID, R.drawable.ic_stat_notifyerr); - - return null; } - ContentResolver mCR = getApplicationContext().getContentResolver(); + if (false) { + ContentResolver contentResolver = getApplicationContext().getContentResolver(); + addV3OnionServicesToTorrc(extraLines, contentResolver); + addV3ClientAuthToTorrc(extraLines, contentResolver); + addV2HiddenServicesToTorrc(extraLines, contentResolver); + addV2ClientCookiesToTorrc(extraLines, contentResolver); + } + return extraLines; + } + + public static String formatBandwidthCount(Context context, long bitsPerSecond) { + NumberFormat nf = NumberFormat.getInstance(Locale.getDefault()); + if (bitsPerSecond < 1e6) + return nf.format(Math.round(((float) ((int) (bitsPerSecond * 10 / 1024)) / 10))) + + "kbps"; + else + return nf.format(Math.round(((float) ((int) (bitsPerSecond * 100 / 1024 / 1024)) / 100))) + + "mbps"; + } + + private void addV3OnionServicesToTorrc(StringBuffer torrc, ContentResolver contentResolver) { try { - /* ---- Hidden Services ---- */ - Cursor hidden_services = mCR.query(HS_CONTENT_URI, hsProjection, HiddenService.ENABLED + "=1", null, null); + Cursor onionServices = contentResolver.query(V3_ONION_SERVICES_CONTENT_URI, V3_ONION_SERVICE_PROJECTION, OnionService.ENABLED + "=1", null, null); + if (onionServices != null) { + while (onionServices.moveToNext()) { + int id = onionServices.getInt(onionServices.getColumnIndex(OnionService._ID)); + int localPort = onionServices.getInt(onionServices.getColumnIndex(OnionService.PORT)); + int onionPort = onionServices.getInt(onionServices.getColumnIndex(OnionService.ONION_PORT)); + String path = onionServices.getString(onionServices.getColumnIndex(OnionService.PATH)); + String domain = onionServices.getString(onionServices.getColumnIndex(OnionService.DOMAIN)); + if (path == null) { + path = "v3"; + if (domain == null) + path += UUID.randomUUID().toString(); + else + path += localPort; + ContentValues cv = new ContentValues(); + cv.put(OnionService.PATH, path); + contentResolver.update(V3_ONION_SERVICES_CONTENT_URI, cv, OnionService._ID + "=" + id, null); + } + String v3DirPath = new File(mV3OnionBasePath.getAbsolutePath(), path).getCanonicalPath(); + torrc.append("HiddenServiceDir ").append(v3DirPath).append("\n"); + torrc.append("HiddenServiceVersion 3").append("\n"); + torrc.append("HiddenServicePort ").append(onionPort).append(" 127.0.0.1:").append(localPort).append("\n"); + } + onionServices.close(); + } + } catch (Exception e) { + Log.i("sad","asd"); + Log.e(TAG, e.getLocalizedMessage()); + } + } + + private void addV2HiddenServicesToTorrc(StringBuffer torrc, ContentResolver contentResolver) { + try { + Cursor hidden_services = contentResolver.query(V2_HS_CONTENT_URI, LEGACY_V2_ONION_SERVICE_PROJECTION, OnionService.ENABLED + "=1", null, null); if (hidden_services != null) { try { while (hidden_services.moveToNext()) { - String HSname = hidden_services.getString(hidden_services.getColumnIndex(HiddenService.NAME)); - Integer HSLocalPort = hidden_services.getInt(hidden_services.getColumnIndex(HiddenService.PORT)); - Integer HSOnionPort = hidden_services.getInt(hidden_services.getColumnIndex(HiddenService.ONION_PORT)); - Integer HSAuthCookie = hidden_services.getInt(hidden_services.getColumnIndex(HiddenService.AUTH_COOKIE)); - String hsDirPath = new File(mHSBasePath.getAbsolutePath(), "hs" + HSLocalPort).getCanonicalPath(); + int id = hidden_services.getInt(hidden_services.getColumnIndex(OnionService._ID)); + String HSname = hidden_services.getString(hidden_services.getColumnIndex(OnionService.NAME)); + String domain = hidden_services.getString(hidden_services.getColumnIndex(OnionService.DOMAIN)); + int HSLocalPort = hidden_services.getInt(hidden_services.getColumnIndex(OnionService.PORT)); + int HSOnionPort = hidden_services.getInt(hidden_services.getColumnIndex(OnionService.ONION_PORT)); + int HSAuthCookie = hidden_services.getInt(hidden_services.getColumnIndex(OnionService.AUTH_COOKIE)); + String path = hidden_services.getString(hidden_services.getColumnIndex(OnionService.PATH)); + + // logic to fix bug where you can't have 2+ hidden services on same local port without breaking services that were configured before the bug fix + if (path == null) { + String newPath = "hs"; + if (domain == null) + newPath +=UUID.randomUUID().toString(); + else + newPath += HSLocalPort; + + ContentValues cv = new ContentValues(); + cv.put(OnionService.PATH, newPath); + contentResolver.update(V2_HS_CONTENT_URI, cv, OnionService._ID + "=" + id, null); + path = newPath; + } + + String hsDirPath = new File(mHSBasePath.getAbsolutePath(), path).getCanonicalPath(); + debug("Adding hidden service on port: " + HSLocalPort); - extraLines.append("HiddenServiceDir" + ' ' + hsDirPath).append('\n'); - extraLines.append("HiddenServicePort" + ' ' + HSOnionPort + " 127.0.0.1:" + HSLocalPort).append('\n'); - extraLines.append("HiddenServiceVersion 2").append('\n'); + torrc.append("HiddenServiceDir" + ' ' + hsDirPath).append('\n'); + torrc.append("HiddenServiceVersion 2").append('\n'); + torrc.append("HiddenServicePort" + ' ' + HSOnionPort + " 127.0.0.1:" + HSLocalPort).append('\n'); if (HSAuthCookie == 1) - extraLines.append("HiddenServiceAuthorizeClient stealth " + HSname).append('\n'); + torrc.append("HiddenServiceAuthorizeClient stealth " + HSname).append('\n'); } } catch (NumberFormatException e) { Log.e(OrbotConstants.TAG, "error parsing hsport", e); @@ -1626,31 +1464,57 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb hidden_services.close(); } } catch (SecurityException se) { - Log.i("sda","ASd"); + Log.i("sad","asd"); } + } + public static String buildV3ClientAuthFile(String domain, String keyHash) { + return domain + ":descriptor:x25519:" + keyHash; + } + + private void addV3ClientAuthToTorrc(StringBuffer torrc, ContentResolver contentResolver) { + Cursor v3auths = contentResolver.query(V3_CLIENT_AUTH_URI, V3_CLIENT_AUTH_PROJECTION, V3ClientAuth.ENABLED + "=1", null, null); + if (v3auths != null) { + for (File file : mV3AuthBasePath.listFiles()) { + if (!file.isDirectory()) + file.delete(); // todo the adapter should maybe just write these files and not do this in service... + } + torrc.append("ClientOnionAuthDir " + mV3AuthBasePath.getAbsolutePath()).append('\n'); + try { + int i = 0; + while (v3auths.moveToNext()) { + String domain = v3auths.getString(v3auths.getColumnIndex(V3ClientAuth.DOMAIN)); + String hash = v3auths.getString(v3auths.getColumnIndex(V3ClientAuth.HASH)); + File authFile = new File(mV3AuthBasePath, (i++) + ".auth_private"); + authFile.createNewFile(); + FileOutputStream fos = new FileOutputStream(authFile); + fos.write(buildV3ClientAuthFile(domain, hash).getBytes()); + fos.close(); + } + } catch (Exception e) { + Log.e(TAG, "error adding v3 client auth..."); + } + } + } + + private void addV2ClientCookiesToTorrc(StringBuffer torrc, ContentResolver contentResolver) { try { - - /* ---- Client Cookies ---- */ - Cursor client_cookies = mCR.query(COOKIE_CONTENT_URI, cookieProjection, ClientCookie.ENABLED + "=1", null, null); + Cursor client_cookies = contentResolver.query(COOKIE_CONTENT_URI, LEGACY_COOKIE_PROJECTION, ClientCookie.ENABLED + "=1", null, null); if (client_cookies != null) { try { while (client_cookies.moveToNext()) { String domain = client_cookies.getString(client_cookies.getColumnIndex(ClientCookie.DOMAIN)); String cookie = client_cookies.getString(client_cookies.getColumnIndex(ClientCookie.AUTH_COOKIE_VALUE)); - extraLines.append("HidServAuth" + ' ' + domain + ' ' + cookie).append('\n'); + torrc.append("HidServAuth" + ' ' + domain + ' ' + cookie).append('\n'); } } catch (Exception e) { Log.e(OrbotConstants.TAG, "error starting share server", e); } - client_cookies.close(); } } catch (SecurityException se) { - Log.i("sda","ASd"); + Log.i("sad","asd"); } - - return extraLines; } //using Google DNS for now as the public DNS server @@ -1704,7 +1568,6 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb @Override public IBinder onBind(Intent intent) { Log.e(TAG, "onBind"); - //do nothing here return super.onBind(intent); // invoking super class will call onRevoke() when appropriate } @@ -1791,6 +1654,7 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb in.close(); } catch (Exception e) { + Log.i("sad","asd"); e.printStackTrace(); } } @@ -1847,27 +1711,28 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb } } - public static final class HiddenService implements BaseColumns { + + public static final class OnionService implements BaseColumns { public static final String NAME = "name"; public static final String PORT = "port"; public static final String ONION_PORT = "onion_port"; public static final String DOMAIN = "domain"; public static final String AUTH_COOKIE = "auth_cookie"; public static final String AUTH_COOKIE_VALUE = "auth_cookie_value"; - public static final String CREATED_BY_USER = "created_by_user"; public static final String ENABLED = "enabled"; + public static final String PATH = "filepath"; + } - private HiddenService() { - } + public static final class V3ClientAuth implements BaseColumns { + public static final String DOMAIN = "domain"; + public static final String HASH = "hash"; + public static final String ENABLED = "enabled"; } 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() { - } } // for bridge loading from the assets default bridges.txt file @@ -1883,6 +1748,7 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb public Bridge(){ } } + private class IncomingIntentRouter implements Runnable { Intent mIntent; @@ -1891,11 +1757,20 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb } public void run() { - String action = mIntent.getAction(); if (!TextUtils.isEmpty(action)) { if (action.equals(ACTION_START) || action.equals(ACTION_START_ON_BOOT)) { + + //if (useIPtObfsMeekProxy()) + // IPtProxy.startObfs4Proxy("DEBUG", true, false); + + if (useIPtSnowflakeProxy()) + startSnowflakeClient(); + + if (Prefs.beSnowflakeProxy()) + runSnowflakeProxy(); + startTor(); replyWithStatus(mIntent); @@ -1919,11 +1794,8 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb if (mVpnManager != null && (!mVpnManager.isStarted())) { //start VPN here Intent vpnIntent = VpnService.prepare(OrbotService.this); - if (vpnIntent == null) //then we can run the VPN - { + if (vpnIntent == null) { //then we can run the VPN mVpnManager.handleIntent(new Builder(), mIntent); - - } } @@ -1936,10 +1808,11 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb mVpnManager.handleIntent(new Builder(), mIntent); } else if (action.equals(ACTION_STATUS)) { replyWithStatus(mIntent); - } else if (action.equals(CMD_SIGNAL_HUP)) { + } else if (action.equals(TorControlCommands.SIGNAL_RELOAD)) { requestTorRereadConfig(); - } else if (action.equals(CMD_NEWNYM)) { - newIdentity(); + } + else if (action.equals(CMD_NEWNYM)) { + newIdentity(); } else if (action.equals(CMD_SETTING)) { onSettingRegister(); @@ -1947,9 +1820,7 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb else if (action.equals(CMD_ACTIVE)) { sendSignalActive(); } else if (action.equals(CMD_SET_EXIT)) { - setExitNode(mIntent.getStringExtra("exit")); - } else { Log.w(OrbotConstants.TAG, "unhandled OrbotService Intent: " + action); } @@ -1957,27 +1828,6 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb } } - public String getProxyStatus() { - return mCurrentStatus; - } - - private static OrbotService self = null; - - public static OrbotService getServiceObject(){ - return self; - } - - public void onSettingRegister(){ - try { - Intent intent = null; - intent = new Intent(this, Class.forName("com.darkweb.genesissearchengine.appManager.settingManager.notificationManager.settingNotificationController")); - intent.setFlags(FLAG_ACTIVITY_NEW_TASK); - getApplicationContext().startActivity(intent); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - } - public void disableNotification(){ if(mNotificationManager!=null){ mNotificationManager.cancel(NOTIFY_ID); @@ -1992,8 +1842,22 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb } public void enableNotification(){ - orbotLocalConstants.mNotificationStatus = 1; - showToolbarNotification(0+"kbps ⇣ / " +0+"kbps ⇡", HS_NOTIFY_ID, R.mipmap.ic_stat_tor_logo); + if(mConnectivity && orbotLocalConstants.mIsTorInitialized){ + orbotLocalConstants.mNotificationStatus = 1; + showToolbarNotification(0+"kbps ⇣ / " +0+"kbps ⇡", HS_NOTIFY_ID, R.mipmap.ic_stat_tor_logo); + } + } + + public void onSettingRegister(){ + try { + Intent intent = null; + intent = new Intent(this, Class.forName("com.darkweb.genesissearchengine.appManager.settingManager.notificationManager.settingNotificationController")); + intent.setFlags(FLAG_ACTIVITY_NEW_TASK); + getApplicationContext().startActivity(intent); + } catch (ClassNotFoundException e) { + Log.i("sad","asd"); + e.printStackTrace(); + } } private class ActionBroadcastReceiver extends BroadcastReceiver { diff --git a/orbotmanager/src/main/java/org/torproject/android/service/StartTorReceiver.java b/orbotmanager/src/main/java/org/torproject/android/service/StartTorReceiver.java index cbfb58a0..3fb77e91 100644 --- a/orbotmanager/src/main/java/org/torproject/android/service/StartTorReceiver.java +++ b/orbotmanager/src/main/java/org/torproject/android/service/StartTorReceiver.java @@ -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; diff --git a/orbotmanager/src/main/java/org/torproject/android/proxy/TorEventHandler.java b/orbotmanager/src/main/java/org/torproject/android/service/TorEventHandler.java similarity index 72% rename from orbotmanager/src/main/java/org/torproject/android/proxy/TorEventHandler.java rename to orbotmanager/src/main/java/org/torproject/android/service/TorEventHandler.java index 1a15c0e3..5340732b 100644 --- a/orbotmanager/src/main/java/org/torproject/android/proxy/TorEventHandler.java +++ b/orbotmanager/src/main/java/org/torproject/android/service/TorEventHandler.java @@ -1,251 +1,220 @@ -package org.torproject.android.proxy; - -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 java.text.NumberFormat; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.StringTokenizer; - -/** - * Created by n8fr8 on 9/25/16. - */ -public class TorEventHandler implements EventHandler, TorServiceConstants { - - private final static int BW_THRESDHOLD = 10000; - private OrbotService mService; - private long lastRead = -1; - private long lastWritten = -1; - private long mTotalTrafficWritten = 0; - private long mTotalTrafficRead = 0; - private NumberFormat mNumberFormat; - private HashMap hmBuiltNodes = new HashMap<>(); - - public TorEventHandler(OrbotService service) { - mService = service; - mNumberFormat = NumberFormat.getInstance(Locale.getDefault()); //localized numbers! - - } - - public HashMap getNodes() { - return hmBuiltNodes; - } - - @Override - public void message(String severity, String msg) { - - if (severity.equalsIgnoreCase("debug")) - mService.debug(severity + ": " + msg); - else - mService.logNotice(severity + ": " + msg); - } - - @Override - public void newDescriptors(List orList) { - - for (String desc : orList) - mService.debug("descriptors: " + desc); - - } - - @Override - public void orConnStatus(String status, String orName) { - - String sb = "orConnStatus (" + - parseNodeName(orName) + - "): " + - status; - mService.debug(sb); - } - - @Override - public void streamStatus(String status, String streamID, String target) { - - String sb = "StreamStatus (" + - (streamID) + - "): " + - status; - mService.debug(sb); - } - - @Override - public void unrecognized(String type, String msg) { - - String sb = "Message (" + - type + - "): " + - msg; - mService.logNotice(sb); - } - - @Override - public void bandwidthUsed(long read, long written) { - - if (lastWritten > BW_THRESDHOLD || lastRead > BW_THRESDHOLD) { - - int iconId = R.mipmap.ic_stat_tor_logo; - - if (read > 0 || written > 0){ - if(orbotLocalConstants.mIsTorInitialized){ - 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); - - mTotalTrafficWritten += written; - mTotalTrafficRead += read; - - mService.sendCallbackBandwidth(lastWritten, lastRead, mTotalTrafficWritten, mTotalTrafficRead); - - lastWritten = 0; - lastRead = 0; - } - - lastWritten += written; - lastRead += read; - - } - - 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")) { - mService.sendCallbackStatus(STATUS_ON); - } - - if (Prefs.useDebugLogging()) { - StringBuilder sb = new StringBuilder(); - sb.append("Circuit ("); - sb.append((circID)); - sb.append(") "); - sb.append(status); - sb.append(": "); - - StringTokenizer st = new StringTokenizer(path, ","); - Node node; - - boolean isFirstNode = true; - int nodeCount = st.countTokens(); - - while (st.hasMoreTokens()) { - String nodePath = st.nextToken(); - String nodeId = null, nodeName = null; - - String[] nodeParts; - - if (nodePath.contains("=")) - nodeParts = nodePath.split("="); - else - nodeParts = nodePath.split("~"); - - if (nodeParts.length == 1) { - nodeId = nodeParts[0].substring(1); - nodeName = nodeId; - } else if (nodeParts.length == 2) { - nodeId = nodeParts[0].substring(1); - nodeName = nodeParts[1]; - } - - if (nodeId == null) - continue; - - node = hmBuiltNodes.get(nodeId); - - if (node == null) { - node = new Node(); - node.id = nodeId; - node.name = nodeName; - } - - node.status = status; - - sb.append(node.name); - - if (!TextUtils.isEmpty(node.ipAddress)) - sb.append("(").append(node.ipAddress).append(")"); - - if (st.hasMoreTokens()) - sb.append(" > "); - - if (status.equals("EXTENDED")) { - - if (isFirstNode) { - hmBuiltNodes.put(node.id, node); - - if (node.ipAddress == null && (!node.isFetchingInfo) && Prefs.useDebugLogging()) { - node.isFetchingInfo = true; - mService.exec(new ExternalIPFetcher(mService, node, OrbotService.mPortHTTP)); - } - - isFirstNode = false; - } - } else if (status.equals("BUILT")) { - // mService.logNotice(sb.toString()); - - if (Prefs.useDebugLogging() && nodeCount > 3) - mService.debug(sb.toString()); - } else if (status.equals("CLOSED")) { - // mService.logNotice(sb.toString()); - hmBuiltNodes.remove(node.id); - } - - } - - - } - - - } - - private String parseNodeName(String node) { - if (node.indexOf('=') != -1) { - return (node.substring(node.indexOf("=") + 1)); - } else if (node.indexOf('~') != -1) { - return (node.substring(node.indexOf("~") + 1)); - } else - return node; - } - - public static class Node { - public String status; - public String id; - public String name; - public String ipAddress; - public String country; - public String organization; - - public boolean isFetchingInfo = false; - } -} +package org.torproject.android.service; + +import android.text.TextUtils; + +import net.freehaven.tor.control.EventHandler; + +import org.torproject.android.service.util.ExternalIPFetcher; +import org.torproject.android.service.util.Prefs; +import org.torproject.android.service.wrapper.orbotLocalConstants; + +import java.util.HashMap; +import java.util.List; +import java.util.StringTokenizer; + +/** + * Created by n8fr8 on 9/25/16. + */ +public class TorEventHandler implements EventHandler, TorServiceConstants { + + private final static int BW_THRESDHOLD = 10000; + private final OrbotService mService; + private long lastRead = -1; + private long lastWritten = -1; + private long mTotalTrafficWritten = 0; + private long mTotalTrafficRead = 0; + private final HashMap hmBuiltNodes = new HashMap<>(); + + public TorEventHandler(OrbotService service) { + mService = service; + } + + public HashMap getNodes() { + return hmBuiltNodes; + } + + @Override + public void message(String severity, String msg) { + if (severity.equalsIgnoreCase("debug")) + mService.debug(severity + ": " + msg); + else + mService.logNotice(severity + ": " + msg); + } + + @Override + public void newDescriptors(List orList) { + + for (String desc : orList) + mService.debug("descriptors: " + desc); + + } + + @Override + public void orConnStatus(String status, String orName) { + + String sb = "orConnStatus (" + + parseNodeName(orName) + + "): " + + status; + mService.debug(sb); + } + + @Override + public void streamStatus(String status, String streamID, String target) { + + String sb = "StreamStatus (" + + (streamID) + + "): " + + status; + mService.debug(sb); + } + + @Override + public void unrecognized(String type, String msg) { + + String sb = "Message (" + + type + + "): " + + msg; + mService.logNotice(sb); + } + + @Override + public void bandwidthUsed(long read, long written) { + + if (lastWritten > BW_THRESDHOLD || lastRead > BW_THRESDHOLD) { + + int iconId = R.drawable.ic_stat_starting_tor_logo; + + if (read > 0 || written > 0 || OrbotService.getServiceObject().getConnectivity()) + iconId = R.mipmap.ic_stat_tor_logo; + + 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(written, read, mTotalTrafficWritten, mTotalTrafficRead); + + lastWritten = 0; + lastRead = 0; + } + + lastWritten += written; + lastRead += read; + + } + + 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")){ + mService.sendCallbackStatus(STATUS_ON); + } + + if (Prefs.useDebugLogging()) { + StringBuilder sb = new StringBuilder(); + sb.append("Circuit ("); + sb.append((circID)); + sb.append(") "); + sb.append(status); + sb.append(": "); + + StringTokenizer st = new StringTokenizer(path, ","); + Node node; + + boolean isFirstNode = true; + int nodeCount = st.countTokens(); + + while (st.hasMoreTokens()) { + String nodePath = st.nextToken(); + String nodeId = null, nodeName = null; + + String[] nodeParts; + + if (nodePath.contains("=")) + nodeParts = nodePath.split("="); + else + nodeParts = nodePath.split("~"); + + if (nodeParts.length == 1) { + nodeId = nodeParts[0].substring(1); + nodeName = nodeId; + } else if (nodeParts.length == 2) { + nodeId = nodeParts[0].substring(1); + nodeName = nodeParts[1]; + } + + if (nodeId == null) + continue; + + node = hmBuiltNodes.get(nodeId); + + if (node == null) { + node = new Node(); + node.id = nodeId; + node.name = nodeName; + } + + node.status = status; + + sb.append(node.name); + + if (!TextUtils.isEmpty(node.ipAddress)) + sb.append("(").append(node.ipAddress).append(")"); + + if (st.hasMoreTokens()) + sb.append(" > "); + + if (status.equals("EXTENDED")) { + + if (isFirstNode) { + hmBuiltNodes.put(node.id, node); + + if (node.ipAddress == null && (!node.isFetchingInfo) && Prefs.useDebugLogging()) { + node.isFetchingInfo = true; + mService.exec(new ExternalIPFetcher(mService, node, OrbotService.mPortHTTP)); + } + + isFirstNode = false; + } + } else if (status.equals("BUILT")) { + // mService.logNotice(sb.toString()); + + if (Prefs.useDebugLogging() && nodeCount > 3) + mService.debug(sb.toString()); + } else if (status.equals("CLOSED")) { + // mService.logNotice(sb.toString()); + hmBuiltNodes.remove(node.id); + } + + } + + + } + + + } + + private String parseNodeName(String node) { + if (node.indexOf('=') != -1) { + return (node.substring(node.indexOf("=") + 1)); + } else if (node.indexOf('~') != -1) { + return (node.substring(node.indexOf("~") + 1)); + } else + return node; + } + + public static class Node { + public String status; + public String id; + public String name; + public String ipAddress; + public String country; + public String organization; + + public boolean isFetchingInfo = false; + } +} diff --git a/orbotmanager/src/main/java/org/torproject/android/service/TorServiceConstants.java b/orbotmanager/src/main/java/org/torproject/android/service/TorServiceConstants.java index 82db6c6f..5ee4a778 100644 --- a/orbotmanager/src/main/java/org/torproject/android/service/TorServiceConstants.java +++ b/orbotmanager/src/main/java/org/torproject/android/service/TorServiceConstants.java @@ -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"; } diff --git a/orbotmanager/src/main/java/org/torproject/android/service/util/CustomNativeLoader.java b/orbotmanager/src/main/java/org/torproject/android/service/util/CustomNativeLoader.java index 6504b8c7..fb528621 100644 --- a/orbotmanager/src/main/java/org/torproject/android/service/util/CustomNativeLoader.java +++ b/orbotmanager/src/main/java/org/torproject/android/service/util/CustomNativeLoader.java @@ -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) { diff --git a/orbotmanager/src/main/java/org/torproject/android/service/util/CustomTorResourceInstaller.java b/orbotmanager/src/main/java/org/torproject/android/service/util/CustomTorResourceInstaller.java index 8bec9ccc..fc8acde1 100644 --- a/orbotmanager/src/main/java/org/torproject/android/service/util/CustomTorResourceInstaller.java +++ b/orbotmanager/src/main/java/org/torproject/android/service/util/CustomTorResourceInstaller.java @@ -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); } /* diff --git a/orbotmanager/src/main/java/org/torproject/android/service/util/ExternalIPFetcher.java b/orbotmanager/src/main/java/org/torproject/android/service/util/ExternalIPFetcher.java index 4addb2c5..957e1e65 100644 --- a/orbotmanager/src/main/java/org/torproject/android/service/util/ExternalIPFetcher.java +++ b/orbotmanager/src/main/java/org/torproject/android/service/util/ExternalIPFetcher.java @@ -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; diff --git a/orbotmanager/src/main/java/org/torproject/android/service/util/NativeLoader.java b/orbotmanager/src/main/java/org/torproject/android/service/util/NativeLoader.java index f97f68e0..c870025a 100644 --- a/orbotmanager/src/main/java/org/torproject/android/service/util/NativeLoader.java +++ b/orbotmanager/src/main/java/org/torproject/android/service/util/NativeLoader.java @@ -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) { diff --git a/orbotmanager/src/main/java/org/torproject/android/service/util/Prefs.java b/orbotmanager/src/main/java/org/torproject/android/service/util/Prefs.java index 8251fc88..aa39b7be 100644 --- a/orbotmanager/src/main/java/org/torproject/android/service/util/Prefs.java +++ b/orbotmanager/src/main/java/org/torproject/android/service/util/Prefs.java @@ -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); } @@ -118,4 +139,4 @@ public class Prefs { public static SharedPreferences getSharedPrefs(Context context) { return context.getSharedPreferences(OrbotConstants.PREF_TOR_SHARED_PREFS, Context.MODE_MULTI_PROCESS); } -} +} \ No newline at end of file diff --git a/orbotmanager/src/main/java/org/torproject/android/service/vpn/OrbotVpnManager.java b/orbotmanager/src/main/java/org/torproject/android/service/vpn/OrbotVpnManager.java index d9678b85..66538b04 100644 --- a/orbotmanager/src/main/java/org/torproject/android/service/vpn/OrbotVpnManager.java +++ b/orbotmanager/src/main/java/org/torproject/android/service/vpn/OrbotVpnManager.java @@ -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 lines; + ArrayList 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() { diff --git a/orbotmanager/src/main/java/org/torproject/android/service/vpn/Tun2Socks.java b/orbotmanager/src/main/java/org/torproject/android/service/vpn/Tun2Socks.java index 461a5a8d..8eda5954 100644 --- a/orbotmanager/src/main/java/org/torproject/android/service/vpn/Tun2Socks.java +++ b/orbotmanager/src/main/java/org/torproject/android/service/vpn/Tun2Socks.java @@ -50,7 +50,7 @@ public class Tun2Socks { private static HashMap mAppUidBlacklist = new HashMap<>(); static { - System.loadLibrary("tun2socks"); + //System.loadLibrary("tun2socks"); } public static void init() { diff --git a/orbotmanager/src/main/java/org/torproject/android/proxy/wrapper/LocaleHelper.java b/orbotmanager/src/main/java/org/torproject/android/service/wrapper/LocaleHelper.java similarity index 93% rename from orbotmanager/src/main/java/org/torproject/android/proxy/wrapper/LocaleHelper.java rename to orbotmanager/src/main/java/org/torproject/android/service/wrapper/LocaleHelper.java index 5308f564..25248a72 100644 --- a/orbotmanager/src/main/java/org/torproject/android/proxy/wrapper/LocaleHelper.java +++ b/orbotmanager/src/main/java/org/torproject/android/service/wrapper/LocaleHelper.java @@ -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; diff --git a/orbotmanager/src/main/java/org/torproject/android/proxy/wrapper/localHelperMethod.java b/orbotmanager/src/main/java/org/torproject/android/service/wrapper/localHelperMethod.java similarity index 91% rename from orbotmanager/src/main/java/org/torproject/android/proxy/wrapper/localHelperMethod.java rename to orbotmanager/src/main/java/org/torproject/android/service/wrapper/localHelperMethod.java index 478edfb0..063a8161 100644 --- a/orbotmanager/src/main/java/org/torproject/android/proxy/wrapper/localHelperMethod.java +++ b/orbotmanager/src/main/java/org/torproject/android/service/wrapper/localHelperMethod.java @@ -1,4 +1,4 @@ -package org.torproject.android.proxy.wrapper; +package org.torproject.android.service.wrapper; import java.util.Calendar; diff --git a/orbotmanager/src/main/java/org/torproject/android/proxy/wrapper/logRowModel.java b/orbotmanager/src/main/java/org/torproject/android/service/wrapper/logRowModel.java similarity index 87% rename from orbotmanager/src/main/java/org/torproject/android/proxy/wrapper/logRowModel.java rename to orbotmanager/src/main/java/org/torproject/android/service/wrapper/logRowModel.java index 48dddd87..3c748669 100644 --- a/orbotmanager/src/main/java/org/torproject/android/proxy/wrapper/logRowModel.java +++ b/orbotmanager/src/main/java/org/torproject/android/service/wrapper/logRowModel.java @@ -1,4 +1,4 @@ -package org.torproject.android.proxy.wrapper; +package org.torproject.android.service.wrapper; public class logRowModel { /*Private Variables*/ diff --git a/orbotmanager/src/main/java/org/torproject/android/proxy/wrapper/orbotLocalConstants.java b/orbotmanager/src/main/java/org/torproject/android/service/wrapper/orbotLocalConstants.java similarity index 91% rename from orbotmanager/src/main/java/org/torproject/android/proxy/wrapper/orbotLocalConstants.java rename to orbotmanager/src/main/java/org/torproject/android/service/wrapper/orbotLocalConstants.java index 6d2873a0..b5b7e4f6 100644 --- a/orbotmanager/src/main/java/org/torproject/android/proxy/wrapper/orbotLocalConstants.java +++ b/orbotmanager/src/main/java/org/torproject/android/service/wrapper/orbotLocalConstants.java @@ -1,4 +1,4 @@ -package org.torproject.android.proxy.wrapper; +package org.torproject.android.service.wrapper; import android.content.Context; import android.content.Intent; diff --git a/orbotmanager/src/main/jniLibs b/orbotmanager/src/main/jniLibs deleted file mode 100644 index 4dc6caa6..00000000 --- a/orbotmanager/src/main/jniLibs +++ /dev/null @@ -1 +0,0 @@ -libs \ No newline at end of file diff --git a/orbotmanager/src/main/jniLibs b/orbotmanager/src/main/jniLibs new file mode 120000 index 00000000..37559697 --- /dev/null +++ b/orbotmanager/src/main/jniLibs @@ -0,0 +1 @@ +/home/morgan/Downloads/orbot-master/orbotservice/src/main/libs \ No newline at end of file diff --git a/orbotmanager/src/main/res/drawable-hdpi/ic_refresh_white_24dp.png b/orbotmanager/src/main/res/drawable-hdpi/ic_refresh_white_24dp.png new file mode 100644 index 00000000..19bea38e Binary files /dev/null and b/orbotmanager/src/main/res/drawable-hdpi/ic_refresh_white_24dp.png differ diff --git a/orbotmanager/src/main/res/drawable-mdpi/ic_action_settings.png b/orbotmanager/src/main/res/drawable-mdpi/ic_action_settings.png new file mode 100644 index 00000000..4b965fa7 Binary files /dev/null and b/orbotmanager/src/main/res/drawable-mdpi/ic_action_settings.png differ diff --git a/orbotmanager/src/main/res/drawable-mdpi/ic_autorenew_black_36dp.png b/orbotmanager/src/main/res/drawable-mdpi/ic_autorenew_black_36dp.png new file mode 100644 index 00000000..32a688d8 Binary files /dev/null and b/orbotmanager/src/main/res/drawable-mdpi/ic_autorenew_black_36dp.png differ diff --git a/orbotmanager/src/main/res/drawable-mdpi/ic_filter_none_black_36dp.png b/orbotmanager/src/main/res/drawable-mdpi/ic_filter_none_black_36dp.png new file mode 100644 index 00000000..c4a6d7d7 Binary files /dev/null and b/orbotmanager/src/main/res/drawable-mdpi/ic_filter_none_black_36dp.png differ diff --git a/orbotmanager/src/main/res/drawable-mdpi/ic_launcher.png b/orbotmanager/src/main/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 00000000..d81f1159 Binary files /dev/null and b/orbotmanager/src/main/res/drawable-mdpi/ic_launcher.png differ diff --git a/orbotmanager/src/main/res/drawable-mdpi/ic_playlist_add_check_black_36dp.png b/orbotmanager/src/main/res/drawable-mdpi/ic_playlist_add_check_black_36dp.png new file mode 100644 index 00000000..0a3f63b8 Binary files /dev/null and b/orbotmanager/src/main/res/drawable-mdpi/ic_playlist_add_check_black_36dp.png differ diff --git a/orbotmanager/src/main/res/drawable-mdpi/ic_refresh_white_24dp.png b/orbotmanager/src/main/res/drawable-mdpi/ic_refresh_white_24dp.png new file mode 100644 index 00000000..99233274 Binary files /dev/null and b/orbotmanager/src/main/res/drawable-mdpi/ic_refresh_white_24dp.png differ diff --git a/orbotmanager/src/main/res/drawable-mdpi/ic_stat_tor_xfer.png b/orbotmanager/src/main/res/drawable-mdpi/ic_stat_tor_xfer.png new file mode 100644 index 00000000..ec893235 Binary files /dev/null and b/orbotmanager/src/main/res/drawable-mdpi/ic_stat_tor_xfer.png differ diff --git a/orbotmanager/src/main/res/drawable-mdpi/inverse.png b/orbotmanager/src/main/res/drawable-mdpi/inverse.png new file mode 100644 index 00000000..71e1adc5 Binary files /dev/null and b/orbotmanager/src/main/res/drawable-mdpi/inverse.png differ diff --git a/orbotmanager/src/main/res/drawable-xxhdpi/ic_autorenew_black_36dp.png b/orbotmanager/src/main/res/drawable-xxhdpi/ic_autorenew_black_36dp.png new file mode 100644 index 00000000..f5fcab1c Binary files /dev/null and b/orbotmanager/src/main/res/drawable-xxhdpi/ic_autorenew_black_36dp.png differ diff --git a/orbotmanager/src/main/res/drawable-xxhdpi/ic_filter_none_black_36dp.png b/orbotmanager/src/main/res/drawable-xxhdpi/ic_filter_none_black_36dp.png new file mode 100644 index 00000000..b7a72182 Binary files /dev/null and b/orbotmanager/src/main/res/drawable-xxhdpi/ic_filter_none_black_36dp.png differ diff --git a/orbotmanager/src/main/res/drawable-xxhdpi/ic_launcher.png b/orbotmanager/src/main/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 00000000..448c032b Binary files /dev/null and b/orbotmanager/src/main/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/orbotmanager/src/main/res/drawable-xxhdpi/ic_playlist_add_check_black_36dp.png b/orbotmanager/src/main/res/drawable-xxhdpi/ic_playlist_add_check_black_36dp.png new file mode 100644 index 00000000..aae1fc8d Binary files /dev/null and b/orbotmanager/src/main/res/drawable-xxhdpi/ic_playlist_add_check_black_36dp.png differ diff --git a/orbotmanager/src/main/res/drawable-xxhdpi/ic_refresh_white_24dp.png b/orbotmanager/src/main/res/drawable-xxhdpi/ic_refresh_white_24dp.png new file mode 100644 index 00000000..535f3f01 Binary files /dev/null and b/orbotmanager/src/main/res/drawable-xxhdpi/ic_refresh_white_24dp.png differ diff --git a/orbotmanager/src/main/res/drawable-xxhdpi/ic_stat_tor_xfer.png b/orbotmanager/src/main/res/drawable-xxhdpi/ic_stat_tor_xfer.png new file mode 100644 index 00000000..b04b18e7 Binary files /dev/null and b/orbotmanager/src/main/res/drawable-xxhdpi/ic_stat_tor_xfer.png differ diff --git a/orbotmanager/src/main/res/drawable-xxhdpi/inverse.png b/orbotmanager/src/main/res/drawable-xxhdpi/inverse.png new file mode 100644 index 00000000..71e1adc5 Binary files /dev/null and b/orbotmanager/src/main/res/drawable-xxhdpi/inverse.png differ diff --git a/orbotmanager/src/main/res/drawable-xxxhdpi/ic_autorenew_black_36dp.png b/orbotmanager/src/main/res/drawable-xxxhdpi/ic_autorenew_black_36dp.png new file mode 100644 index 00000000..9c9a1f66 Binary files /dev/null and b/orbotmanager/src/main/res/drawable-xxxhdpi/ic_autorenew_black_36dp.png differ diff --git a/orbotmanager/src/main/res/drawable-xxxhdpi/ic_filter_none_black_36dp.png b/orbotmanager/src/main/res/drawable-xxxhdpi/ic_filter_none_black_36dp.png new file mode 100644 index 00000000..963e1951 Binary files /dev/null and b/orbotmanager/src/main/res/drawable-xxxhdpi/ic_filter_none_black_36dp.png differ diff --git a/orbotmanager/src/main/res/drawable-xxxhdpi/ic_launcher.png b/orbotmanager/src/main/res/drawable-xxxhdpi/ic_launcher.png new file mode 100644 index 00000000..6ae04dbf Binary files /dev/null and b/orbotmanager/src/main/res/drawable-xxxhdpi/ic_launcher.png differ diff --git a/orbotmanager/src/main/res/drawable-xxxhdpi/ic_playlist_add_check_black_36dp.png b/orbotmanager/src/main/res/drawable-xxxhdpi/ic_playlist_add_check_black_36dp.png new file mode 100644 index 00000000..9a544026 Binary files /dev/null and b/orbotmanager/src/main/res/drawable-xxxhdpi/ic_playlist_add_check_black_36dp.png differ diff --git a/orbotmanager/src/main/res/drawable-xxxhdpi/ic_refresh_white_24dp.png b/orbotmanager/src/main/res/drawable-xxxhdpi/ic_refresh_white_24dp.png new file mode 100644 index 00000000..a9db32db Binary files /dev/null and b/orbotmanager/src/main/res/drawable-xxxhdpi/ic_refresh_white_24dp.png differ diff --git a/orbotmanager/src/main/res/drawable-xxxhdpi/ic_stat_tor_xfer.png b/orbotmanager/src/main/res/drawable-xxxhdpi/ic_stat_tor_xfer.png new file mode 100644 index 00000000..82bb917c Binary files /dev/null and b/orbotmanager/src/main/res/drawable-xxxhdpi/ic_stat_tor_xfer.png differ diff --git a/orbotmanager/src/main/res/drawable-xxxhdpi/inverse.png b/orbotmanager/src/main/res/drawable-xxxhdpi/inverse.png new file mode 100644 index 00000000..71e1adc5 Binary files /dev/null and b/orbotmanager/src/main/res/drawable-xxxhdpi/inverse.png differ diff --git a/orbotmanager/src/test/java/org/torproject/android/control/.cvsignore b/orbotmanager/src/test/java/org/torproject/android/control/.cvsignore deleted file mode 100644 index 6b468b62..00000000 --- a/orbotmanager/src/test/java/org/torproject/android/control/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -*.class diff --git a/orbotmanager/src/test/java/org/torproject/android/control/Bytes.java b/orbotmanager/src/test/java/org/torproject/android/control/Bytes.java deleted file mode 100644 index e754d907..00000000 --- a/orbotmanager/src/test/java/org/torproject/android/control/Bytes.java +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2005 Nick Mathewson, Roger Dingledine -// See LICENSE file for copying information -package org.torproject.android.control; - -import java.util.Arrays; -import java.util.List; - -/** - * Static class to do bytewise structure manipulation in Java. - */ -/* XXXX There must be a better way to do most of this. - * XXXX The string logic here uses default encoding, which is stupid. - */ -final class Bytes { - - /** Write the two-byte value in 's' into the byte array 'ba', starting at - * the index 'pos'. */ - public static void setU16(byte[] ba, int pos, short s) { - ba[pos] = (byte)((s >> 8) & 0xff); - ba[pos+1] = (byte)((s ) & 0xff); - } - - /** Write the four-byte value in 'i' into the byte array 'ba', starting at - * the index 'pos'. */ - public static void setU32(byte[] ba, int pos, int i) { - ba[pos] = (byte)((i >> 24) & 0xff); - ba[pos+1] = (byte)((i >> 16) & 0xff); - ba[pos+2] = (byte)((i >> 8) & 0xff); - ba[pos+3] = (byte)((i ) & 0xff); - } - - /** Return the four-byte value starting at index 'pos' within 'ba' */ - public static int getU32(byte[] ba, int pos) { - return - ((ba[pos ]&0xff)<<24) | - ((ba[pos+1]&0xff)<<16) | - ((ba[pos+2]&0xff)<< 8) | - ((ba[pos+3]&0xff)); - } - - public static String getU32S(byte[] ba, int pos) { - return String.valueOf( (getU32(ba,pos))&0xffffffffL ); - } - - /** Return the two-byte value starting at index 'pos' within 'ba' */ - public static int getU16(byte[] ba, int pos) { - return - ((ba[pos ]&0xff)<<8) | - ((ba[pos+1]&0xff)); - } - - /** Return the string starting at position 'pos' of ba and extending - * until a zero byte or the end of the string. */ - public static String getNulTerminatedStr(byte[] ba, int pos) { - int len, maxlen = ba.length-pos; - for (len=0; len lst, byte[] ba, int pos, byte split) { - while (pos < ba.length && ba[pos] != 0) { - int len; - for (len=0; pos+len < ba.length; ++len) { - if (ba[pos+len] == 0 || ba[pos+len] == split) - break; - } - if (len>0) - lst.add(new String(ba, pos, len)); - pos += len; - if (ba[pos] == split) - ++pos; - } - } - - /** - * Read bytes from 'ba' starting at 'pos', dividing them into strings - * along the character in 'split' and writing them into 'lst' - */ - public static List splitStr(List lst, String str) { - // split string on spaces, include trailing/leading - String[] tokenArray = str.split(" ", -1); - if (lst == null) { - lst = Arrays.asList( tokenArray ); - } else { - lst.addAll( Arrays.asList( tokenArray ) ); - } - return lst; - } - - private static final char[] NYBBLES = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' - }; - - public static final String hex(byte[] ba) { - StringBuffer buf = new StringBuffer(); - for (int i = 0; i < ba.length; ++i) { - int b = (ba[i]) & 0xff; - buf.append(NYBBLES[b >> 4]); - buf.append(NYBBLES[b&0x0f]); - } - return buf.toString(); - } - - private Bytes() {}; -} - diff --git a/orbotmanager/src/test/java/org/torproject/android/control/ConfigEntry.java b/orbotmanager/src/test/java/org/torproject/android/control/ConfigEntry.java deleted file mode 100644 index 31eb4b8e..00000000 --- a/orbotmanager/src/test/java/org/torproject/android/control/ConfigEntry.java +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2005 Nick Mathewson, Roger Dingledine -// See LICENSE file for copying information -package org.torproject.android.control; - -/** A single key-value pair from Tor's configuration. */ -public class ConfigEntry { - public ConfigEntry(String k, String v) { - key = k; - value = v; - is_default = false; - } - public ConfigEntry(String k) { - key = k; - value = ""; - is_default = true; - } - public final String key; - public final String value; - public final boolean is_default; -} diff --git a/orbotmanager/src/test/java/org/torproject/android/control/EventHandler.java b/orbotmanager/src/test/java/org/torproject/android/control/EventHandler.java deleted file mode 100644 index 5a4e2b5b..00000000 --- a/orbotmanager/src/test/java/org/torproject/android/control/EventHandler.java +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2005 Nick Mathewson, Roger Dingledine -// See LICENSE file for copying information -package org.torproject.android.control; - -/** - * Abstract interface whose methods are invoked when Tor sends us an event. - * - * @see TorControlConnection#setEventHandler - * @see TorControlConnection#setEvents - */ -public interface EventHandler { - /** - * Invoked when a circuit's status has changed. - * Possible values for status are: - *
    - *
  • "LAUNCHED" : circuit ID assigned to new circuit
  • - *
  • "BUILT" : all hops finished, can now accept streams
  • - *
  • "EXTENDED" : one more hop has been completed
  • - *
  • "FAILED" : circuit closed (was not built)
  • - *
  • "CLOSED" : circuit closed (was built)
  • - *
- * - * circID is the alphanumeric identifier of the affected circuit, - * and path is a comma-separated list of alphanumeric ServerIDs. - */ - public void circuitStatus(String status, String circID, String path); - /** - * Invoked when a stream's status has changed. - * Possible values for status are: - *
    - *
  • "NEW" : New request to connect
  • - *
  • "NEWRESOLVE" : New request to resolve an address
  • - *
  • "SENTCONNECT" : Sent a connect cell along a circuit
  • - *
  • "SENTRESOLVE" : Sent a resolve cell along a circuit
  • - *
  • "SUCCEEDED" : Received a reply; stream established
  • - *
  • "FAILED" : Stream failed and not retriable.
  • - *
  • "CLOSED" : Stream closed
  • - *
  • "DETACHED" : Detached from circuit; still retriable.
  • - *
- * - * streamID is the alphanumeric identifier of the affected stream, - * and its target is specified as address:port. - */ - public void streamStatus(String status, String streamID, String target); - /** - * Invoked when the status of a connection to an OR has changed. - * Possible values for status are ["LAUNCHED" | "CONNECTED" | "FAILED" | "CLOSED"]. - * orName is the alphanumeric identifier of the OR affected. - */ - public void orConnStatus(String status, String orName); - /** - * Invoked once per second. read and written are - * the number of bytes read and written, respectively, in - * the last second. - */ - public void bandwidthUsed(long read, long written); - /** - * Invoked whenever Tor learns about new ORs. The orList object - * contains the alphanumeric ServerIDs associated with the new ORs. - */ - public void newDescriptors(java.util.List orList); - /** - * Invoked when Tor logs a message. - * severity is one of ["DEBUG" | "INFO" | "NOTICE" | "WARN" | "ERR"], - * and msg is the message string. - */ - public void message(String severity, String msg); - /** - * Invoked when an unspecified message is received. - * is the message type, and is the message string. - */ - public void unrecognized(String type, String msg); - -} - diff --git a/orbotmanager/src/test/java/org/torproject/android/control/PasswordDigest.java b/orbotmanager/src/test/java/org/torproject/android/control/PasswordDigest.java deleted file mode 100644 index 03d0a98e..00000000 --- a/orbotmanager/src/test/java/org/torproject/android/control/PasswordDigest.java +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2005 Nick Mathewson, Roger Dingledine -// See LICENSE file for copying information -package org.torproject.android.control; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; - -/** - * A hashed digest of a secret password (used to set control connection - * security.) - * - * For the actual hashing algorithm, see RFC2440's secret-to-key conversion. - */ -public class PasswordDigest { - - private final byte[] secret; - private final String hashedKey; - - /** Return a new password digest with a random secret and salt. */ - public static PasswordDigest generateDigest() { - byte[] secret = new byte[20]; - SecureRandom rng = new SecureRandom(); - rng.nextBytes(secret); - return new PasswordDigest(secret); - } - - /** Construct a new password digest with a given secret and random salt */ - public PasswordDigest(byte[] secret) { - this(secret, null); - } - - /** Construct a new password digest with a given secret and random salt. - * Note that the 9th byte of the specifier determines the number of hash - * iterations as in RFC2440. - */ - public PasswordDigest(byte[] secret, byte[] specifier) { - this.secret = secret.clone(); - if (specifier == null) { - specifier = new byte[9]; - SecureRandom rng = new SecureRandom(); - rng.nextBytes(specifier); - specifier[8] = 96; - } - hashedKey = "16:"+encodeBytes(secretToKey(secret, specifier)); - } - - /** Return the secret used to generate this password hash. - */ - public byte[] getSecret() { - return secret.clone(); - } - - /** Return the hashed password in the format used by Tor. */ - public String getHashedPassword() { - return hashedKey; - } - - /** Parameter used by RFC2440's s2k algorithm. */ - private static final int EXPBIAS = 6; - - /** Implement rfc2440 s2k */ - public static byte[] secretToKey(byte[] secret, byte[] specifier) { - MessageDigest d; - try { - d = MessageDigest.getInstance("SHA-1"); - } catch (NoSuchAlgorithmException ex) { - throw new RuntimeException("Can't run without sha-1."); - } - int c = (specifier[8])&0xff; - int count = (16 + (c&15)) << ((c>>4) + EXPBIAS); - - byte[] tmp = new byte[8+secret.length]; - System.arraycopy(specifier, 0, tmp, 0, 8); - System.arraycopy(secret, 0, tmp, 8, secret.length); - while (count > 0) { - if (count >= tmp.length) { - d.update(tmp); - count -= tmp.length; - } else { - d.update(tmp, 0, count); - count = 0; - } - } - byte[] key = new byte[20+9]; - System.arraycopy(d.digest(), 0, key, 9, 20); - System.arraycopy(specifier, 0, key, 0, 9); - return key; - } - - /** Return a hexadecimal encoding of a byte array. */ - // XXX There must be a better way to do this in Java. - private static final String encodeBytes(byte[] ba) { - return Bytes.hex(ba); - } - -} - diff --git a/orbotmanager/src/test/java/org/torproject/android/control/README b/orbotmanager/src/test/java/org/torproject/android/control/README deleted file mode 100644 index b310c7d5..00000000 --- a/orbotmanager/src/test/java/org/torproject/android/control/README +++ /dev/null @@ -1,4 +0,0 @@ -We broke the version detection stuff in Tor 0.1.2.16 / 0.2.0.4-alpha. -Somebody should rip out the v0 control protocol stuff from here, and -it should start working again. -RD - diff --git a/orbotmanager/src/test/java/org/torproject/android/control/TorControlCommands.java b/orbotmanager/src/test/java/org/torproject/android/control/TorControlCommands.java deleted file mode 100644 index c98a1c48..00000000 --- a/orbotmanager/src/test/java/org/torproject/android/control/TorControlCommands.java +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright 2005 Nick Mathewson, Roger Dingledine -// See LICENSE file for copying information -package org.torproject.android.control; - -/** Interface defining constants used by the Tor controller protocol. - */ -// XXXX Take documentation for these from control-spec.txt -public interface TorControlCommands { - - public static final short CMD_ERROR = 0x0000; - public static final short CMD_DONE = 0x0001; - public static final short CMD_SETCONF = 0x0002; - public static final short CMD_GETCONF = 0x0003; - public static final short CMD_CONFVALUE = 0x0004; - public static final short CMD_SETEVENTS = 0x0005; - public static final short CMD_EVENT = 0x0006; - public static final short CMD_AUTH = 0x0007; - public static final short CMD_SAVECONF = 0x0008; - public static final short CMD_SIGNAL = 0x0009; - public static final short CMD_MAPADDRESS = 0x000A; - public static final short CMD_GETINFO = 0x000B; - public static final short CMD_INFOVALUE = 0x000C; - public static final short CMD_EXTENDCIRCUIT = 0x000D; - public static final short CMD_ATTACHSTREAM = 0x000E; - public static final short CMD_POSTDESCRIPTOR = 0x000F; - public static final short CMD_FRAGMENTHEADER = 0x0010; - public static final short CMD_FRAGMENT = 0x0011; - public static final short CMD_REDIRECTSTREAM = 0x0012; - public static final short CMD_CLOSESTREAM = 0x0013; - public static final short CMD_CLOSECIRCUIT = 0x0014; - - public static final String[] CMD_NAMES = { - "ERROR", - "DONE", - "SETCONF", - "GETCONF", - "CONFVALUE", - "SETEVENTS", - "EVENT", - "AUTH", - "SAVECONF", - "SIGNAL", - "MAPADDRESS", - "GETINFO", - "INFOVALUE", - "EXTENDCIRCUIT", - "ATTACHSTREAM", - "POSTDESCRIPTOR", - "FRAGMENTHEADER", - "FRAGMENT", - "REDIRECTSTREAM", - "CLOSESTREAM", - "CLOSECIRCUIT", - }; - - public static final short EVENT_CIRCSTATUS = 0x0001; - public static final short EVENT_STREAMSTATUS = 0x0002; - public static final short EVENT_ORCONNSTATUS = 0x0003; - public static final short EVENT_BANDWIDTH = 0x0004; - public static final short EVENT_NEWDESCRIPTOR = 0x0006; - public static final short EVENT_MSG_DEBUG = 0x0007; - public static final short EVENT_MSG_INFO = 0x0008; - public static final short EVENT_MSG_NOTICE = 0x0009; - public static final short EVENT_MSG_WARN = 0x000A; - public static final short EVENT_MSG_ERROR = 0x000B; - - public static final String[] EVENT_NAMES = { - "(0)", - "CIRC", - "STREAM", - "ORCONN", - "BW", - "OLDLOG", - "NEWDESC", - "DEBUG", - "INFO", - "NOTICE", - "WARN", - "ERR", - }; - - public static final byte CIRC_STATUS_LAUNCHED = 0x01; - public static final byte CIRC_STATUS_BUILT = 0x02; - public static final byte CIRC_STATUS_EXTENDED = 0x03; - public static final byte CIRC_STATUS_FAILED = 0x04; - public static final byte CIRC_STATUS_CLOSED = 0x05; - - public static final String[] CIRC_STATUS_NAMES = { - "LAUNCHED", - "BUILT", - "EXTENDED", - "FAILED", - "CLOSED", - }; - - public static final byte STREAM_STATUS_SENT_CONNECT = 0x00; - public static final byte STREAM_STATUS_SENT_RESOLVE = 0x01; - public static final byte STREAM_STATUS_SUCCEEDED = 0x02; - public static final byte STREAM_STATUS_FAILED = 0x03; - public static final byte STREAM_STATUS_CLOSED = 0x04; - public static final byte STREAM_STATUS_NEW_CONNECT = 0x05; - public static final byte STREAM_STATUS_NEW_RESOLVE = 0x06; - public static final byte STREAM_STATUS_DETACHED = 0x07; - - public static final String[] STREAM_STATUS_NAMES = { - "SENT_CONNECT", - "SENT_RESOLVE", - "SUCCEEDED", - "FAILED", - "CLOSED", - "NEW_CONNECT", - "NEW_RESOLVE", - "DETACHED" - }; - - public static final byte OR_CONN_STATUS_LAUNCHED = 0x00; - public static final byte OR_CONN_STATUS_CONNECTED = 0x01; - public static final byte OR_CONN_STATUS_FAILED = 0x02; - public static final byte OR_CONN_STATUS_CLOSED = 0x03; - - public static final String[] OR_CONN_STATUS_NAMES = { - "LAUNCHED","CONNECTED","FAILED","CLOSED" - }; - - public static final byte SIGNAL_HUP = 0x01; - public static final byte SIGNAL_INT = 0x02; - public static final byte SIGNAL_USR1 = 0x0A; - public static final byte SIGNAL_USR2 = 0x0C; - public static final byte SIGNAL_TERM = 0x0F; - - public static final String ERROR_MSGS[] = { - "Unspecified error", - "Internal error", - "Unrecognized message type", - "Syntax error", - "Unrecognized configuration key", - "Invalid configuration value", - "Unrecognized byte code", - "Unauthorized", - "Failed authentication attempt", - "Resource exhausted", - "No such stream", - "No such circuit", - "No such OR", - }; - -} - diff --git a/orbotmanager/src/test/java/org/torproject/android/control/TorControlConnection.java b/orbotmanager/src/test/java/org/torproject/android/control/TorControlConnection.java deleted file mode 100644 index 204dbc06..00000000 --- a/orbotmanager/src/test/java/org/torproject/android/control/TorControlConnection.java +++ /dev/null @@ -1,730 +0,0 @@ -// Copyright 2005 Nick Mathewson, Roger Dingledine -// See LICENSE file for copying information -package org.torproject.android.control; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.PrintStream; -import java.io.PrintWriter; -import java.io.Reader; -import java.io.Writer; -import java.net.Socket; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.StringTokenizer; - -/** A connection to a running Tor process as specified in control-spec.txt. */ -public class TorControlConnection implements TorControlCommands { - - private final LinkedList waiters; - private final BufferedReader input; - private final Writer output; - - private ControlParseThread thread; // Locking: this - - private volatile EventHandler handler; - private volatile PrintWriter debugOutput; - private volatile IOException parseThreadException; - - static class Waiter { - - List response; // Locking: this - - synchronized List getResponse() throws InterruptedException { - while (response == null) { - wait(); - } - return response; - } - - synchronized void setResponse(List response) { - this.response = response; - notifyAll(); - } - } - - static class ReplyLine { - - final String status; - final String msg; - final String rest; - - ReplyLine(String status, String msg, String rest) { - this.status = status; this.msg = msg; this.rest = rest; - } - } - - /** Create a new TorControlConnection to communicate with Tor over - * a given socket. After calling this constructor, it is typical to - * call launchThread and authenticate. */ - public TorControlConnection(Socket connection) throws IOException { - this(connection.getInputStream(), connection.getOutputStream()); - } - - /** Create a new TorControlConnection to communicate with Tor over - * an arbitrary pair of data streams. - */ - public TorControlConnection(InputStream i, OutputStream o) { - this(new InputStreamReader(i), new OutputStreamWriter(o)); - } - - public TorControlConnection(Reader i, Writer o) { - this.output = o; - if (i instanceof BufferedReader) - this.input = (BufferedReader) i; - else - this.input = new BufferedReader(i); - this.waiters = new LinkedList(); - } - - protected final void writeEscaped(String s) throws IOException { - StringTokenizer st = new StringTokenizer(s, "\n"); - while (st.hasMoreTokens()) { - String line = st.nextToken(); - if (line.startsWith(".")) - line = "."+line; - if (line.endsWith("\r")) - line += "\n"; - else - line += "\r\n"; - if (debugOutput != null) - debugOutput.print(">> "+line); - output.write(line); - } - output.write(".\r\n"); - if (debugOutput != null) - debugOutput.print(">> .\n"); - } - - protected static final String quote(String s) { - StringBuffer sb = new StringBuffer("\""); - for (int i = 0; i < s.length(); ++i) { - char c = s.charAt(i); - switch (c) - { - case '\r': - case '\n': - case '\\': - case '\"': - sb.append('\\'); - } - sb.append(c); - } - sb.append('\"'); - return sb.toString(); - } - - protected final ArrayList readReply() throws IOException { - ArrayList reply = new ArrayList(); - char c; - do { - String line = input.readLine(); - if (line == null) { - // if line is null, the end of the stream has been reached, i.e. - // the connection to Tor has been closed! - if (reply.isEmpty()) { - // nothing received so far, can exit cleanly - return reply; - } - // received half of a reply before the connection broke down - throw new TorControlSyntaxError("Connection to Tor " + - " broke down while receiving reply!"); - } - if (debugOutput != null) - debugOutput.println("<< "+line); - if (line.length() < 4) - throw new TorControlSyntaxError("Line (\""+line+"\") too short"); - String status = line.substring(0,3); - c = line.charAt(3); - String msg = line.substring(4); - String rest = null; - if (c == '+') { - StringBuffer data = new StringBuffer(); - while (true) { - line = input.readLine(); - if (debugOutput != null) - debugOutput.print("<< "+line); - if (line.equals(".")) - break; - else if (line.startsWith(".")) - line = line.substring(1); - data.append(line).append('\n'); - } - rest = data.toString(); - } - reply.add(new ReplyLine(status, msg, rest)); - } while (c != ' '); - - return reply; - } - - protected synchronized List sendAndWaitForResponse(String s, - String rest) throws IOException { - if(parseThreadException != null) throw parseThreadException; - checkThread(); - Waiter w = new Waiter(); - if (debugOutput != null) - debugOutput.print(">> "+s); - synchronized (waiters) { - output.write(s); - if (rest != null) - writeEscaped(rest); - output.flush(); - waiters.addLast(w); - } - List lst; - try { - lst = w.getResponse(); - } catch (InterruptedException ex) { - throw new IOException("Interrupted"); - } - for (Iterator i = lst.iterator(); i.hasNext(); ) { - ReplyLine c = i.next(); - if (! c.status.startsWith("2")) - throw new TorControlError("Error reply: "+c.msg); - } - return lst; - } - - /** Helper: decode a CMD_EVENT command and dispatch it to our - * EventHandler (if any). */ - protected void handleEvent(ArrayList events) { - if (handler == null) - return; - - for (Iterator i = events.iterator(); i.hasNext(); ) { - ReplyLine line = i.next(); - int idx = line.msg.indexOf(' '); - String tp = line.msg.substring(0, idx).toUpperCase(); - String rest = line.msg.substring(idx+1); - if (tp.equals("CIRC")) { - List lst = Bytes.splitStr(null, rest); - handler.circuitStatus(lst.get(1), - lst.get(0), - lst.get(1).equals("LAUNCHED") - || lst.size() < 3 ? "" - : lst.get(2)); - } else if (tp.equals("STREAM")) { - List lst = Bytes.splitStr(null, rest); - handler.streamStatus(lst.get(1), - lst.get(0), - lst.get(3)); - // XXXX circID. - } else if (tp.equals("ORCONN")) { - List lst = Bytes.splitStr(null, rest); - handler.orConnStatus(lst.get(1), lst.get(0)); - } else if (tp.equals("BW")) { - List lst = Bytes.splitStr(null, rest); - handler.bandwidthUsed(Integer.parseInt(lst.get(0)), - Integer.parseInt(lst.get(1))); - } else if (tp.equals("NEWDESC")) { - List lst = Bytes.splitStr(null, rest); - handler.newDescriptors(lst); - } else if (tp.equals("DEBUG") || - tp.equals("INFO") || - tp.equals("NOTICE") || - tp.equals("WARN") || - tp.equals("ERR")) { - handler.message(tp, rest); - } else { - handler.unrecognized(tp, rest); - } - } - } - - - /** Sets w as the PrintWriter for debugging output, - * which writes out all messages passed between Tor and the controller. - * Outgoing messages are preceded by "\>\>" and incoming messages are preceded - * by "\<\<" - */ - public void setDebugging(PrintWriter w) { - debugOutput = w; - } - - /** Sets s as the PrintStream for debugging output, - * which writes out all messages passed between Tor and the controller. - * Outgoing messages are preceded by "\>\>" and incoming messages are preceded - * by "\<\<" - */ - public void setDebugging(PrintStream s) { - debugOutput = new PrintWriter(s, true); - } - - /** Set the EventHandler object that will be notified of any - * events Tor delivers to this connection. To make Tor send us - * events, call setEvents(). */ - public void setEventHandler(EventHandler handler) { - this.handler = handler; - } - - /** - * Start a thread to react to Tor's responses in the background. - * This is necessary to handle asynchronous events and synchronous - * responses that arrive independantly over the same socket. - */ - public synchronized Thread launchThread(boolean daemon) { - ControlParseThread th = new ControlParseThread(); - if (daemon) - th.setDaemon(true); - th.start(); - this.thread = th; - return th; - } - - protected class ControlParseThread extends Thread { - - @Override - public void run() { - try { - react(); - } catch (IOException ex) { - parseThreadException = ex; - } - } - } - - protected synchronized void checkThread() { - if (thread == null) - launchThread(true); - } - - /** helper: implement the main background loop. */ - protected void react() throws IOException { - while (true) { - ArrayList lst = readReply(); - if (lst.isEmpty()) { - // connection has been closed remotely! end the loop! - return; - } - if ((lst.get(0)).status.startsWith("6")) - handleEvent(lst); - else { - synchronized (waiters) { - if (!waiters.isEmpty()) - { - Waiter w; - w = waiters.removeFirst(); - w.setResponse(lst); - } - } - - } - } - } - - /** Change the value of the configuration option 'key' to 'val'. - */ - public void setConf(String key, String value) throws IOException { - List lst = new ArrayList(); - lst.add(key+" "+value); - setConf(lst); - } - - /** Change the values of the configuration options stored in kvMap. */ - public void setConf(Map kvMap) throws IOException { - List lst = new ArrayList(); - for (Iterator> it = kvMap.entrySet().iterator(); it.hasNext(); ) { - Map.Entry ent = it.next(); - lst.add(ent.getKey()+" "+ent.getValue()+"\n"); - } - setConf(lst); - } - - /** Changes the values of the configuration options stored in - * kvList. Each list element in kvList is expected to be - * String of the format "key value". - * - * Tor behaves as though it had just read each of the key-value pairs - * from its configuration file. Keywords with no corresponding values have - * their configuration values reset to their defaults. setConf is - * all-or-nothing: if there is an error in any of the configuration settings, - * Tor sets none of them. - * - * When a configuration option takes multiple values, or when multiple - * configuration keys form a context-sensitive group (see getConf below), then - * setting any of the options in a setConf command is taken to reset all of - * the others. For example, if two ORBindAddress values are configured, and a - * command arrives containing a single ORBindAddress value, the new - * command's value replaces the two old values. - * - * To remove all settings for a given option entirely (and go back to its - * default value), include a String in kvList containing the key and no value. - */ - public void setConf(Collection kvList) throws IOException { - if (kvList.size() == 0) - return; - StringBuffer b = new StringBuffer("SETCONF"); - for (Iterator it = kvList.iterator(); it.hasNext(); ) { - String kv = it.next(); - int i = kv.indexOf(' '); - if (i == -1) - b.append(" ").append(kv); - b.append(" ").append(kv.substring(0,i)).append("=") - .append(quote(kv.substring(i+1))); - } - b.append("\r\n"); - sendAndWaitForResponse(b.toString(), null); - } - - /** Try to reset the values listed in the collection 'keys' to their - * default values. - **/ - public void resetConf(Collection keys) throws IOException { - if (keys.size() == 0) - return; - StringBuffer b = new StringBuffer("RESETCONF"); - for (Iterator it = keys.iterator(); it.hasNext(); ) { - String key = it.next(); - b.append(" ").append(key); - } - b.append("\r\n"); - sendAndWaitForResponse(b.toString(), null); - } - - /** Return the value of the configuration option 'key' */ - public List getConf(String key) throws IOException { - List lst = new ArrayList(); - lst.add(key); - return getConf(lst); - } - - /** Requests the values of the configuration variables listed in keys. - * Results are returned as a list of ConfigEntry objects. - * - * If an option appears multiple times in the configuration, all of its - * key-value pairs are returned in order. - * - * Some options are context-sensitive, and depend on other options with - * different keywords. These cannot be fetched directly. Currently there - * is only one such option: clients should use the "HiddenServiceOptions" - * virtual keyword to get all HiddenServiceDir, HiddenServicePort, - * HiddenServiceNodes, and HiddenServiceExcludeNodes option settings. - */ - public List getConf(Collection keys) throws IOException { - StringBuffer sb = new StringBuffer("GETCONF"); - for (Iterator it = keys.iterator(); it.hasNext(); ) { - String key = it.next(); - sb.append(" ").append(key); - } - sb.append("\r\n"); - List lst = sendAndWaitForResponse(sb.toString(), null); - List result = new ArrayList(); - for (Iterator it = lst.iterator(); it.hasNext(); ) { - String kv = (it.next()).msg; - int idx = kv.indexOf('='); - if (idx >= 0) - result.add(new ConfigEntry(kv.substring(0, idx), - kv.substring(idx+1))); - else - result.add(new ConfigEntry(kv)); - } - return result; - } - - /** Request that the server inform the client about interesting events. - * Each element of events is one of the following Strings: - * ["CIRC" | "STREAM" | "ORCONN" | "BW" | "DEBUG" | - * "INFO" | "NOTICE" | "WARN" | "ERR" | "NEWDESC" | "ADDRMAP"] . - * - * Any events not listed in the events are turned off; thus, calling - * setEvents with an empty events argument turns off all event reporting. - */ - public void setEvents(List events) throws IOException { - StringBuffer sb = new StringBuffer("SETEVENTS"); - for (Iterator it = events.iterator(); it.hasNext(); ) { - sb.append(" ").append(it.next()); - } - sb.append("\r\n"); - sendAndWaitForResponse(sb.toString(), null); - } - - /** Authenticates the controller to the Tor server. - * - * By default, the current Tor implementation trusts all local users, and - * the controller can authenticate itself by calling authenticate(new byte[0]). - * - * If the 'CookieAuthentication' option is true, Tor writes a "magic cookie" - * file named "control_auth_cookie" into its data directory. To authenticate, - * the controller must send the contents of this file in auth. - * - * If the 'HashedControlPassword' option is set, auth must contain the salted - * hash of a secret password. The salted hash is computed according to the - * S2K algorithm in RFC 2440 (OpenPGP), and prefixed with the s2k specifier. - * This is then encoded in hexadecimal, prefixed by the indicator sequence - * "16:". - * - * You can generate the salt of a password by calling - * 'tor --hash-password ' - * or by using the provided PasswordDigest class. - * To authenticate under this scheme, the controller sends Tor the original - * secret that was used to generate the password. - */ - public void authenticate(byte[] auth) throws IOException { - String cmd = "AUTHENTICATE " + Bytes.hex(auth) + "\r\n"; - sendAndWaitForResponse(cmd, null); - } - - /** Instructs the server to write out its configuration options into its torrc. - */ - public void saveConf() throws IOException { - sendAndWaitForResponse("SAVECONF\r\n", null); - } - - /** Sends a signal from the controller to the Tor server. - * signal is one of the following Strings: - *
    - *
  • "RELOAD" or "HUP" : Reload config items, refetch directory
  • - *
  • "SHUTDOWN" or "INT" : Controlled shutdown: if server is an OP, exit immediately. - * If it's an OR, close listeners and exit after 30 seconds
  • - *
  • "DUMP" or "USR1" : Dump stats: log information about open connections and circuits
  • - *
  • "DEBUG" or "USR2" : Debug: switch all open logs to loglevel debug
  • - *
  • "HALT" or "TERM" : Immediate shutdown: clean up and exit now
  • - *
- */ - public void signal(String signal) throws IOException { - String cmd = "SIGNAL " + signal + "\r\n"; - sendAndWaitForResponse(cmd, null); - } - - /** Send a signal to the Tor process to shut it down or halt it. - * Does not wait for a response. */ - public void shutdownTor(String signal) throws IOException { - String s = "SIGNAL " + signal + "\r\n"; - Waiter w = new Waiter(); - if (debugOutput != null) - debugOutput.print(">> "+s); - synchronized (waiters) { - output.write(s); - output.flush(); - } - } - - /** Tells the Tor server that future SOCKS requests for connections to a set of original - * addresses should be replaced with connections to the specified replacement - * addresses. Each element of kvLines is a String of the form - * "old-address new-address". This function returns the new address mapping. - * - * The client may decline to provide a body for the original address, and - * instead send a special null address ("0.0.0.0" for IPv4, "::0" for IPv6, or - * "." for hostname), signifying that the server should choose the original - * address itself, and return that address in the reply. The server - * should ensure that it returns an element of address space that is unlikely - * to be in actual use. If there is already an address mapped to the - * destination address, the server may reuse that mapping. - * - * If the original address is already mapped to a different address, the old - * mapping is removed. If the original address and the destination address - * are the same, the server removes any mapping in place for the original - * address. - * - * Mappings set by the controller last until the Tor process exits: - * they never expire. If the controller wants the mapping to last only - * a certain time, then it must explicitly un-map the address when that - * time has elapsed. - */ - public Map mapAddresses(Collection kvLines) throws IOException { - StringBuffer sb = new StringBuffer("MAPADDRESS"); - for (Iterator it = kvLines.iterator(); it.hasNext(); ) { - String kv = it.next(); - int i = kv.indexOf(' '); - sb.append(" ").append(kv.substring(0,i)).append("=") - .append(quote(kv.substring(i+1))); - } - sb.append("\r\n"); - List lst = sendAndWaitForResponse(sb.toString(), null); - Map result = new HashMap(); - for (Iterator it = lst.iterator(); it.hasNext(); ) { - String kv = (it.next()).msg; - int idx = kv.indexOf('='); - result.put(kv.substring(0, idx), - kv.substring(idx+1)); - } - return result; - } - - public Map mapAddresses(Map addresses) throws IOException { - List kvList = new ArrayList(); - for (Iterator> it = addresses.entrySet().iterator(); it.hasNext(); ) { - Map.Entry e = it.next(); - kvList.add(e.getKey()+" "+e.getValue()); - } - return mapAddresses(kvList); - } - - public String mapAddress(String fromAddr, String toAddr) throws IOException { - List lst = new ArrayList(); - lst.add(fromAddr+" "+toAddr+"\n"); - Map m = mapAddresses(lst); - return m.get(fromAddr); - } - - /** Queries the Tor server for keyed values that are not stored in the torrc - * configuration file. Returns a map of keys to values. - * - * Recognized keys include: - *
    - *
  • "version" : The version of the server's software, including the name - * of the software. (example: "Tor 0.0.9.4")
  • - *
  • "desc/id/" or "desc/name/" : the latest server - * descriptor for a given OR, NUL-terminated. If no such OR is known, the - * corresponding value is an empty string.
  • - *
  • "network-status" : a space-separated list of all known OR identities. - * This is in the same format as the router-status line in directories; - * see tor-spec.txt for details.
  • - *
  • "addr-mappings/all"
  • - *
  • "addr-mappings/config"
  • - *
  • "addr-mappings/cache"
  • - *
  • "addr-mappings/control" : a space-separated list of address mappings, each - * in the form of "from-address=to-address". The 'config' key - * returns those address mappings set in the configuration; the 'cache' - * key returns the mappings in the client-side DNS cache; the 'control' - * key returns the mappings set via the control interface; the 'all' - * target returns the mappings set through any mechanism.
  • - *
  • "circuit-status" : A series of lines as for a circuit status event. Each line is of the form: - * "CircuitID CircStatus Path"
  • - *
  • "stream-status" : A series of lines as for a stream status event. Each is of the form: - * "StreamID StreamStatus CircID Target"
  • - *
  • "orconn-status" : A series of lines as for an OR connection status event. Each is of the - * form: "ServerID ORStatus"
  • - *
- */ - public Map getInfo(Collection keys) throws IOException { - StringBuffer sb = new StringBuffer("GETINFO"); - for (Iterator it = keys.iterator(); it.hasNext(); ) { - sb.append(" ").append(it.next()); - } - sb.append("\r\n"); - List lst = sendAndWaitForResponse(sb.toString(), null); - Map m = new HashMap(); - for (Iterator it = lst.iterator(); it.hasNext(); ) { - ReplyLine line = it.next(); - int idx = line.msg.indexOf('='); - if (idx<0) - break; - String k = line.msg.substring(0,idx); - String v; - if (line.rest != null) { - v = line.rest; - } else { - v = line.msg.substring(idx+1); - } - m.put(k, v); - } - return m; - } - - - - /** Return the value of the information field 'key' */ - public String getInfo(String key) throws IOException { - List lst = new ArrayList(); - lst.add(key); - Map m = getInfo(lst); - return m.get(key); - } - - /** An extendCircuit request takes one of two forms: either the circID is zero, in - * which case it is a request for the server to build a new circuit according - * to the specified path, or the circID is nonzero, in which case it is a - * request for the server to extend an existing circuit with that ID according - * to the specified path. - * - * If successful, returns the Circuit ID of the (maybe newly created) circuit. - */ - public String extendCircuit(String circID, String path) throws IOException { - List lst = sendAndWaitForResponse( - "EXTENDCIRCUIT "+circID+" "+path+"\r\n", null); - return (lst.get(0)).msg; - } - - /** Informs the Tor server that the stream specified by streamID should be - * associated with the circuit specified by circID. - * - * Each stream may be associated with - * at most one circuit, and multiple streams may share the same circuit. - * Streams can only be attached to completed circuits (that is, circuits that - * have sent a circuit status "BUILT" event or are listed as built in a - * getInfo circuit-status request). - * - * If circID is 0, responsibility for attaching the given stream is - * returned to Tor. - * - * By default, Tor automatically attaches streams to - * circuits itself, unless the configuration variable - * "__LeaveStreamsUnattached" is set to "1". Attempting to attach streams - * via TC when "__LeaveStreamsUnattached" is false may cause a race between - * Tor and the controller, as both attempt to attach streams to circuits. - */ - public void attachStream(String streamID, String circID) - throws IOException { - sendAndWaitForResponse("ATTACHSTREAM "+streamID+" "+circID+"\r\n", null); - } - - /** Tells Tor about the server descriptor in desc. - * - * The descriptor, when parsed, must contain a number of well-specified - * fields, including fields for its nickname and identity. - */ - // More documentation here on format of desc? - // No need for return value? control-spec.txt says reply is merely "250 OK" on success... - public String postDescriptor(String desc) throws IOException { - List lst = sendAndWaitForResponse("+POSTDESCRIPTOR\r\n", desc); - return (lst.get(0)).msg; - } - - /** Tells Tor to change the exit address of the stream identified by streamID - * to address. No remapping is performed on the new provided address. - * - * To be sure that the modified address will be used, this event must be sent - * after a new stream event is received, and before attaching this stream to - * a circuit. - */ - public void redirectStream(String streamID, String address) throws IOException { - sendAndWaitForResponse("REDIRECTSTREAM "+streamID+" "+address+"\r\n", - null); - } - - /** Tells Tor to close the stream identified by streamID. - * reason should be one of the Tor RELAY_END reasons given in tor-spec.txt, as a decimal: - *
    - *
  • 1 -- REASON_MISC (catch-all for unlisted reasons)
  • - *
  • 2 -- REASON_RESOLVEFAILED (couldn't look up hostname)
  • - *
  • 3 -- REASON_CONNECTREFUSED (remote host refused connection)
  • - *
  • 4 -- REASON_EXITPOLICY (OR refuses to connect to host or port)
  • - *
  • 5 -- REASON_DESTROY (Circuit is being destroyed)
  • - *
  • 6 -- REASON_DONE (Anonymized TCP connection was closed)
  • - *
  • 7 -- REASON_TIMEOUT (Connection timed out, or OR timed out while connecting)
  • - *
  • 8 -- (unallocated)
  • - *
  • 9 -- REASON_HIBERNATING (OR is temporarily hibernating)
  • - *
  • 10 -- REASON_INTERNAL (Internal error at the OR)
  • - *
  • 11 -- REASON_RESOURCELIMIT (OR has no resources to fulfill request)
  • - *
  • 12 -- REASON_CONNRESET (Connection was unexpectedly reset)
  • - *
  • 13 -- REASON_TORPROTOCOL (Sent when closing connection because of Tor protocol violations)
  • - *
- * - * Tor may hold the stream open for a while to flush any data that is pending. - */ - public void closeStream(String streamID, byte reason) - throws IOException { - sendAndWaitForResponse("CLOSESTREAM "+streamID+" "+reason+"\r\n",null); - } - - /** Tells Tor to close the circuit identified by circID. - * If ifUnused is true, do not close the circuit unless it is unused. - */ - public void closeCircuit(String circID, boolean ifUnused) throws IOException { - sendAndWaitForResponse("CLOSECIRCUIT "+circID+ - (ifUnused?" IFUNUSED":"")+"\r\n", null); - } -} - diff --git a/orbotmanager/src/test/java/org/torproject/android/control/TorControlError.java b/orbotmanager/src/test/java/org/torproject/android/control/TorControlError.java deleted file mode 100644 index d07ee514..00000000 --- a/orbotmanager/src/test/java/org/torproject/android/control/TorControlError.java +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2005 Nick Mathewson, Roger Dingledine -// See LICENSE file for copying information -package org.torproject.android.control; - -import java.io.IOException; - -/** - * An exception raised when Tor tells us about an error. - */ -public class TorControlError extends IOException { - - static final long serialVersionUID = 3; - - private final int errorType; - - public TorControlError(int type, String s) { - super(s); - errorType = type; - } - - public TorControlError(String s) { - this(-1, s); - } - - public int getErrorType() { - return errorType; - } - - public String getErrorMsg() { - try { - if (errorType == -1) - return null; - return TorControlCommands.ERROR_MSGS[errorType]; - } catch (ArrayIndexOutOfBoundsException ex) { - return "Unrecongized error #"+errorType; - } - } -} - diff --git a/orbotmanager/src/test/java/org/torproject/android/control/TorControlSyntaxError.java b/orbotmanager/src/test/java/org/torproject/android/control/TorControlSyntaxError.java deleted file mode 100644 index dba4f44b..00000000 --- a/orbotmanager/src/test/java/org/torproject/android/control/TorControlSyntaxError.java +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2005 Nick Mathewson, Roger Dingledine -// See LICENSE file for copying information -package org.torproject.android.control; - -import java.io.IOException; - -/** - * An exception raised when Tor behaves in an unexpected way. - */ -public class TorControlSyntaxError extends IOException { - - static final long serialVersionUID = 3; - - public TorControlSyntaxError(String s) { super(s); } -} - diff --git a/orbotmanager/src/test/java/org/torproject/android/control/examples/.cvsignore b/orbotmanager/src/test/java/org/torproject/android/control/examples/.cvsignore deleted file mode 100644 index 6b468b62..00000000 --- a/orbotmanager/src/test/java/org/torproject/android/control/examples/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -*.class diff --git a/orbotmanager/src/test/java/org/torproject/android/control/examples/DebuggingEventHandler.java b/orbotmanager/src/test/java/org/torproject/android/control/examples/DebuggingEventHandler.java deleted file mode 100644 index 48c49a28..00000000 --- a/orbotmanager/src/test/java/org/torproject/android/control/examples/DebuggingEventHandler.java +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2005 Nick Mathewson, Roger Dingledine -// See LICENSE file for copying information -package org.torproject.android.control.examples; - -import java.io.PrintWriter; -import java.util.Iterator; -import org.torproject.android.control.EventHandler; - -public class DebuggingEventHandler implements EventHandler { - - private final PrintWriter out; - - public DebuggingEventHandler(PrintWriter p) { - out = p; - } - - public void circuitStatus(String status, String circID, String path) { - out.println("Circuit "+circID+" is now "+status+" (path="+path+")"); - } - public void streamStatus(String status, String streamID, String target) { - out.println("Stream "+streamID+" is now "+status+" (target="+target+")"); - } - public void orConnStatus(String status, String orName) { - out.println("OR connection to "+orName+" is now "+status); - } - public void bandwidthUsed(long read, long written) { - out.println("Bandwidth usage: "+read+" bytes read; "+ - written+" bytes written."); - } - public void newDescriptors(java.util.List orList) { - out.println("New descriptors for routers:"); - for (Iterator i = orList.iterator(); i.hasNext(); ) - out.println(" "+i.next()); - } - public void message(String type, String msg) { - out.println("["+type+"] "+msg.trim()); - } - - public void unrecognized(String type, String msg) { - out.println("unrecognized event ["+type+"] "+msg.trim()); - } - -} - diff --git a/orbotmanager/src/test/java/org/torproject/android/control/examples/Main.java b/orbotmanager/src/test/java/org/torproject/android/control/examples/Main.java deleted file mode 100644 index b0e0a3c0..00000000 --- a/orbotmanager/src/test/java/org/torproject/android/control/examples/Main.java +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright 2005 Nick Mathewson, Roger Dingledine -// See LICENSE file for copying information -package org.torproject.android.control.examples; - -import org.torproject.android.control.*; -import java.io.EOFException; -import java.io.IOException; -import java.io.PrintWriter; -import java.net.Socket; -import java.util.ArrayList; -import java.util.List; -import java.util.Arrays; -import java.util.Map; -import java.util.Iterator; - -public class Main implements TorControlCommands { - - public static void main(String args[]) { - if (args.length < 1) { - System.err.println("No command given."); - return; - } - try { - if (args[0].equals("set-config")) { - setConfig(args); - } else if (args[0].equals("get-config")) { - getConfig(args); - } else if (args[0].equals("get-info")) { - getInfo(args); - } else if (args[0].equals("listen")) { - listenForEvents(args); - } else if (args[0].equals("signal")) { - signal(args); - } else if (args[0].equals("auth")) { - authDemo(args); - } else { - System.err.println("Unrecognized command: "+args[0]); - } - } catch (EOFException ex) { - System.out.println("Control socket closed by Tor."); - } catch (TorControlError ex) { - System.err.println("Error from Tor process: "+ - ex+" ["+ex.getErrorMsg()+"]"); - } catch (IOException ex) { - System.err.println("IO exception when talking to Tor process: "+ - ex); - ex.printStackTrace(System.err); - } - } - - private static TorControlConnection getConnection(String[] args, - boolean daemon) throws IOException { - Socket s = new Socket("127.0.0.1", 9100); - TorControlConnection conn = new TorControlConnection(s); - conn.launchThread(daemon); - conn.authenticate(new byte[0]); - return conn; - } - - private static TorControlConnection getConnection(String[] args) - throws IOException { - return getConnection(args, true); - } - - public static void setConfig(String[] args) throws IOException { - // Usage: "set-config [-save] key value key value key value" - TorControlConnection conn = getConnection(args); - ArrayList lst = new ArrayList(); - int i = 1; - boolean save = false; - if (args[i].equals("-save")) { - save = true; - ++i; - } - for (; i < args.length; i +=2) { - lst.add(args[i]+" "+args[i+1]); - } - conn.setConf(lst); - if (save) { - conn.saveConf(); - } - } - - public static void getConfig(String[] args) throws IOException { - // Usage: get-config key key key - TorControlConnection conn = getConnection(args); - List lst = conn.getConf(Arrays.asList(args).subList(1,args.length)); - for (Iterator i = lst.iterator(); i.hasNext(); ) { - ConfigEntry e = i.next(); - System.out.println("KEY: "+e.key); - System.out.println("VAL: "+e.value); - } - } - - public static void getInfo(String[] args) throws IOException { - TorControlConnection conn = getConnection(args); - Map m = conn.getInfo(Arrays.asList(args).subList(1,args.length)); - for (Iterator> i = m.entrySet().iterator(); i.hasNext(); ) { - Map.Entry e = i.next(); - System.out.println("KEY: "+e.getKey()); - System.out.println("VAL: "+e.getValue()); - } - } - - public static void listenForEvents(String[] args) throws IOException { - // Usage: listen [circ|stream|orconn|bw|newdesc|info|notice|warn|error]* - TorControlConnection conn = getConnection(args, false); - ArrayList lst = new ArrayList(); - for (int i = 1; i < args.length; ++i) { - lst.add(args[i]); - } - conn.setEventHandler( - new DebuggingEventHandler(new PrintWriter(System.out, true))); - conn.setEvents(lst); - } - - public static void signal(String[] args) throws IOException { - // Usage signal [reload|shutdown|dump|debug|halt] - TorControlConnection conn = getConnection(args, false); - // distinguish shutdown signal from other signals - if ("SHUTDOWN".equalsIgnoreCase(args[1]) - || "HALT".equalsIgnoreCase(args[1])) { - conn.shutdownTor(args[1].toUpperCase()); - } else { - conn.signal(args[1].toUpperCase()); - } - } - - public static void authDemo(String[] args) throws IOException { - - PasswordDigest pwd = PasswordDigest.generateDigest(); - Socket s = new Socket("127.0.0.1", 9100); - TorControlConnection conn = new TorControlConnection(s); - conn.launchThread(true); - conn.authenticate(new byte[0]); - - conn.setConf("HashedControlPassword", pwd.getHashedPassword()); - - s = new Socket("127.0.0.1", 9100); - conn = new TorControlConnection(s); - conn.launchThread(true); - conn.authenticate(pwd.getSecret()); - } - -} - diff --git a/orbotmanager/src/test/java/org/torproject/android/proxy/ExampleUnitTest.java b/orbotmanager/src/test/java/org/torproject/android/proxy/ExampleUnitTest.java deleted file mode 100644 index 25454778..00000000 --- a/orbotmanager/src/test/java/org/torproject/android/proxy/ExampleUnitTest.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.torproject.android.proxy; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * To work on unit tests, switch the Test Artifact in the Build Variants view. - */ -public class ExampleUnitTest { - @Test - public void addition_isCorrect() throws Exception { - assertEquals(4, 2 + 2); - } -} \ No newline at end of file diff --git a/orbotmanager/src/test/java/org/torproject/android/service/ExampleUnitTest.java b/orbotmanager/src/test/java/org/torproject/android/service/ExampleUnitTest.java deleted file mode 100644 index 578fa4b9..00000000 --- a/orbotmanager/src/test/java/org/torproject/android/service/ExampleUnitTest.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.torproject.android.service; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * To work on unit tests, switch the Test Artifact in the Build Variants view. - */ -public class ExampleUnitTest { - @Test - public void addition_isCorrect() throws Exception { - assertEquals(4, 2 + 2); - } -} \ No newline at end of file