Bug Fixes

Bug Fixes
master
msmannan00 2021-05-05 13:52:35 +05:00
parent 58329d826b
commit 48c2191eb2
84 changed files with 3947 additions and 1030 deletions

View File

@ -1,24 +1,10 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<JetCodeStyleSettings>
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value>
<package name="java.util" alias="false" withSubpackages="false" />
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
<package name="io.ktor" alias="false" withSubpackages="true" />
</value>
</option>
<option name="PACKAGES_IMPORT_LAYOUT">
<value>
<package name="" alias="false" withSubpackages="true" />
<package name="java" alias="false" withSubpackages="true" />
<package name="javax" alias="false" withSubpackages="true" />
<package name="kotlin" alias="false" withSubpackages="true" />
<package name="" alias="true" withSubpackages="true" />
</value>
</option>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<codeStyleSettings language="XML">
<option name="FORCE_REARRANGE_MODE" value="1" />
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
@ -130,5 +116,8 @@
</rules>
</arrangement>
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</codeStyleSettings>
</code_scheme>
</component>

View File

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="1.8" />
<bytecodeTargetLevel target="11" />
</component>
</project>

View File

@ -27,8 +27,8 @@
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
<option name="useQualifiedModuleNames" value="true" />
</GradleProjectSettings>
</option>
<option name="offlineMode" value="true" />
</component>
</project>

View File

@ -6,7 +6,7 @@
<inspection_tool class="BooleanMethodIsAlwaysInverted" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="BusyWait" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CollectionAddAllCanBeReplacedWithConstructor" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="ConstantConditions" enabled="false" level="WARNING" enabled_by_default="false">
<inspection_tool class="ConstantConditions" enabled="true" level="WARNING" enabled_by_default="true">
<option name="SUGGEST_NULLABLE_ANNOTATIONS" value="false" />
<option name="DONT_REPORT_TRUE_ASSERT_STATEMENTS" value="false" />
</inspection_tool>
@ -32,6 +32,9 @@
<option name="processComments" value="true" />
</inspection_tool>
<inspection_tool class="SuspiciousListRemoveInLoop" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SuspiciousMethodCalls" enabled="false" level="WARNING" enabled_by_default="false">
<option name="REPORT_CONVERTIBLE_METHOD_CALLS" value="true" />
</inspection_tool>
<inspection_tool class="TrivialIf" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="UNCHECKED_WARNING" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="UnnecessaryLocalVariable" enabled="false" level="WARNING" enabled_by_default="false">

View File

@ -43,5 +43,5 @@
</value>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK" />
</project>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
</set>
</option>
</component>
</project>

View File

@ -31,18 +31,6 @@
"versionName": "Build | Dark-Origin 1.1",
"outputFile": "app-aarch64-x86-release.apk"
},
{
"type": "ONE_OF_MANY",
"filters": [
{
"filterType": "ABI",
"value": "arm64-v8a"
}
],
"versionCode": 1001,
"versionName": "Build | Dark-Origin 1.1",
"outputFile": "app-aarch64-arm64-v8a-release.apk"
},
{
"type": "ONE_OF_MANY",
"filters": [
@ -54,6 +42,18 @@
"versionCode": 1001,
"versionName": "Build | Dark-Origin 1.1",
"outputFile": "app-aarch64-armeabi-v7a-release.apk"
},
{
"type": "ONE_OF_MANY",
"filters": [
{
"filterType": "ABI",
"value": "arm64-v8a"
}
],
"versionCode": 1001,
"versionName": "Build | Dark-Origin 1.1",
"outputFile": "app-aarch64-arm64-v8a-release.apk"
}
]
}

View File

@ -143,7 +143,9 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name="com.darkweb.genesissearchengine.externalNavigationManager.externalNavigationController">
<activity android:name="com.darkweb.genesissearchengine.externalNavigationManager.externalNavigationController"
android:launchMode="singleTask"
>
<intent-filter>
<action android:name="android.intent.action.VIEW" />

View File

@ -76,7 +76,7 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
mRealIndex.clear();
mCurrentList.clear();
this.mModelList.clear();
onVerifyLongSelectedURL();
onVerifyLongSelectedURL(true);
ArrayList<bookmarkRowModel> p_model_list = mPassedList;
for(int counter = 0; counter< p_model_list.size(); counter++){
@ -88,7 +88,7 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
}
mRealID.add(p_model_list.get(counter).getID());
mRealIndex.add(m_real_counter);
mRealIndex.add(counter);
this.mModelList.add(p_model_list.get(counter));
m_real_counter+=1;
}
@ -129,7 +129,7 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
}
}
clearLongSelectedURL();
initializeModelWithDate(false);
// initializeModelWithDate(false);
}
private void clearLongSelectedURL(){
@ -185,6 +185,15 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
mSearchEnabled = p_is_searched;
}
public void invokeSwipeClose(int pPosition){
onClose(pPosition);
invokeFilter(true);
if(mPopupWindow!=null){
mPopupWindow.dismiss();
}
}
public void onSelectView(View pItemView, String pUrl, View pMenuItem, ImageView pLogoImage, boolean pIsForced, int pId, Date pDate){
if(!mSearchEnabled){
try {
@ -196,16 +205,21 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
mLongSelectedDate.add(pDate);
mLongSelectedIndex.add(pUrl);
mLongSelectedID.add(pId);
if(mLongSelectedIndex.size()<=1){
notifyDataSetChanged();
}
onVerifyLongSelectedURL();
}
onVerifyLongSelectedURL(false);
}
}
public void onVerifyLongSelectedURL(){
public void onVerifyLongSelectedURL(boolean pIsComputing){
if(mLongSelectedIndex.size()>0){
mEvent.invokeObserver(Collections.singletonList(false),enums.etype.on_verify_selected_url_menu);
}else {
if(!pIsComputing){
notifyDataSetChanged();
}
mEvent.invokeObserver(Collections.singletonList(true),enums.etype.on_verify_selected_url_menu);
}
}
@ -217,12 +231,19 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
mLongSelectedDate.remove(pDate);
mLongSelectedIndex.remove(pUrl);
mLongSelectedID.remove((Integer) pId);
onVerifyLongSelectedURL();
onVerifyLongSelectedURL(false);
} catch (Exception e) {
e.printStackTrace();
}
}
public void notifyFilter(){
if(mFilter.length()>0){
initializeModelWithDate(true);
notifyDataSetChanged();
}
}
@SuppressLint("ClickableViewAccessibility")
public void onSwipe(View pItemView, String pUrl, View pMenuItem, ImageView pLogoImage, int pId, Date pDate){
@ -241,6 +262,7 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
pItemView.setPressed(false);
pItemView.clearFocus();
}
notifyFilter();
};
pItemView.setOnTouchListener((v, event) -> {
@ -257,12 +279,14 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
bookmarkAdapter.this.onSelectView(pItemView, pUrl, pMenuItem, pLogoImage, false, pId, pDate);
}
}
initializeModelWithDate(true);
return false;
}
v.setPressed(false);
handler.removeCallbacks(mLongPressed);
mEvent.invokeObserver(Collections.singletonList(pUrl), enums.etype.url_triggered);
initializeModelWithDate(true);
return true;
} else if (event.getAction() == MotionEvent.ACTION_DOWN) {
@ -270,6 +294,7 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
mLongPressedMenuActive = false;
v.setPressed(true);
handler.postDelayed(mLongPressed, ViewConfiguration.getLongPressTimeout());
initializeModelWithDate(true);
return true;
} else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
handler.removeCallbacks(mLongPressed);
@ -279,10 +304,13 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
}
handler.removeCallbacks(mLongPressed);
initializeModelWithDate(true);
return true;
}
initializeModelWithDate(true);
return false;
});
// initializeModelWithDate(false);
}
void onOpenMenu(View pView, String pUrl, int pPosition, String pTitle){
@ -295,6 +323,11 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
setPopupWindowEvents(mPopupView.findViewById(R.id.pMenuOpenCurrentTab), pUrl, pPosition, pTitle);
setPopupWindowEvents(mPopupView.findViewById(R.id.pMenuOpenNewTab), pUrl, pPosition, pTitle);
setPopupWindowEvents(mPopupView.findViewById(R.id.pMenuDelete), pUrl, pPosition, pTitle);
if(mFilter.length()>0){
initializeModelWithDate(true);
notifyDataSetChanged();
}
}
public void setPopupWindowEvents(View pView, String pUrl, int pPosition, String pTitle){
@ -333,29 +366,19 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
mEvent.invokeObserver(Collections.singletonList(mRealIndex.get(pIndex)),enums.etype.url_clear);
mEvent.invokeObserver(Collections.singletonList(mRealID.get(pIndex)),enums.etype.url_clear_at);
mEvent.invokeObserver(Collections.singletonList(mRealID.get(pIndex)),enums.etype.is_empty);
boolean mDateVerify = false;
if(mPassedList.size()>0){
if(mCurrentList.size()>0 && (mCurrentList.size()>pIndex+1 || mCurrentList.size()==pIndex+1)){
mDateVerify = true;
}
}else {
if(mPassedList.size()<=0){
mCurrentList.clear();
return;
}
int size = mCurrentList.size();
if(mDateVerify){
mCurrentList.remove(pIndex);
notifyItemRemoved(pIndex);
notifyItemRangeChanged(pIndex, mCurrentList.size());
}else {
mCurrentList.remove(pIndex);
notifyItemRemoved(pIndex);
notifyItemChanged(mCurrentList.size()-1);
}
initializeModelWithDate(false);
mCurrentList.remove(mRealIndex.get(pIndex));
notifyItemRemoved(mRealIndex.get(pIndex));
notifyItemRangeChanged(0, mCurrentList.size());
clearLongSelectedURL();
}
/*View Holder Extensions*/
class listViewHolder extends RecyclerView.ViewHolder
{
@ -411,8 +434,13 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
mDateContainer.setVisibility(View.GONE);
mLoadingContainer.setVisibility(View.GONE);
mRowContainer.setVisibility(View.VISIBLE);
if(mLongSelectedID.size()>0){
mRowMenu.setVisibility(View.INVISIBLE);
mRowMenu.setClickable(false);
}else {
mRowMenu.setVisibility(View.VISIBLE);
mRowMenu.setClickable(true);
}
mWebLogo.setVisibility(View.VISIBLE);
mHeader.setText(model.getHeader());
mWebLogo.setText((helperMethod.getDomainName(model.getHeader()).toUpperCase().charAt(0)+""));
@ -443,7 +471,7 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
Bitmap mBitmap = helperMethod.drawableToBitmap(mHindTypeIconTemp.getDrawable());
mFaviconLogo.setImageBitmap(mBitmap);
});
} catch (InterruptedException e) {
} catch (Exception e) {
e.printStackTrace();
}
}
@ -475,7 +503,7 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
void invokeFilter(boolean notify){
if(notify){
notifyDataSetChanged();
initializeModelWithDate(true);
}
}

View File

@ -83,6 +83,7 @@ public class bookmarkAdapterView
helperMethod.vibrate(mContext);
}
pLogoImage.setAlpha(0f);
pLogoImage.setVisibility(View.VISIBLE);
pLogoImage.animate().cancel();

View File

@ -23,6 +23,7 @@ import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.darkweb.genesissearchengine.appManager.activityContextManager;
import com.darkweb.genesissearchengine.appManager.historyManager.historyEnums;
import com.darkweb.genesissearchengine.databaseManager.databaseController;
import com.darkweb.genesissearchengine.appManager.homeManager.homeController.editTextManager;
import com.darkweb.genesissearchengine.appManager.homeManager.homeController.homeController;
@ -145,10 +146,11 @@ public class bookmarkController extends AppCompatActivity
mSearchInput.setOnFocusChangeListener((v, hasFocus) -> {
if (!hasFocus) {
mSearchInput.clearFocus();
// mSearchInput.clearFocus();
}else {
((bookmarkAdapter) Objects.requireNonNull(mRecycleView.getAdapter())).setFilter(mSearchInput.getText().toString());
((bookmarkAdapter) mRecycleView.getAdapter()).invokeFilter(true);
mbookmarkAdapter.setFilter(mSearchInput.getText().toString());
mbookmarkAdapter.invokeFilter(true);
mbookmarkAdapter.notifyDataSetChanged();
}
});
@ -167,10 +169,12 @@ public class bookmarkController extends AppCompatActivity
@Override
public void afterTextChanged(Editable editable)
{
((bookmarkAdapter) Objects.requireNonNull(mRecycleView.getAdapter())).setFilter(mSearchInput.getText().toString());
((bookmarkAdapter) mRecycleView.getAdapter()).invokeFilter(true);
mbookmarkAdapter.setFilter(mSearchInput.getText().toString());
mbookmarkAdapter.invokeFilter(true);
mbookmarkAdapter.notifyDataSetChanged();
}
});
}
@Override
@ -189,32 +193,15 @@ public class bookmarkController extends AppCompatActivity
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
int position = viewHolder.getAdapterPosition();
mbookmarkAdapter.onTrigger(bookmarkEnums.eBookmarkAdapterCommands.ON_CLOSE,Collections.singletonList(position));
mbookmarkAdapter.invokeSwipeClose(position);
}
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
boolean mStatus = (boolean) mbookmarkAdapter.onTrigger(bookmarkEnums.eBookmarkAdapterCommands.GET_LONG_SELECTED_STATUS, null);
if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) {
if(mStatus){
return 0;
}
else {
final int dragFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
final int swipeFlags = 0;
return makeMovementFlags(swipeFlags, dragFlags);
}
} else {
if(mStatus){
return 0;
}
else {
final int dragFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
final int swipeFlags = 0;
return makeMovementFlags(swipeFlags, dragFlags);
}
}
}
@Override
public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
@ -371,9 +358,6 @@ public class bookmarkController extends AppCompatActivity
else if(e_type.equals(enums.etype.url_clear)){
mbookmarkModel.onManualClear((int)data.get(0));
if(mbookmarkModel.getList().size()==0){
mRecycleView.setAlpha(0);
}
}
else if(e_type.equals(enums.etype.url_clear_at)){
dataController.getInstance().invokeBookmark(dataEnums.eBookmarkCommands.M_DELETE_BOOKMARK ,data);

View File

@ -100,6 +100,7 @@ class bookmarkViewController
mEmptyListNotification.animate().setDuration(pDuration).alpha(0f);
mClearButton.setText(strings.HISTORY_CLEAR_HISTORY);
mClearButton.setClickable(true);
mRecycleView.setVisibility(View.VISIBLE);
}
else {
mClearButton.setTextColor(ContextCompat.getColor(mContext, R.color.c_text_v3));
@ -120,6 +121,7 @@ class bookmarkViewController
mClearButton.getLayoutParams().height = 0;
mClearButton.requestLayout();
mRecycleView.setVisibility(View.GONE);
}
}
@ -178,8 +180,6 @@ class bookmarkViewController
mSearchInput.setVisibility(View.GONE);
mSearchInput.setText(strings.GENERIC_EMPTY_STR);
new Handler().postDelayed(() ->
{
mTitle.setAlpha(0f);
mTitle.setVisibility(View.VISIBLE);
mTitle.animate().setDuration(150).alpha(1);
@ -187,7 +187,6 @@ class bookmarkViewController
mSearchButton.setAlpha(0f);
mSearchButton.setVisibility(View.VISIBLE);
mSearchButton.animate().setDuration(150).alpha(1);
}, 500);
mSearchInput.setText(strings.GENERIC_EMPTY_STR);
mSearchInput.setClickable(false);

View File

@ -91,7 +91,7 @@ public class historyAdapter extends RecyclerView.Adapter<historyAdapter.listView
mRealIndex.clear();
mCurrentList.clear();
this.mModelList.clear();
onVerifyLongSelectedURL();
onVerifyLongSelectedURL(true);
ArrayList<historyRowModel> p_model_list = mPassedList;
int m_date_state = -1;
@ -117,7 +117,7 @@ public class historyAdapter extends RecyclerView.Adapter<historyAdapter.listView
if(m_date_state!=1 && p_model_list.get(counter).getID()!=-2){
this.mModelList.add(new historyRowModel("Today ",null,-1));
mRealID.add(m_real_counter);
mRealIndex.add(m_real_counter);
mRealIndex.add(counter);
m_date_state = 1;
}
}else if (diff>=1){
@ -126,20 +126,20 @@ public class historyAdapter extends RecyclerView.Adapter<historyAdapter.listView
m_last_day = (int)(Math.ceil(diff/7)*7);
this.mModelList.add(new historyRowModel("Last " + m_last_day + " Days",null,-1));
mRealID.add(m_real_counter);
mRealIndex.add(m_real_counter);
mRealIndex.add(counter);
m_date_state = 2;
}
}else {
if(m_date_state!=3){
this.mModelList.add(new historyRowModel("Older ",null,-1));
mRealID.add(m_real_counter);
mRealIndex.add(m_real_counter);
mRealIndex.add(counter);
m_date_state = 3;
}
}
mRealID.add(p_model_list.get(counter).getID());
mRealIndex.add(m_real_counter);
mRealIndex.add(counter);
this.mModelList.add(p_model_list.get(counter));
m_real_counter+=1;
}
@ -251,16 +251,33 @@ public class historyAdapter extends RecyclerView.Adapter<historyAdapter.listView
mLongSelectedDate.add(pDate);
mLongSelectedIndex.add(pUrl);
mLongSelectedID.add(pId);
if(mLongSelectedIndex.size()<=1){
notifyDataSetChanged();
}
onVerifyLongSelectedURL();
}
onVerifyLongSelectedURL(false);
pItemView.clearFocus();
pItemView.setPressed(false);
pItemView.setVisibility(View.GONE);
pItemView.setVisibility(View.VISIBLE);
}
}
public void onVerifyLongSelectedURL(){
public boolean isSwipable(int mIndex){
if(mCurrentList.get(mIndex).getID() == -1){
return false;
}else {
return true;
}
}
public void onVerifyLongSelectedURL(boolean pIsComputing){
if(mLongSelectedIndex.size()>0){
mEvent.invokeObserver(Collections.singletonList(false),enums.etype.on_verify_selected_url_menu);
}else {
if(!pIsComputing){
notifyDataSetChanged();
}
mEvent.invokeObserver(Collections.singletonList(true),enums.etype.on_verify_selected_url_menu);
}
}
@ -272,7 +289,7 @@ public class historyAdapter extends RecyclerView.Adapter<historyAdapter.listView
mLongSelectedDate.remove(pDate);
mLongSelectedIndex.remove(pUrl);
mLongSelectedID.remove((Integer) pId);
onVerifyLongSelectedURL();
onVerifyLongSelectedURL(false);
} catch (Exception e) {
e.printStackTrace();
}
@ -282,6 +299,13 @@ public class historyAdapter extends RecyclerView.Adapter<historyAdapter.listView
mWebIcon.clear();
}
public void notifyFilter(){
if(mFilter.length()>0){
initializeModelWithDate(true);
notifyDataSetChanged();
}
}
@SuppressLint("ClickableViewAccessibility")
public void onSwipe(View pItemView, String pUrl, View pMenuItem, ImageView pLogoImage, int pId, Date pDate){
@ -300,6 +324,11 @@ public class historyAdapter extends RecyclerView.Adapter<historyAdapter.listView
pItemView.setPressed(false);
pItemView.clearFocus();
}
if(mFilter.length()>0){
initializeModelWithDate(true);
notifyDataSetChanged();
}
};
pItemView.setOnTouchListener((v, event) -> {
@ -316,12 +345,15 @@ public class historyAdapter extends RecyclerView.Adapter<historyAdapter.listView
historyAdapter.this.onSelectView(pItemView, pUrl, pMenuItem, pLogoImage, false, pId, pDate);
}
}
initializeModelWithDate(true);
return false;
}
v.setPressed(false);
handler.removeCallbacks(mLongPressed);
mEvent.invokeObserver(Collections.singletonList(pUrl), enums.etype.url_triggered);
initializeModelWithDate(true);
return true;
} else if (event.getAction() == MotionEvent.ACTION_DOWN) {
@ -329,6 +361,7 @@ public class historyAdapter extends RecyclerView.Adapter<historyAdapter.listView
mLongPressedMenuActive = false;
v.setPressed(true);
handler.postDelayed(mLongPressed, ViewConfiguration.getLongPressTimeout());
initializeModelWithDate(true);
return true;
} else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
handler.removeCallbacks(mLongPressed);
@ -338,11 +371,14 @@ public class historyAdapter extends RecyclerView.Adapter<historyAdapter.listView
}
handler.removeCallbacks(mLongPressed);
initializeModelWithDate(true);
return true;
}
initializeModelWithDate(true);
return false;
});
initializeModelWithDate(false);
//initializeModelWithDate(false);
}
void onOpenMenu(View pView, String pUrl, int pPosition, String pTitle){
@ -355,6 +391,20 @@ public class historyAdapter extends RecyclerView.Adapter<historyAdapter.listView
setPopupWindowEvents(mPopupView.findViewById(R.id.pMenuOpenCurrentTab), pUrl, pPosition, pTitle);
setPopupWindowEvents(mPopupView.findViewById(R.id.pMenuOpenNewTab), pUrl, pPosition, pTitle);
setPopupWindowEvents(mPopupView.findViewById(R.id.pMenuDelete), pUrl, pPosition, pTitle);
if(mFilter.length()>0){
initializeModelWithDate(true);
notifyDataSetChanged();
}
}
public void invokeSwipeClose(int pPosition){
onClose(pPosition);
invokeFilter(true);
if(mPopupWindow!=null){
mPopupWindow.dismiss();
}
}
public void setPopupWindowEvents(View pView, String pUrl, int pPosition, String pTitle){
@ -393,27 +443,16 @@ public class historyAdapter extends RecyclerView.Adapter<historyAdapter.listView
mEvent.invokeObserver(Collections.singletonList(mRealIndex.get(pIndex)),enums.etype.url_clear);
mEvent.invokeObserver(Collections.singletonList(mRealID.get(pIndex)),enums.etype.url_clear_at);
mEvent.invokeObserver(Collections.singletonList(mRealID.get(pIndex)),enums.etype.is_empty);
boolean mDateVerify = false;
if(mPassedList.size()>0){
if(mCurrentList.size()>0 && (mCurrentList.size()>pIndex+1 || mCurrentList.size()==pIndex+1)){
mDateVerify = true;
}
}else {
if(mPassedList.size()<=0){
mCurrentList.clear();
return;
}
int size = mCurrentList.size();
if(mDateVerify){
mCurrentList.remove(pIndex);
notifyItemRemoved(pIndex);
notifyItemRangeChanged(pIndex, mCurrentList.size());
}else {
mCurrentList.remove(pIndex);
notifyItemRemoved(pIndex);
notifyItemChanged(mCurrentList.size()-1);
}
initializeModelWithDate(false);
notifyItemRangeChanged(0, mCurrentList.size());
clearLongSelectedURL();
}
/*View Holder Extensions*/
@ -472,8 +511,14 @@ public class historyAdapter extends RecyclerView.Adapter<historyAdapter.listView
mDateContainer.setVisibility(View.GONE);
mLoadingContainer.setVisibility(View.GONE);
mRowContainer.setVisibility(View.VISIBLE);
if(mLongSelectedID.size()>0){
mRowMenu.setVisibility(View.INVISIBLE);
mRowMenu.setClickable(false);
}else {
mRowMenu.setVisibility(View.VISIBLE);
mRowMenu.setClickable(true);
}
mWebLogo.setVisibility(View.VISIBLE);
mHeader.setText(model.getHeader());
mWebLogo.setText((helperMethod.getDomainName(model.getHeader()).toUpperCase().charAt(0)+""));

View File

@ -164,6 +164,9 @@ public class historyController extends AppCompatActivity
mSearchInput.setOnEditorActionListener((v, actionId, event) ->{
if (actionId == EditorInfo.IME_ACTION_NEXT)
{
mHistoryAdapter.setFilter(mSearchInput.getText().toString());
mHistoryAdapter.invokeFilter(true);
mHistoryAdapter.notifyDataSetChanged();
helperMethod.hideKeyboard(this);
return true;
}
@ -172,14 +175,15 @@ public class historyController extends AppCompatActivity
mSearchInput.setOnFocusChangeListener((v, hasFocus) -> {
if (!hasFocus) {
//mSearchInput.clearFocus();
//onHideSearch(null);
// mSearchInput.clearFocus();
}else {
//mHistoryAdapter.setFilter(mSearchInput.getText().toString());
//mHistoryAdapter.invokeFilter(true);
mHistoryAdapter.setFilter(mSearchInput.getText().toString());
mHistoryAdapter.invokeFilter(true);
mHistoryAdapter.notifyDataSetChanged();
}
});
mSearchInput.addTextChangedListener(new TextWatcher() {
@Override
@ -197,6 +201,7 @@ public class historyController extends AppCompatActivity
{
mHistoryAdapter.setFilter(mSearchInput.getText().toString());
mHistoryAdapter.invokeFilter(true);
mHistoryAdapter.notifyDataSetChanged();
}
});
}
@ -212,31 +217,19 @@ public class historyController extends AppCompatActivity
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
int position = viewHolder.getAdapterPosition();
mHistoryAdapter.onTrigger(historyEnums.eHistoryAdapterCommands.ON_CLOSE,Collections.singletonList(position));
mHistoryAdapter.invokeSwipeClose(position);
}
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
boolean mStatus = (boolean) mHistoryAdapter.onTrigger(historyEnums.eHistoryAdapterCommands.GET_LONG_SELECTED_STATUS, null);
if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) {
if(mStatus){
return 0;
}
else {
int position = viewHolder.getAdapterPosition();
if(mHistoryAdapter.isSwipable(position)){
final int dragFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
final int swipeFlags = 0;
return makeMovementFlags(swipeFlags, dragFlags);
}
} else {
if(mStatus){
}else {
return 0;
}
else {
final int dragFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
final int swipeFlags = 0;
return makeMovementFlags(swipeFlags, dragFlags);
}
}
}
@Override

View File

@ -91,6 +91,7 @@ class historyViewController
mEmptyListNotification.animate().setDuration(pDuration).alpha(0f);
mClearButton.setText(strings.HISTORY_CLEAR_HISTORY);
mClearButton.setClickable(true);
mRecycleView.setVisibility(View.VISIBLE);
}
else {
mClearButton.setTextColor(ContextCompat.getColor(mContext, R.color.c_text_v3));
@ -111,6 +112,7 @@ class historyViewController
mClearButton.getLayoutParams().height = 0;
mClearButton.requestLayout();
mRecycleView.setVisibility(View.GONE);
}
}

View File

@ -4,24 +4,24 @@ import android.content.Context;
import androidx.core.view.NestedScrollingChildHelper;
import androidx.core.view.ViewCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import com.darkweb.genesissearchengine.constants.status;
import com.darkweb.genesissearchengine.helperManager.eventObserver;
import org.mozilla.geckoview.GeckoView;
import org.mozilla.geckoview.PanZoomController;
import java.util.Collections;
import static com.darkweb.genesissearchengine.constants.enums.etype.GECKO_SCROLL_CHANGED;
import static com.darkweb.genesissearchengine.constants.enums.etype.GECKO_SCROLL_DOWN;
import static com.darkweb.genesissearchengine.constants.enums.etype.GECKO_SCROLL_UP_ALWAYS;
public class NestedGeckoView extends GeckoView {
private int mLastY = 0;
private int deltaY = 0;
private int mLastY;
private final int[] mScrollOffset = new int[2];
private final int[] mScrollConsumed = new int[2];
private int mNestedOffsetY;
private NestedScrollingChildHelper mChildHelper;
private eventObserver.eventListener mEvent;
private int mInputResult = PanZoomController.INPUT_RESULT_UNHANDLED;
public void onSetHomeEvent(eventObserver.eventListener pEvent){
mEvent = pEvent;
@ -32,71 +32,76 @@ public class NestedGeckoView extends GeckoView {
mChildHelper = null;
}
public NestedGeckoView(final Context context) {
this(context, null);
}
public NestedGeckoView(Context context, AttributeSet attrs) {
super(context.getApplicationContext(), attrs);
public NestedGeckoView(final Context context, final AttributeSet attrs) {
super(context, attrs);
mChildHelper = new NestedScrollingChildHelper(this);
setNestedScrollingEnabled(true);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
MotionEvent event = MotionEvent.obtain(ev);
final int action = event.getActionMasked();
int eventY = (int) event.getY();
final MotionEvent event = MotionEvent.obtain(ev);
final int action = ev.getActionMasked();
if (action == MotionEvent.ACTION_DOWN) {
mNestedOffsetY = 0;
}
final int eventY = (int) event.getY();
event.offsetLocation(0, mNestedOffsetY);
if(event.getPointerCount() > 1 && !status.sSettingEnableZoom) {
return true;
}
switch (action) {
case MotionEvent.ACTION_MOVE:
final boolean allowScroll = !shouldPinOnScreen() &&
mInputResult == PanZoomController.INPUT_RESULT_HANDLED;
if(!status.sSettingEnableZoom){
mInputResult = PanZoomController.INPUT_RESULT_UNHANDLED;
}
// mEvent.invokeObserver(Collections.singletonList(null), GECKO_SCROLL_FINISHED);
final boolean allowScroll = status.sFullScreenBrowsing;
int deltaY = mLastY - eventY;
if (allowScroll && dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset)) {
deltaY -= mScrollConsumed[1];
event.offsetLocation(0f, -mScrollOffset[1]);
event.offsetLocation(0, -mScrollOffset[1]);
mNestedOffsetY += mScrollOffset[1];
}
mLastY = eventY - mScrollOffset[1];
if (allowScroll && dispatchNestedScroll(0, mScrollOffset[1], 0, deltaY, mScrollOffset)) {
mLastY -= mScrollOffset[1];
event.offsetLocation(0f, mScrollOffset[1]);
event.offsetLocation(0, mScrollOffset[1]);
mNestedOffsetY += mScrollOffset[1];
}
if(status.sFullScreenBrowsing){
Log.i("wow1", eventY + "");
}
break;
case MotionEvent.ACTION_DOWN:
// A new gesture started. Reset handled status and ask GV if it can handle this.
mInputResult = PanZoomController.INPUT_RESULT_UNHANDLED;
updateInputResult(event);
mNestedOffsetY = 0;
mLastY = eventY;
startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL);
mEvent.invokeObserver(Collections.singletonList(null), GECKO_SCROLL_DOWN);
break;
// The event should be handled either by onTouchEvent,
// either by onTouchEventForResult, never by both.
// Early return if we sent it to updateInputResult(..) which calls onTouchEventForResult.
event.recycle();
return true;
// We don't care about other touch events
case MotionEvent.ACTION_UP:
mEvent.invokeObserver(Collections.singletonList(null), GECKO_SCROLL_UP_ALWAYS);
case MotionEvent.ACTION_CANCEL:
// mEvent.invokeObserver(Collections.singletonList(null), GECKO_SCROLL_FINISHED);
stopNestedScroll();
break;
default:
// mEvent.invokeObserver(Collections.singletonList(null), GECKO_SCROLL_FINISHED);
}
// Execute event handler from parent class in all cases
final boolean eventHandled = callSuperOnTouchEvent(event);
boolean eventHandled = super.onTouchEvent(event);
// Recycle previously obtained event
event.recycle();
@ -104,25 +109,6 @@ public class NestedGeckoView extends GeckoView {
return eventHandled;
}
private boolean callSuperOnTouchEvent(MotionEvent event) {
return super.onTouchEvent(event);
}
private void updateInputResult(MotionEvent event) {
if(status.sSettingEnableZoom){
super.onTouchEventForResult(event).accept(inputResult -> {
mInputResult = inputResult;
mInputResult = PanZoomController.INPUT_RESULT_UNHANDLED;
startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL);
});
}
}
public int getInputResult() {
return mInputResult;
}
@Override
public void setNestedScrollingEnabled(boolean enabled) {
mChildHelper.setNestedScrollingEnabled(enabled);
@ -149,11 +135,7 @@ public class NestedGeckoView extends GeckoView {
}
@Override
public boolean dispatchNestedScroll(int dxConsumed,
int dyConsumed,
int dxUnconsumed,
int dyUnconsumed,
int[] offsetInWindow) {
public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) {
return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow);
}
@ -167,8 +149,8 @@ public class NestedGeckoView extends GeckoView {
return mChildHelper.dispatchNestedFling(velocityX, velocityY, consumed);
}
@Override
public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
return mChildHelper.dispatchNestedPreFling(velocityX, velocityY);
public int getMaxY(){
return 1;
}
}

View File

@ -3,6 +3,7 @@ package com.darkweb.genesissearchengine.appManager.homeManager.geckoManager;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.util.Log;
import android.widget.ImageView;
import androidx.appcompat.app.AppCompatActivity;
@ -13,8 +14,12 @@ import com.darkweb.genesissearchengine.dataManager.dataController;
import com.darkweb.genesissearchengine.dataManager.dataEnums;
import com.darkweb.genesissearchengine.helperManager.eventObserver;
import com.darkweb.genesissearchengine.helperManager.helperMethod;
import java.io.File;
import java.util.List;
import static com.darkweb.genesissearchengine.constants.constants.CONST_GENESIS_URL_CACHED;
import static com.darkweb.genesissearchengine.constants.constants.CONST_GENESIS_URL_CACHED_DARK;
import static com.darkweb.genesissearchengine.constants.constants.CONST_REPORT_URL;
import static com.darkweb.genesissearchengine.constants.enums.etype.on_handle_external_intent;
import static org.mozilla.geckoview.GeckoSessionSettings.USER_AGENT_MODE_MOBILE;
@ -71,15 +76,28 @@ public class geckoClients
public void onValidateInitializeFromStartup(NestedGeckoView mNestedGeckoView, AppCompatActivity pcontext){
boolean mStatus = mSession.onValidateInitializeFromStartup();
if(mStatus){
// loadURL(mSession.getCurrentURL(), mNestedGeckoView, pcontext);
mSession.onRestoreState();
mSession.reload();
boolean mState = mSession.onRestoreState();
if(!mState){
new Handler().postDelayed(() ->
{
mSession.stop();
mSession.loadUri(mSession.getCurrentURL());
}, 500);
}else {
String mURL = mSession.getCurrentURL();
if(mURL.equals("https://boogle.store") || mURL.startsWith(CONST_GENESIS_URL_CACHED) || mURL.startsWith(CONST_GENESIS_URL_CACHED_DARK)){
if(!mSession.canGoBack()){
mNestedGeckoView.releaseSession();
mSession.close();
mSession.open(mRuntime);
mNestedGeckoView.setSession(mSession);
}else {
mSession.goBack();
}
loadURL("boogle.store", mNestedGeckoView, pcontext);
}
}
}
public boolean onGetInitializeFromStartup(){
return mSession.onGetInitializeFromStartup();
}
public geckoSession initFreeSession(GeckoView pGeckoView, AppCompatActivity pcontext, eventObserver.eventListener event){
@ -223,6 +241,7 @@ public class geckoClients
if(status.sTheme == enums.Theme.THEME_LIGHT || helperMethod.isDayMode(pcontext)){
String mURL = constants.CONST_GENESIS_URL_CACHED + "?pData="+ dataController.getInstance().invokeReferenceWebsite(dataEnums.eReferenceWebsiteCommands.M_FETCH,null);
mSession.getSettings().setAllowJavascript(true);
mSession.initURL(mURL);
mSession.loadUri(mURL);
}else {
String mURL = constants.CONST_GENESIS_URL_CACHED_DARK + "?pData="+ dataController.getInstance().invokeReferenceWebsite(dataEnums.eReferenceWebsiteCommands.M_FETCH,null);
@ -258,6 +277,10 @@ public class geckoClients
onLoadFavIcon(pcontext);
}
public boolean isLoaded(){
return mSession.isLoaded();
}
public void onClearSiteData(){
mRuntime.getStorageController().clearData(SITE_SETTINGS);
mRuntime.getStorageController().clearData(SITE_DATA);
@ -278,9 +301,10 @@ public class geckoClients
mRuntime.getStorageController().clearData(COOKIES);
}
public void onBackPressed(boolean isFinishAllowed, int mTabSize){
public void onBackPressed(boolean isFinishAllowed, int mTabSize, NestedGeckoView mNestedGeckoView, AppCompatActivity pcontext){
if(mSession.canGoBack()){
mSession.goBackSession();
mSession.onUpdateBannerAdvert();
}
else if(isFinishAllowed){
if(mSession.getRemovableFromBackPressed() && mTabSize>1){
@ -321,6 +345,10 @@ public class geckoClients
}
}
public void onClose(){
mSession.onClose();
}
public void setRemovableFromBackPressed(boolean pStatus){
mSession.setRemovableFromBackPressed(pStatus);
}
@ -331,9 +359,18 @@ public class geckoClients
}
public void onReload(NestedGeckoView mNestedGeckoView, AppCompatActivity pcontext){
///mSession.stop();
mSession.stop();
String url = mSession.getCurrentURL();
if(url.startsWith("https://boogle.store/?pG") || url.startsWith("https://boogle.store?pG") || url.endsWith("boogle.store") || url.contains(constants.CONST_GENESIS_HELP_URL_SUB) || url.contains(constants.CONST_GENESIS_HELP_URL_CACHE) || url.contains(constants.CONST_GENESIS_HELP_URL_CACHE_DARK)){
loadURL(mSession.getCurrentURL(), mNestedGeckoView, pcontext);
}else{
mSession.reload();
//loadURL(mSession.getCurrentURL(), mNestedGeckoView, pcontext);
}
}
public void onReloadStatic(NestedGeckoView mNestedGeckoView, AppCompatActivity pcontext){
///mSession.stop();
loadURL(mSession.getCurrentURL(), mNestedGeckoView, pcontext);
}
public void manual_download(String url, AppCompatActivity context){
@ -377,12 +414,53 @@ public class geckoClients
mRuntime.getSettings().setFontSizeFactor(font/100);
}
public void reinitHomeTheme(){
String mURLFinal;
mSession.initURL(constants.CONST_GENESIS_DOMAIN_URL);
if(status.sTheme == enums.Theme.THEME_LIGHT || helperMethod.isDayMode(activityContextManager.getInstance().getHomeController())){
String mURL = constants.CONST_GENESIS_URL_CACHED + "?pData="+ dataController.getInstance().invokeReferenceWebsite(dataEnums.eReferenceWebsiteCommands.M_FETCH,null);
mSession.getSettings().setAllowJavascript(true);
mSession.initURL(mURL);
mURLFinal = mURL;
}else {
String mURL = constants.CONST_GENESIS_URL_CACHED_DARK + "?pData="+ dataController.getInstance().invokeReferenceWebsite(dataEnums.eReferenceWebsiteCommands.M_FETCH,null);
mSession.getSettings().setAllowJavascript(true);
mSession.initURL(mURL);
mURLFinal = mURL;
}
if(!mSession.canGoBack()){
activityContextManager.getInstance().getHomeController().getGeckoView().releaseSession();
mSession.close();
mSession.open(mRuntime);
activityContextManager.getInstance().getHomeController().getGeckoView().setSession(mSession);
}else {
mSession.goBack();
}
new Handler().postDelayed(() ->
{
if(!mSession.canGoBack()){
mSession.close();
activityContextManager.getInstance().getHomeController().getGeckoView().releaseSession();
mSession.open(mRuntime);
activityContextManager.getInstance().getHomeController().getGeckoView().setSession(mSession);
}
mSession.loadUri(mURLFinal);
}, 10);
}
public class geckoViewClientCallback implements eventObserver.eventListener{
@Override
public Object invokeObserver(List<Object> data, Object e_type)
{
if(mSession!=null && mSession.isClosed()){
if(e_type.equals(enums.etype.M_CHANGE_HOME_THEME)){
reinitHomeTheme();
}
else if(mSession!=null && mSession.isClosed()){
return null;
}else if(mSession!=null) {
if(e_type.equals(enums.etype.SESSION_ID)){

View File

@ -28,6 +28,8 @@ import androidx.annotation.UiThread;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationCompat;
import androidx.core.content.FileProvider;
import com.darkweb.genesissearchengine.appManager.activityContextManager;
import com.darkweb.genesissearchengine.constants.constants;
import com.darkweb.genesissearchengine.constants.enums;
import com.darkweb.genesissearchengine.constants.status;
@ -75,12 +77,14 @@ public class geckoSession extends GeckoSession implements GeckoSession.MediaDele
{
private eventObserver.eventListener event;
private boolean wasBackPressed = false;
private String mSessionID;
private boolean mCanGoBack = false;
private boolean mCanGoForward = false;
private boolean mFullScreen = false;
private boolean isPageLoading = false;
private int mProgress = 0;
private String mPrevURL = "about:blank";
private String mCurrentTitle = "loading";
private String mCurrentURL = "about:blank";
private Uri mUriPermission = null;
@ -341,6 +345,10 @@ public class geckoSession extends GeckoSession implements GeckoSession.MediaDele
event.invokeObserver(Arrays.asList("",mSessionID,mCurrentTitle, m_current_url_id, mTheme, false), dataEnums.eTabCommands.M_UPDATE_PIXEL);
}
public boolean isLoaded(){
return mProgress>=100;
}
/*History Delegate*/
@Override
public GeckoResult<Boolean> onVisited(@NonNull GeckoSession var1, @NonNull String var2, @Nullable String var3, int var4) {
@ -360,16 +368,19 @@ public class geckoSession extends GeckoSession implements GeckoSession.MediaDele
@UiThread
public void onSessionStateChange(@NonNull GeckoSession session, @NonNull SessionState sessionState) {
mSessionState = sessionState;
if(!status.sRestoreTabs){
mSessionState = null;
}
if(mSessionState!=null)
// if(!status.sRestoreTabs){
// mSessionState = null;
// }
// if(mSessionState!=null)
event.invokeObserver(Arrays.asList(mCurrentURL,mSessionID,mCurrentTitle, m_current_url_id, mTheme, mSessionState.toString()), enums.etype.M_UPDATE_SESSION_STATE);
}
public void onRestoreState(){
public boolean onRestoreState(){
if(mSessionState!=null){
restoreState(mSessionState);
return true;
}else {
return false;
}
}
@ -379,6 +390,21 @@ public class geckoSession extends GeckoSession implements GeckoSession.MediaDele
if(!mIsLoaded){
return;
}
if(wasBackPressed && mHistoryList.get(mHistoryList.getCurrentIndex()-1).getUri().equals(var2)){
if(var2.equals("https://boogle.store") || var2.startsWith(CONST_GENESIS_URL_CACHED) || var2.startsWith(CONST_GENESIS_URL_CACHED_DARK)){
if(var2.startsWith(CONST_GENESIS_URL_CACHED_DARK) && (status.sTheme == enums.Theme.THEME_LIGHT || helperMethod.isDayMode(mContext.get()))){
isPageLoading = false;
//stop();
event.invokeObserver(null, enums.etype.M_CHANGE_HOME_THEME);
}
else if(var2.startsWith(CONST_GENESIS_URL_CACHED) && (status.sTheme != enums.Theme.THEME_LIGHT && !helperMethod.isDayMode(mContext.get()))){
isPageLoading = false;
//stop();
event.invokeObserver(null, enums.etype.M_CHANGE_HOME_THEME);
}
}
}
wasBackPressed = false;
String newUrl = Objects.requireNonNull(var2).split("#")[0];
if(!mCurrentTitle.equals("loading")){
@ -441,6 +467,7 @@ public class geckoSession extends GeckoSession implements GeckoSession.MediaDele
}
else if(var1.target==2){
event.invokeObserver(Arrays.asList(var1.uri,mSessionID), enums.etype.open_new_tab);
event.invokeObserver(Arrays.asList(mCurrentURL,mSessionID,mCurrentTitle, mTheme), enums.etype.ON_EXPAND_TOP_BAR);
return GeckoResult.fromValue(AllowOrDeny.DENY);
}
else if(!var1.uri.equals("about:blank")){
@ -452,14 +479,13 @@ public class geckoSession extends GeckoSession implements GeckoSession.MediaDele
}else {
setURL(constants.CONST_GENESIS_HELP_URL_CACHE_DARK);
}
}else{
}else if(!var1.uri.startsWith("resource://android/assets/homepage/")){
setURL(var1.uri);
}
event.invokeObserver(Arrays.asList(var1.uri,mSessionID), enums.etype.start_proxy);
event.invokeObserver(Arrays.asList(mCurrentURL,mSessionID), enums.etype.search_update);
checkApplicationRate();
event.invokeObserver(Arrays.asList(mCurrentURL,mSessionID,mCurrentTitle, mTheme), enums.etype.ON_EXPAND_TOP_BAR);
/* Its Absence causes delay on first launch*/
if(!mCurrentURL.contains("boogle.store")){
@ -473,6 +499,17 @@ public class geckoSession extends GeckoSession implements GeckoSession.MediaDele
}
}
public void onUpdateBannerAdvert(){
event.invokeObserver(Arrays.asList(mCurrentURL,mSessionID,mCurrentTitle, false), enums.etype.M_ON_BANNER_UPDATE);
}
public void onClose(){
stop();
mCurrentURL = mPrevURL;
//mIsLoaded = false;
//isPageLoading = false;
}
@Override
public void onCanGoBack(@NonNull GeckoSession session, boolean var2)
{
@ -537,6 +574,8 @@ public class geckoSession extends GeckoSession implements GeckoSession.MediaDele
}
event.invokeObserver(Arrays.asList(mCurrentURL,mSessionID,mCurrentTitle, m_current_url_id, mTheme), enums.etype.M_UPDATE_PIXEL_BACKGROUND);
event.invokeObserver(Arrays.asList(mCurrentURL,mSessionID,mCurrentTitle, mTheme), enums.etype.ON_EXPAND_TOP_BAR);
mPrevURL = mCurrentURL;
}
@UiThread
@ -826,8 +865,8 @@ public class geckoSession extends GeckoSession implements GeckoSession.MediaDele
}
public String getCurrentURL(){
if(mCurrentURL.equals("resource://android/assets/Homepage/homepage.html")){
setURL("https://boogle.store");
if(mCurrentURL.equals("resource://android/assets/Homepage/homepage.html") || mCurrentURL.equals("resource://android/assets/Homepage/homepage-dark.html")){
//setURL("https://boogle.store");
}
return mCurrentURL;
}
@ -940,30 +979,8 @@ public class geckoSession extends GeckoSession implements GeckoSession.MediaDele
}
void goBackSession(){
wasBackPressed = true;
goBack();
/*
if(mHistoryList!=null){
stop();
int index = mHistoryList.getCurrentIndex()-1;
initURL(mHistoryList.get(index).getUri());
if(mHistoryList.size()>index && index>0){
event.invokeObserver(Arrays.asList(mHistoryList.get(index).getUri(), mSessionID), enums.etype.start_proxy);
}
final Handler handler = new Handler();
handler.postDelayed(this::goBack, 100);
mProgress = 5;
event.invokeObserver(Arrays.asList(5, mSessionID, mCurrentURL), enums.etype.progress_update_forced);
event.invokeObserver(Arrays.asList(5, mSessionID, mCurrentURL), enums.etype.M_ADMOB_BANNER_RECHECK);
}
else {
final Handler handler = new Handler();
handler.postDelayed(this::goBack, 100);
mProgress = 5;
event.invokeObserver(Arrays.asList(5, mSessionID, mCurrentURL), enums.etype.progress_update_forced);
event.invokeObserver(Arrays.asList(5, mSessionID, mCurrentURL), enums.etype.M_ADMOB_BANNER_RECHECK);
}*/
}
void goForwardSession(){

View File

@ -64,6 +64,11 @@ public class hintAdapter extends RecyclerView.Adapter<hintAdapter.listViewHolder
public void onUpdateAdapter(ArrayList<historyRowModel> pHintList, String pSearch){
mHintList = pHintList;
if(mHintList.size()==1 && mHintList.get(0).getHeader().equals("about:blank")) {
mHintList.clear();
mHintList.add( new historyRowModel("Genesis Search", "genesis.onion",-1));
}
notifyDataSetChanged();
}

View File

@ -1,7 +1,10 @@
package com.darkweb.genesissearchengine.appManager.homeManager.homeController;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.DownloadManager;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2;
@ -14,7 +17,6 @@ import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.net.Uri;
import android.net.VpnService;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
@ -29,6 +31,7 @@ import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.webkit.URLUtil;
import android.widget.*;
import androidx.annotation.NonNull;
@ -44,6 +47,7 @@ import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.darkweb.genesissearchengine.appManager.activityContextManager;
import com.darkweb.genesissearchengine.appManager.bookmarkManager.bookmarkController;
import com.darkweb.genesissearchengine.constants.sql;
import com.darkweb.genesissearchengine.databaseManager.databaseController;
import com.darkweb.genesissearchengine.appManager.historyManager.historyController;
import com.darkweb.genesissearchengine.appManager.historyManager.historyRowModel;
@ -81,10 +85,11 @@ import com.google.android.gms.ads.AdView;
import org.mozilla.geckoview.ContentBlocking;
import org.mozilla.geckoview.GeckoResult;
import org.mozilla.geckoview.GeckoSession;
import org.mozilla.geckoview.GeckoView;
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.wrapper.LocaleHelper;
import org.torproject.android.service.wrapper.orbotLocalConstants;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@ -95,15 +100,18 @@ import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.concurrent.Callable;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static com.darkweb.genesissearchengine.constants.constants.CONST_GENESIS_HELP_URL_CACHE;
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.GECKO_SCROLL_CHANGED;
import static com.darkweb.genesissearchengine.constants.enums.etype.GECKO_SCROLL_DOWN;
import static com.darkweb.genesissearchengine.constants.enums.etype.M_INITIALIZE_TAB_LINK;
import static com.darkweb.genesissearchengine.constants.enums.etype.M_INITIALIZE_TAB_SINGLE;
import static com.darkweb.genesissearchengine.constants.enums.etype.M_NEW_LINK_IN_NEW_TAB;
import static com.darkweb.genesissearchengine.constants.enums.etype.open_new_tab;
import static com.darkweb.genesissearchengine.constants.enums.etype.reload;
import static com.darkweb.genesissearchengine.pluginManager.pluginEnums.eMessageManager.*;
import static com.darkweb.genesissearchengine.pluginManager.pluginEnums.eMessageManagerCallbacks.M_RATE_APPLICATION;
import static java.lang.Character.isLetter;
@ -210,6 +218,8 @@ public class homeController extends AppCompatActivity implements ComponentCallba
initAdmob();
initWidget();
initSuggestionView(new ArrayList<>(), strings.GENERIC_EMPTY_STR);
status.sSettingIsAppRunning = true;
org.torproject.android.service.util.Prefs.setContext(activityContextManager.getInstance().getHomeController());
}
@ -218,7 +228,6 @@ public class homeController extends AppCompatActivity implements ComponentCallba
if(!status.sSettingIsAppStarted){
if(mSplashScreen.getAlpha()==1 && mConnectButton.isEnabled()){
onStartApplication(null);
status.sWidgetResponse = enums.WidgetResponse.NONE;
}
}else {
mHomeViewController.initSearchBarFocus(false, isKeyboardOpened);
@ -236,7 +245,6 @@ public class homeController extends AppCompatActivity implements ComponentCallba
if(!status.sSettingIsAppStarted){
if(mSplashScreen.getAlpha()==1 && mConnectButton.isEnabled()){
onStartApplication(null);
status.sWidgetResponse = enums.WidgetResponse.NONE;
}
}else {
if(mSearchEngineBar.getVisibility() != View.VISIBLE){
@ -328,7 +336,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
}
onLoadTab(model.getSession(),false,true);
//onLoadURL(model.getSession().getCurrentURL());
mGeckoClient.onReload(mGeckoView, this);
//mGeckoClient.onReload(mGeckoView, this);
}else {
onNewIntent(getIntent());
onOpenLinkNewTab(helperMethod.getDomainName(mHomeModel.getSearchEngine()));
@ -465,7 +473,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
public boolean dispatchTouchEvent(MotionEvent event) {
if(inSignatureArea(event)){
try{
mSwipeDirectionDetector.onTouchEvent(event);
//mSwipeDirectionDetector.onTouchEvent(event);
}catch (Exception ignored){ }
}
return super.dispatchTouchEvent(event);
@ -558,6 +566,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
}
public void onLoadURL(String url){
status.sUIInteracted = true;
if(mGeckoView.getSession()!=null && !mGeckoView.getSession().isOpen()){
mGeckoView.getSession().open(mGeckoClient.getmRuntime());
}
@ -608,7 +617,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
}catch (Exception ignored){}
if(pExpandAppBar){
mHomeViewController.expandTopBar();
mHomeViewController.expandTopBar(false, mGeckoView.getMaxY());
}
if(mGeckoClient.getSession().getCurrentURL().equals("about:blank") || mGeckoClient.getSession().getCurrentURL().contains("boogle.store") || mGeckoClient.wasPreviousErrorPage() || mGeckoClient.getSession().getCurrentURL().startsWith(CONST_GENESIS_URL_CACHED) || mGeckoClient.getSession().getCurrentURL().startsWith(CONST_GENESIS_URL_CACHED_DARK) || mGeckoClient.getSession().getCurrentURL().startsWith(CONST_GENESIS_HELP_URL_CACHE) || mGeckoClient.getSession().getCurrentURL().startsWith(CONST_GENESIS_HELP_URL_CACHE_DARK)){
@ -704,15 +713,18 @@ public class homeController extends AppCompatActivity implements ComponentCallba
@SuppressLint("ClickableViewAccessibility")
@Override
protected void onDestroy() {
pluginController.getInstance().onOrbotInvoke(null, pluginEnums.eOrbotManager.M_DESTROY);
mBackSplash.setImageDrawable(null);
mBackSplash.setBackground(null);
if(!status.mThemeApplying){
if(!status.sSettingIsAppStarted){
Intent intent = new Intent(getApplicationContext(), OrbotService.class);
stopService(intent);
}else {
NotificationManagerCompat.from(this).cancelAll();
}
}
KeyboardUtils.removeAllKeyboardToggleListeners();
mGatewaySplash.setOnTouchListener(null);
@ -755,6 +767,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
mNewTab.setOnTouchListener((v, event) -> {
if(event.getAction() == MotionEvent.ACTION_DOWN){
mTopBarContainer.getLayoutTransition().setDuration(200);
onOpenTabViewBoundary(null);
mNewTab.setPressed(true);
}
@ -811,17 +824,19 @@ public class homeController extends AppCompatActivity implements ComponentCallba
mGeckoView.setOnTouchListener((v, event) -> {
mHomeViewController.onClearSelections(true);
if (event.getAction() == MotionEvent.ACTION_DOWN)
if (event.getAction() == MotionEvent.ACTION_DOWN){
mGatewaySplash.setElevation(9);
status.sUIInteracted = true;
}
else if (event.getAction() == MotionEvent.ACTION_UP){
int[] location = new int[2];
mTopLayout.getLocationOnScreen(location);
int y = location[1];
if(status.sFullScreenBrowsing){
if(y<=-helperMethod.pxFromDp(6)){
mAppBar.setExpanded(false,true);
//mAppBar.setExpanded(false,true);
}else {
mAppBar.setExpanded(true,true);
//mAppBar.setExpanded(true,true);
}
}
}
@ -910,6 +925,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
mSearchbar.setEventHandler(new edittextManagerCallback());
mSearchbar.setOnFocusChangeListener((v, hasFocus) -> {
status.sUIInteracted = true;
if(!hasFocus)
{
mSearchBarWasBackButtonPressed = true;
@ -986,9 +1002,8 @@ public class homeController extends AppCompatActivity implements ComponentCallba
public void onSearchBarInvoked(View view){
String url = ((EditText)view).getText().toString();
String validated_url = mHomeModel.urlComplete(url, mHomeModel.getSearchEngine());
if(validated_url!=null){
url = validated_url;
}
mHomeViewController.onUpdateSearchBar(url,false,true, false);
onLoadURL(url);
}
@ -999,13 +1014,15 @@ public class homeController extends AppCompatActivity implements ComponentCallba
mVal = ((TextView)view.findViewById(R.id.pHeaderSingle)).getText().toString();
}
String pURL = mHomeModel.urlComplete(mVal, status.sSettingSearchStatus);
if(pURL==null){
pURL = mVal;
}
mHomeViewController.onClearSelections(true);
onLoadURL(pURL);
mHomeViewController.onUpdateSearchBar(pURL,false,true, true);
String finalPURL = pURL;
new Handler().postDelayed(() ->
{
onLoadURL(finalPURL);
}, 250);
}
public void onSuggestionMove(View view){
@ -1169,12 +1186,16 @@ public class homeController extends AppCompatActivity implements ComponentCallba
mHomeViewController.onNewTabAnimation(Arrays.asList(isKeyboardOpenedTemp, isKeyboardOpened), M_INITIALIZE_TAB_SINGLE);
}
public String completeURL(String pURL){
return mHomeModel.urlComplete(pURL, mHomeModel.getSearchEngine());
}
public void onOpenLinkNewTab(String url){
mNewTab.setPressed(true);
final Handler handler = new Handler();
handler.postDelayed(() -> {
onGetThumbnail(null, false);
mHomeViewController.expandTopBar();
mHomeViewController.expandTopBar(false,mGeckoView.getMaxY());
if(status.sSettingSearchStatus.startsWith("https://boogle.store") || !status.sOpenURLInNewTab){
mHomeViewController.updateBannerAdvertStatus(false, (boolean)pluginController.getInstance().onAdsInvoke(null, pluginEnums.eAdManager.M_IS_ADVERT_LOADED));
}
@ -1182,11 +1203,16 @@ public class homeController extends AppCompatActivity implements ComponentCallba
}, 100);
}
public void onClearSelectionTab(){
mNewTab.setPressed(false);
}
public void onOpenTabViewBoundary(View view){
onInvokePixelGenerator();
if(mScrollHandler!=null){
mScrollHandler.removeCallbacksAndMessages(null);
}
onInvokePixelGenerator();
mNewTab.setPressed(true);
onOpenTabReady();
}
@ -1218,7 +1244,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
initLocalLanguage();
helperMethod.hideKeyboard(this);
mHomeViewController.onOpenMenu(view,mGeckoClient.canGoForward(),!(mProgressBar.getAlpha()<=0 || mProgressBar.getVisibility() ==View.INVISIBLE),mGeckoClient.getUserAgent(), mGeckoClient.getSession().getCurrentURL());
mHomeViewController.onOpenMenu(view,mGeckoClient.canGoForward(),!(mProgressBar.getAlpha()<=0 || mProgressBar.getVisibility() == View.INVISIBLE || mGeckoClient.isLoaded()),mGeckoClient.getUserAgent(), mGeckoClient.getSession().getCurrentURL());
view.setClickable(false);
new Handler().postDelayed(() ->
@ -1271,14 +1297,18 @@ public class homeController extends AppCompatActivity implements ComponentCallba
}
else if(!mSearchBarWasBackButtonPressed){
int mTabSize = (int)dataController.getInstance().invokeTab(dataEnums.eTabCommands.GET_TOTAL_TAB, null);
mGeckoClient.onBackPressed(true, mTabSize);
mGeckoClient.onBackPressed(true, mTabSize, mGeckoView, this);
}
}
/*Activity States*/
public NestedGeckoView getGeckoView(){
return mGeckoView;
}
public void onReload(View view){
mHomeViewController.onUpdateLogo();
onLoadURL(mSearchbar.getText().toString());
}
public void onClearSession(){
@ -1337,7 +1367,12 @@ public class homeController extends AppCompatActivity implements ComponentCallba
pluginController.getInstance().onLanguageInvoke(Collections.singletonList(this), pluginEnums.eLangManager.M_RESUME);
mHomeViewController.onClearSelections(true);
mHomeViewController.onUpdateSearchBar(mGeckoClient.getSession().getCurrentURL(),false,true, true);
mHomeViewController.initTopBarPadding();
mHomeViewController.onSetBannerAdMargin(!mGeckoClient.isLoading(),(boolean)pluginController.getInstance().onAdsInvoke(null, pluginEnums.eAdManager.M_IS_ADVERT_LOADED)&&!!mGeckoClient.isLoading());
mHomeViewController.expandTopBar(false, mGeckoView.getMaxY());
status.sUIInteracted = true;
}
@Override
@ -1362,6 +1397,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
pluginController.getInstance().onMessageManagerInvoke(null, M_RESET);
pluginController.getInstance().onNotificationInvoke(Collections.singletonList(1296000000) , pluginEnums.eNotificationManager.M_CREATE_NOTIFICATION);
mSearchBarWasBackButtonPressed = false;
status.sUIInteracted = true;
}
@Override
@ -1403,7 +1439,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
}
if(mAppBar!=null){
mHomeViewController.expandTopBar();
mHomeViewController.expandTopBar(false, mGeckoView.getMaxY());
mAppBar.refreshDrawableState();
mAppBar.invalidate();
@ -1473,7 +1509,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
}
if(mAppBar!=null){
mHomeViewController.expandTopBar();
mHomeViewController.expandTopBar(false, mGeckoView.getMaxY());
mAppBar.refreshDrawableState();
mAppBar.invalidate();
@ -1512,7 +1548,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
}
public void onVoiceClick(View view) {
if(status.sSettingEnableVoiceInput){
if(status.sSettingEnableVoiceInput || status.sWidgetResponse == enums.WidgetResponse.VOICE){
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault());
@ -1523,7 +1559,11 @@ public class homeController extends AppCompatActivity implements ComponentCallba
}
}else {
mHomeViewController.onClearSelections(true);
mSearchbar.clearFocus();
new Handler().postDelayed(() ->
{
mHomeViewController.onUpdateSearchBar(mGeckoClient.getSession().getCurrentURL(),false,true, false);
}, 170);
}
}
/*-------------------------------------------------------External Callback Methods-------------------------------------------------------*/
@ -1705,6 +1745,10 @@ public class homeController extends AppCompatActivity implements ComponentCallba
pluginController.getInstance().onMessageManagerInvoke(Collections.singletonList(this), M_REPORT_URL);
}
else if (menuId == R.id.pMenuQuit)
{
pluginController.getInstance().onOrbotInvoke(null, pluginEnums.eOrbotManager.M_DESTROY);
new Handler().postDelayed(() ->
{
status.sSettingIsAppStarted = false;
finishAndRemoveTask();
@ -1720,6 +1764,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
}
}
}.start();
}, 100);
}
else if (menuId == R.id.pMenuFind)
{
@ -1727,8 +1772,9 @@ public class homeController extends AppCompatActivity implements ComponentCallba
mHomeViewController.onUpdateFindBar(true);
}
if (menuId == R.id.menu20) {
mGeckoClient.onClose();
mHomeViewController.onUpdateSearchBar(mGeckoClient.getSession().getCurrentURL(),false,true, true);
helperMethod.hideKeyboard(this);
mGeckoClient.onStop();
}
if (menuId == R.id.menu21) {
helperMethod.hideKeyboard(this);
@ -1815,6 +1861,8 @@ public class homeController extends AppCompatActivity implements ComponentCallba
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_HISTORY_CLEAR,true));
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_GATEWAY,true));
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_GATEWAY_MANUAL,false));
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_IS_WELCOME_ENABLED,true));
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.PROXY_IS_APP_RATED,false));
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.VPN_ENABLED,false));
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.BRIDGE_ENABLES,false));
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_FONT_ADJUSTABLE,true));
@ -1839,22 +1887,40 @@ public class homeController extends AppCompatActivity implements ComponentCallba
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));
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_OPEN_URL_IN_NEW_TAB,true));
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_POPUP,true));
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_STRING, Arrays.asList(keys.BRIDGE_CUSTOM_TYPE,strings.BRIDGE_CUSTOM_BRIDGE_OBFS4));
dataController.getInstance().invokeTab(dataEnums.eTabCommands.M_CLEAR_TAB, null);
databaseController.getInstance().execSQL(sql.SQL_CLEAR_HISTORY,null);
dataController.getInstance().invokeHistory(dataEnums.eHistoryCommands.M_CLEAR_HISTORY ,null);
activityContextManager.getInstance().getHomeController().onClearCache();
dataController.getInstance().invokeTab(dataEnums.eTabCommands.M_CLEAR_TAB, null);
activityContextManager.getInstance().getHomeController().onClearSiteData();
activityContextManager.getInstance().getHomeController().onClearSession();
activityContextManager.getInstance().getHomeController().onClearCookies();
onClearSettings();
status.initStatus(activityContextManager.getInstance().getHomeController());
dataController.getInstance().invokeTab(dataEnums.eTabCommands.M_CLEAR_TAB, null);
activityContextManager.getInstance().getHomeController().initRuntimeSettings();
pluginController.getInstance().onMessageManagerInvoke(Collections.singletonList(this), M_DATA_CLEARED);
activityContextManager.getInstance().getHomeController().onClearSettings();
status.sSettingIsAppStarted = false;
finishAndRemoveTask();
new Thread(){
public void run(){
try {
sleep(1000);
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(1);
} catch (InterruptedException e) {
e.printStackTrace();
Intent intent = new Intent(this, homeController.class);
intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
overridePendingTransition(R.anim.popup_anim_in, R.anim.popup_anim_out);
if (this
instanceof Activity) {
((Activity) this).finish();
}
}
}.start();
Runtime.getRuntime().exit(0);
}
public class nestedGeckoViewCallback implements eventObserver.eventListener{
@ -1862,9 +1928,24 @@ public class homeController extends AppCompatActivity implements ComponentCallba
@Override
public Object invokeObserver(List<Object> data, Object e_type)
{
if(e_type.equals(GECKO_SCROLL_CHANGED)){
mHomeViewController.onMoveTopBar((int)data.get(0));
onInvokePixelGenerator();
if(status.sFullScreenBrowsing){
if(e_type.equals(GECKO_SCROLL_DOWN)){
mTopBarContainer.getLayoutTransition().setDuration(0);
mHomeViewController.onClearSelections(isKeyboardOpened);
mSearchbar.clearFocus();
}
else {
int[] locatiosn = new int[2];
mSearchbar.getLocationOnScreen(locatiosn);
int ys = locatiosn[1];
if(ys!=0){
if(ys<=50){
mHomeViewController.shrinkTopBar(true, mGeckoView.getMaxY());
}else {
mHomeViewController.expandTopBar(true, mGeckoView.getMaxY());
}
}
}
}
return null;
}
@ -1929,11 +2010,23 @@ public class homeController extends AppCompatActivity implements ComponentCallba
{
mHomeViewController.onSetBannerAdMargin((boolean)data.get(0),(boolean)pluginController.getInstance().onAdsInvoke(null, pluginEnums.eAdManager.M_IS_ADVERT_LOADED));
}
else if(e_type.equals(enums.etype.M_SPLASH_DISABLE))
{
initWidget();
}
else if(e_type.equals(enums.etype.M_WELCOME_MESSAGE)){
if(status.sSettingIsWelcomeEnabled){
final Handler handler = new Handler();
Runnable runnable = () -> pluginController.getInstance().onMessageManagerInvoke(Arrays.asList(strings.GENERIC_EMPTY_STR, homeController.this), M_WELCOME);
handler.postDelayed(runnable, 1300);
Runnable runnable = () -> {
if(!status.sUIInteracted){
mHomeViewController.closeMenu();
mHomeViewController.onUpdateSearchBar(mGeckoClient.getSession().getCurrentURL(),false,true, true);
mSearchbar.clearFocus();
pluginController.getInstance().onMessageManagerInvoke(Arrays.asList(strings.GENERIC_EMPTY_STR, homeController.this), M_WELCOME);
status.sUIInteracted = true;
}
};
handler.postDelayed(runnable, 2500);
}
}
else if(e_type.equals(enums.etype.on_url_load)){
@ -2091,7 +2184,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
{
if(e_type.equals(enums.etype.ON_EXPAND_TOP_BAR)){
mHomeViewController.expandTopBar();
mHomeViewController.expandTopBar(false, mGeckoView.getMaxY());
}
else if(e_type.equals(enums.etype.M_ON_BANNER_UPDATE)){
Object mAdvertResponse = pluginController.getInstance().onAdsInvoke(null, pluginEnums.eAdManager.M_IS_ADVERT_LOADED);
@ -2203,6 +2296,9 @@ public class homeController extends AppCompatActivity implements ComponentCallba
if(activityContextManager.getInstance().getTabController()!=null && mTabFragment.getVisibility()==View.VISIBLE)
activityContextManager.getInstance().getTabController().onTabRowChanged((String) data.get(1));
}
else if(e_type.equals(enums.etype.M_RELOAD)){
onReload(null);
}
else if(e_type.equals(enums.etype.M_UPDATE_SESSION_STATE)){
dataController.getInstance().invokeTab(dataEnums.eTabCommands.M_UPDATE_SESSION_STATE, data);
}
@ -2222,6 +2318,9 @@ public class homeController extends AppCompatActivity implements ComponentCallba
else if(e_type.equals(enums.etype.M_UPDATE_PIXEL_BACKGROUND)){
onInvokePixelGenerator();
}
else if(e_type.equals(enums.etype.M_INIT_PADDING)){
mHomeViewController.initTopBarPadding();
}
return null;
}

View File

@ -28,7 +28,7 @@ class homeModel
boolean isUrlValid = Patterns.WEB_URL.matcher(updateUrl).matches();
if(isUrlValid && host.getHost().replace("www.","").contains("."))
{
return null;
return pURL;
}
}

View File

@ -17,6 +17,7 @@ import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.InsetDrawable;
import android.graphics.drawable.StateListDrawable;
import android.os.Build;
import android.os.Debug;
import android.os.Handler;
import android.os.Message;
import android.text.method.MovementMethod;
@ -49,7 +50,7 @@ import com.example.myapplication.R;
import com.google.android.gms.ads.AdView;
import com.google.android.material.appbar.AppBarLayout;
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;
@ -118,6 +119,7 @@ class homeViewController
private MovementMethod mSearchBarMovementMethod = null;
private Handler mTabDialogHandler = null;
private Runnable mTabDialogRunnable = null;
private boolean mIsTopBarExpanded = true;
void initialization(eventObserver.eventListener event, AppCompatActivity context, Button mNewTab, ConstraintLayout webviewContainer, TextView loadingText, AnimatedProgressBar progressBar, editTextManager searchbar, ConstraintLayout splashScreen, ImageView loading, AdView banner_ads, ImageButton gateway_splash, LinearLayout top_bar, GeckoView gecko_view, ImageView backsplash, Button connect_button, View pFindBar, EditText pFindText, TextView pFindCount, androidx.constraintlayout.widget.ConstraintLayout pTopLayout, ImageButton pVoiceInput, ImageButton pMenu, androidx.core.widget.NestedScrollView pNestedScroll, ImageView pBlocker, ImageView pBlockerFullSceen, View mSearchEngineBar, TextView pCopyright, RecyclerView pHistListView, com.google.android.material.appbar.AppBarLayout pAppBar, ImageButton pOrbotLogManager, ConstraintLayout pInfoLandscape, ConstraintLayout pInfoPortrait, ProgressBar pProgressBarIndeterminate, FragmentContainerView pTabFragment, LinearLayout pTopBarContainer, ImageView pSearchLock, View pPopupLoadNewTab, ImageView pTopBarHider, ImageView pNewTabBlocker, CoordinatorLayout mCoordinatorLayout, ImageView pImageDivider, ImageButton pPanicButton, ImageView pGenesisLogo,ImageButton pPanicButtonLandscape){
this.mContext = context;
@ -179,13 +181,10 @@ class homeViewController
mTopBarContainer.getLayoutTransition().setDuration(200);
final Handler handler = new Handler();
handler.postDelayed(() ->
{
mContext.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER);
}, 1500);
handler.postDelayed(() -> mContext.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER), 1500);
updateBannerAdvertStatus(false, false);
expandTopBar();
expandTopBar(false, 2000);
mBlockerFullSceen.setVisibility(View.GONE);
mNewTab.setPressed(true);
mNewTab.setPressed(false);
@ -194,6 +193,7 @@ class homeViewController
View child = mAppBar.getChildAt(0);
AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) child.getLayoutParams();
params.setScrollFlags(1);
mIsTopBarExpanded = false;
mAppBar.setExpanded(true,false);
mAppBar.refreshDrawableState();
mAppBar.invalidate();
@ -274,7 +274,7 @@ class homeViewController
mPopupLoadNewTab.animate().cancel();
mPopupLoadNewTab.setAlpha(0);
mPopupLoadNewTab.setVisibility(View.VISIBLE);
mPopupLoadNewTab.animate().setDuration(350).alpha(1);
mPopupLoadNewTab.animate().setStartDelay(400).setDuration(250).alpha(1);
if(mTabDialogHandler!=null){
mTabDialogHandler.removeCallbacksAndMessages(null);
@ -282,14 +282,14 @@ class homeViewController
mTabDialogHandler = new Handler();
mTabDialogRunnable = this::onHideLoadTabDialog;
mTabDialogHandler.postDelayed(mTabDialogRunnable, 7500);
mTabDialogHandler.postDelayed(mTabDialogRunnable, 3500);
}
public void onHideLoadTabDialog() {
mPopupLoadNewTab.findViewById(R.id.pBlockerUndo).setVisibility(View.VISIBLE);
mPopupLoadNewTab.animate().cancel();
mPopupLoadNewTab.animate().setDuration(350).alpha(0).withEndAction(() -> {
mPopupLoadNewTab.animate().setDuration(250).alpha(0).withEndAction(() -> {
mPopupLoadNewTab.setVisibility(View.GONE);
});
}
@ -495,13 +495,13 @@ class homeViewController
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
animatedColor oneToTwo = new animatedColor(ContextCompat.getColor(mContext, R.color.landing_ease_blue), ContextCompat.getColor(mContext, R.color.green_dark_v2));
int mDelay = 800;
int mDelay = 1150;
if(status.mThemeApplying || mInstant){
mDelay = 0;
}
ValueAnimator animator = ObjectAnimator.ofFloat(0f, 1f);
animator.setDuration(300).setStartDelay(mDelay);
animator.setDuration(250).setStartDelay(mDelay);
animator.addUpdateListener(animation ->
{
float v = (float) animation.getAnimatedValue();
@ -647,20 +647,20 @@ class homeViewController
if(mSplashScreen.getAlpha()==1){
if(!mIsAnimating){
mIsAnimating = true;
triggerPostUI();
triggerPostUI(2000);
mProgressBar.setVisibility(View.GONE);
mSplashScreen.animate().cancel();
onClearSelections(false);
mGeckoView.requestFocus();
mProgressBarIndeterminate.animate().setStartDelay(300).setDuration(250).alpha(0).withEndAction(() -> mSplashScreen.animate().setDuration(350).setStartDelay(200).alpha(0).withEndAction(() -> {
mProgressBarIndeterminate.animate().cancel();
mProgressBarIndeterminate.animate().setStartDelay(750).setDuration(250).alpha(0).withEndAction(() -> {
mSplashScreen.animate().setDuration(250).setStartDelay(100).alpha(0).withEndAction(() -> {
mProgressBarIndeterminate.setVisibility(View.GONE);
mSplashScreen.setClickable(false);
mSplashScreen.setFocusable(false);
mProgressBarIndeterminate.setVisibility(View.GONE);
mSearchbar.setEnabled(true);
mBlocker.setEnabled(false);
mProgressBarIndeterminate.setVisibility(View.GONE);
mBlocker.setVisibility(View.GONE);
mGatewaySplash.setVisibility(View.GONE);
mConnectButton.setVisibility(View.GONE);
@ -669,7 +669,8 @@ class homeViewController
mEvent.invokeObserver(null, enums.etype.M_CACHE_UPDATE_TAB);
mEvent.invokeObserver(null, enums.etype.M_SPLASH_DISABLE);
}));
});
});
mEvent.invokeObserver(null, enums.etype.M_WELCOME_MESSAGE);
mOrbotLogManager.setClickable(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
@ -684,18 +685,79 @@ class homeViewController
mContext.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER);
}
private void triggerPostUI(){
expandTopBar();
private void triggerPostUI(int pOffsetY){
expandTopBar(false, pOffsetY);
if(mProgressBar.getProgress()>0 && mProgressBar.getProgress()<10000){
mProgressBar.animate().setStartDelay(0).alpha(1);
}
}
public void expandTopBar(){
public void disableExpand(){
View child = mAppBar.getChildAt(0);
AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) child.getLayoutParams();
params.setScrollFlags(0);
}
@SuppressLint("WrongConstant")
private void enableCollapsing() {
View child = mAppBar.getChildAt(0);
AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) child.getLayoutParams();
params.setScrollFlags(1);
}
public void expandTopBar(boolean pForced, int pOffsetY){
if(pOffsetY == -1){
mAppBar.setExpanded(true,true);
disableExpand();
}else {
enableCollapsing();
}
new Handler().postDelayed(() ->
{
mTopBarContainer.getLayoutTransition().setDuration(200);
Object mTag = mAppBar.getTag(R.id.expandableBar);
if(mIsTopBarExpanded && !pForced){
return;
}
if(mTag!=null && (boolean) mTag){
mAppBar.setExpanded(true,true);
mIsTopBarExpanded = true;
Log.i("wwwwww1","wwwwww");
}
}, 100);
}
public void shrinkTopBar(boolean pForced, int pOffsetY){
if(pOffsetY == -1){
mAppBar.setExpanded(true,true);
disableExpand();
}else {
enableCollapsing();
}
mTopBarContainer.getLayoutTransition().setDuration(0);
new Handler().postDelayed(() ->
{
mTopBarContainer.getLayoutTransition().setDuration(200);
Object mTag = mAppBar.getTag(R.id.expandableBar);
if(!mIsTopBarExpanded && !pForced){
return;
}
if(mTag!=null && (boolean) mTag){
mIsTopBarExpanded = false;
mAppBar.setExpanded(false,true);
Log.i("wwwwww2","wwwwww");
}
}, 100);
}
/*-------------------------------------------------------Helper Methods-------------------------------------------------------*/
@ -867,15 +929,8 @@ class homeViewController
mSearchbar.setTag(R.id.msearchbarProcessing,true);
url = CONST_GENESIS_DOMAIN_URL;
}
else if(url.startsWith(CONST_GENESIS_HELP_URL_CACHE) || url.startsWith(CONST_GENESIS_HELP_URL_CACHE_DARK)){
mSearchbar.setTag(R.id.msearchbarProcessing,true);
url = CONST_GENESIS_HELP_URL;
}
else if(helperMethod.getHost(helperMethod.completeURL(url)).contains("genesis") || helperMethod.getHost(helperMethod.completeURL(url)).contains("boogle")){
mSearchbar.setTag(R.id.msearchbarProcessing,true);
}else {
mSearchbar.setTag(R.id.msearchbarProcessing,false);
}
Log.i("FUCK::5",url);
if(!mSearchbar.hasFocus() || pClearText || pBypassFocus){
if(mSearchEngineBar.getVisibility() == View.GONE || pBypassFocus){
@ -1010,7 +1065,7 @@ class homeViewController
mNewTab.setTextColor(ContextCompat.getColor(mContext, R.color.c_text_v1));
mMenu.setColorFilter(ContextCompat.getColor(mContext, R.color.c_navigation_tint));
mVoiceInput.setColorFilter(ContextCompat.getColor(mContext, R.color.c_navigation_tint));
mVoiceInput.setColorFilter(ContextCompat.getColor(mContext, R.color.c_text_v8));
mSearchbar.setTextColor(ContextCompat.getColor(mContext, R.color.c_text_v1));
mSearchbar.setHintTextColor(ContextCompat.getColor(mContext, R.color.c_text_v2));
@ -1352,6 +1407,8 @@ class homeViewController
this.mBlockerFullSceen.animate().setStartDelay(0).setDuration(200).alpha(0).withEndAction(() -> mBlockerFullSceen.setVisibility(View.GONE));
mContext.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
initTopBarPadding();
mIsTopBarExpanded = false;
mAppBar.setExpanded(true,false);
mAppBar.refreshDrawableState();
mAppBar.invalidate();

View File

@ -15,7 +15,7 @@ import com.darkweb.genesissearchengine.appManager.activityContextManager;
import com.darkweb.genesissearchengine.appManager.tabManager.tabEnums;
import com.darkweb.genesissearchengine.helperManager.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;

View File

@ -24,7 +24,7 @@ import com.darkweb.genesissearchengine.pluginManager.pluginController;
import com.darkweb.genesissearchengine.pluginManager.pluginEnums;
import com.example.myapplication.R;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import org.torproject.android.proxy.wrapper.orbotLocalConstants;
import org.torproject.android.service.wrapper.orbotLocalConstants;
import java.util.Collections;
import java.util.List;

View File

@ -2,7 +2,7 @@ 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;
class orbotLogModel

View File

@ -2,6 +2,7 @@ package com.darkweb.genesissearchengine.appManager.settingManager.accessibilityM
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.SeekBar;
import android.widget.TextView;
@ -171,6 +172,12 @@ public class settingAccessibilityController extends AppCompatActivity {
mSettingAccessibilityModel.onTrigger(settingAccessibilityEnums.eAccessibilityViewController.M_ZOOM_SETTING, Collections.singletonList(!mZoom.isChecked()));
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_ZOOM,status.sSettingEnableZoom));
mZoom.toggle();
new Handler().postDelayed(() ->
{
activityContextManager.getInstance().getHomeController().onReload(null);
}, 300);
}
public void onVoiceInputSettingUpdate(View view){

View File

@ -8,8 +8,10 @@ import android.widget.CheckBox;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.core.content.ContextCompat;
import com.darkweb.genesissearchengine.appManager.activityContextManager;
import com.darkweb.genesissearchengine.appManager.settingManager.generalManager.settingGeneralController;
import com.darkweb.genesissearchengine.databaseManager.databaseController;
import com.darkweb.genesissearchengine.appManager.helpManager.helpController;
import com.darkweb.genesissearchengine.constants.constants;
@ -160,9 +162,25 @@ public class settingClearController extends AppCompatActivity {
if(mHomeInvoked){
activityContextManager.getInstance().getHomeController().onClearSettings();
}
}
private void onClearSettings(){
boolean mIsThemeChangable = false;
if(!status.sDefaultNightMode){
if(AppCompatDelegate.getDefaultNightMode() != AppCompatDelegate.MODE_NIGHT_NO){
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
mIsThemeChangable = true;
}
}else {
if(AppCompatDelegate.getDefaultNightMode() != AppCompatDelegate.MODE_NIGHT_YES){
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
mIsThemeChangable = true;
}
}
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_SEARCH_HISTORY,true));
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_SEARCH_SUGGESTION,true));
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_JAVA_SCRIPT,true));
@ -197,6 +215,15 @@ public class settingClearController extends AppCompatActivity {
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_OPEN_URL_IN_NEW_TAB,true));
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_POPUP,true));
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_STRING, Arrays.asList(keys.BRIDGE_CUSTOM_TYPE,strings.BRIDGE_CUSTOM_BRIDGE_OBFS4));
if(mIsThemeChangable) {
status.mThemeApplying = true;
onBackPressed();
overridePendingTransition(R.anim.fade_in_lang, R.anim.fade_out_lang);
activityContextManager.getInstance().getHomeController().onReInitTheme();
activityContextManager.getInstance().getSettingController().onReInitTheme();
helperMethod.openActivity(settingClearController.class, constants.CONST_LIST_HISTORY, settingClearController.this, true);
}
}
/* LOCAL OVERRIDES */

View File

@ -356,7 +356,9 @@ public class tabController extends Fragment
onClearSelection(null);
}
initTabCount(400);
new Handler().postDelayed(() -> {
activityContextManager.getInstance().getHomeController().onLoadTabFromTabController();
}, 500);
mTabAdapter.onTrigger(tabEnums.eTabAdapterCommands.INIT_FIRST_ROW, null);
onSwipeBounce(0);
}
@ -375,19 +377,19 @@ public class tabController extends Fragment
mTabAdapter.notifyDataSetChanged();
onClearSelection(null);
});
activityContextManager.getInstance().getHomeController().onLoadTabFromTabController();
new Handler().postDelayed(() -> {
activityContextManager.getInstance().getHomeController().onLoadTabFromTabController();
onSwipeBounce(0);
}, 400);
}, 500);
return true;
}else{
onShowUndoDialog();
mTabAdapter.notifyItemRangeChanged(pIndex, mTabAdapter.getItemCount() - pIndex);
mTabAdapter.notifyItemChanged(0);
activityContextManager.getInstance().getHomeController().onLoadTabFromTabController();
new Handler().postDelayed(() -> {
activityContextManager.getInstance().getHomeController().onLoadTabFromTabController();
onSwipeBounce(0);
}, 400);
}, 500);
return true;
}
}
@ -435,7 +437,10 @@ public class tabController extends Fragment
mtabViewController.onTrigger(tabEnums.eTabViewCommands.ON_HIDE_UNDO_DIALOG, null);
mTabAdapter.onTrigger(tabEnums.eTabAdapterCommands.REINIT_DATA, Collections.singletonList(mBackup));
}
new Handler().postDelayed(() -> {
activityContextManager.getInstance().getHomeController().onLoadTabFromTabController();
}, 500);
}, 100);
}
@ -498,7 +503,9 @@ public class tabController extends Fragment
mtabViewController.onTrigger(tabEnums.eTabViewCommands.ON_SHOW_SELECTION_MENU, Arrays.asList(false,0));
mtabViewController.onTrigger(tabEnums.eTabViewCommands.ON_HIDE_SELECTION, null);
new Handler().postDelayed(() -> {
activityContextManager.getInstance().getHomeController().onLoadTabFromTabController();
}, 500);
// mTabAdapter.notifyDataSetChanged();
initTabCount(400);

View File

@ -4,7 +4,7 @@ public class enums
{
/*Settings Manager*/
public enum etype{
on_update_favicon,ON_UPDATE_TAB_TITLE, ON_OPEN_TAB_VIEW,ON_NEW_TAB_ANIMATION, M_UPDATE_SESSION_STATE,ON_LOAD_REQUEST,GECKO_SCROLL_CHANGED,ON_UPDATE_SEARCH_BAR,M_ON_MAIL,SESSION_ID,M_UPDATE_PIXEL_BACKGROUND,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, GECKO_SCROLL_DOWN_CALLER,ON_UPDATE_SEARCH_BAR,M_ON_MAIL,SESSION_ID,M_UPDATE_PIXEL_BACKGROUND, M_INIT_PADDING,M_CACHE_UPDATE_TAB,
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,

View File

@ -33,6 +33,7 @@ public class status
public static String sExternalWebsite = strings.GENERIC_EMPTY_STR;
public static String sBridgesDefault = strings.BRIDGES_DEFAULT;
public static boolean sUIInteracted = false;
public static boolean sSettingEnableZoom = true;
public static boolean sSettingEnableVoiceInput = true;
public static boolean sSettingSearchHistory = false;
@ -43,6 +44,7 @@ public class status
public static boolean sSettingIsAppPaused = false;
public static boolean sSettingIsWelcomeEnabled = true;
public static boolean sSettingIsAppStarted = false;
public static boolean sSettingIsAppRunning = false;
public static boolean sSettingIsAppRedirected = false;
public static boolean sSettingIsAppRestarting = false;
public static boolean sSettingIsAppRated = false;
@ -88,6 +90,7 @@ public class status
{
versionVerifier(pContext);
status.sUIInteracted = false;
status.sSettingSearchHistory = (boolean)dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_GET_BOOL, Arrays.asList(keys.SETTING_SEARCH_HISTORY,true));
status.sSearchSuggestionStatus = (boolean)dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_GET_BOOL, Arrays.asList(keys.SETTING_SEARCH_SUGGESTION,true));
status.sSettingJavaStatus = (boolean)dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_GET_BOOL, Arrays.asList(keys.SETTING_JAVA_SCRIPT,true));

View File

@ -109,6 +109,10 @@ public class suggestionDataModel implements SpellCheckerSession.SpellCheckerSess
}
}
if(mCurrentList.size()<=0) {
mCurrentList.add( mSize,new historyRowModel("Genesis Search", "genesis.onion",-1));
}
return mCurrentList;
}

View File

@ -50,7 +50,7 @@ public class databaseController
/*Initializations*/
public void prepareDatabaseEnvironment(AppCompatActivity app_context) {
File databaseFile = app_context.getDatabasePath(CONST_DATABASE_NAME);
File databaseFile = app_context.getDatabasePath(CONST_DATABASE_NAME + "_SECURE");
if (!databaseFile.exists()) {
databaseFile.getParentFile().mkdirs();
@ -63,7 +63,7 @@ public class databaseController
{
SQLiteDatabase.loadLibs(app_context);
prepareDatabaseEnvironment(app_context);
mDatabaseInstance = mDatabaseInstance.openOrCreateDatabase(app_context.getDatabasePath(CONST_DATABASE_NAME), constants.CONST_ENCRYPTION_KEY_DATABASE,null, wrapHook(null));
mDatabaseInstance = mDatabaseInstance.openOrCreateDatabase(app_context.getDatabasePath(CONST_DATABASE_NAME + "_SECURE"), constants.CONST_ENCRYPTION_KEY_DATABASE,null, wrapHook(null));
mDatabaseInstance.execSQL("CREATE TABLE IF NOT EXISTS " + "history" + " (id INT(4) PRIMARY KEY,date DATETIME,url VARCHAR,title VARCHAR);");
mDatabaseInstance.execSQL("CREATE TABLE IF NOT EXISTS " + "bookmark" + " (id INT(4) PRIMARY KEY,title VARCHAR,url VARCHAR);");
@ -159,22 +159,26 @@ public class databaseController
public ArrayList<tabRowModel> selectTabs(){
ArrayList<tabRowModel> mTempListModel = new ArrayList<>();
Cursor c = mDatabaseInstance.rawQuery("SELECT * FROM tab ORDER BY date DESC", null);
Cursor c = mDatabaseInstance.rawQuery("SELECT * FROM tab ORDER BY date ASC", null);
if (c.moveToFirst()){
do {
geckoSession mSession = activityContextManager.getInstance().getHomeController().onNewTabInit();
tabRowModel model = new tabRowModel(c.getString(0), c.getString(1),c.getBlob(4));
GeckoSession.SessionState session = null;
try {
if(status.sRestoreTabs){
// if(status.sRestoreTabs){
session = GeckoSession.SessionState.fromString(c.getString(6));
}
// }
} catch (Exception ex) {
ex.printStackTrace();
}
model.setSession(mSession, c.getString(3),c.getString(2), c.getString(5), session);
model.getSession().setSessionID(model.getmId());
if(session != null){
mTempListModel.add(0, model);
}else {
mTempListModel.add(model);
}
} while(c.moveToNext());
}
c.close();

View File

@ -10,29 +10,46 @@ import com.darkweb.genesissearchengine.appManager.homeManager.homeController.hom
import com.darkweb.genesissearchengine.constants.status;
import com.example.myapplication.R;
import org.torproject.android.service.wrapper.orbotLocalConstants;
public class externalNavigationController extends AppCompatActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Uri data = externalNavigationController.this.getIntent().getData();
if(data == null){
finish();
activityContextManager.getInstance().onClearStack();
Intent bringToForegroundIntent = new Intent(activityContextManager.getInstance().getHomeController(), homeController.class);
bringToForegroundIntent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(bringToForegroundIntent);
return;
}
if(status.sSettingIsAppStarted){
finish();
Uri data = externalNavigationController.this.getIntent().getData();
activityContextManager.getInstance().getHomeController().onOpenLinkNewTab(data.toString());
activityContextManager.getInstance().onClearStack();
final Handler handler = new Handler();
handler.postDelayed(() -> {
Intent launchIntent = getPackageManager().getLaunchIntentForPackage("com.darkweb.genesissearchengine");
startActivity(launchIntent);
new Handler().postDelayed(() ->
{
activityContextManager.getInstance().getHomeController().onOpenLinkNewTab(activityContextManager.getInstance().getHomeController().completeURL(data.toString()));
activityContextManager.getInstance().getHomeController().onClearSelectionTab();
}, 500);
Intent bringToForegroundIntent = new Intent(activityContextManager.getInstance().getHomeController(), homeController.class);
bringToForegroundIntent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(bringToForegroundIntent);
return;
}else if(status.sSettingIsAppRunning){
finish();
status.sExternalWebsite = data.toString();
return;
}
Intent intent = new Intent(this.getIntent());
intent.setClassName(this.getApplicationContext(), homeController.class.getName());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
Uri data = this.getIntent().getData();
if(data!=null){
if(activityContextManager.getInstance().getHomeController()!=null){
activityContextManager.getInstance().getHomeController().onOpenLinkNewTab(data.toString());

View File

@ -22,7 +22,11 @@ import android.widget.Toast;
import androidx.core.app.NotificationCompat;
import androidx.core.content.FileProvider;
import com.darkweb.genesissearchengine.appManager.activityContextManager;
import com.darkweb.genesissearchengine.netcipher.client.StrongHttpsClient;
import com.darkweb.genesissearchengine.pluginManager.pluginController;
import com.darkweb.genesissearchengine.pluginManager.pluginEnums;
import com.example.myapplication.R;
import org.mozilla.thirdparty.com.google.android.exoplayer2.util.Log;
import org.torproject.android.proxy.util.Prefs;
@ -37,6 +41,7 @@ import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Collections;
import ch.boye.httpclientandroidlib.HttpHost;
@ -196,10 +201,7 @@ public class localFileDownloader extends AsyncTask<String, Integer, String> {
} catch (Exception ex) {
Log.i("FIZZAHFUCK", ex.getMessage());
if(mRequestCode>300){
mEvent.invokeObserver(Collections.singletonList(mRequestCode), M_DOWNLOAD_FAILURE);
//Toast.makeText(context,"Request Forbidden Error Code : ",mRequestCode).show();
}
onCancel();
}
}else {
@ -260,9 +262,7 @@ public class localFileDownloader extends AsyncTask<String, Integer, String> {
output.close();
mStream.close();
}catch (Exception ex){
if(mRequestCode>300){
mEvent.invokeObserver(Collections.singletonList(mRequestCode), M_DOWNLOAD_FAILURE);
}
pluginController.getInstance().onMessageManagerInvoke(Arrays.asList(Collections.singletonList(mRequestCode), activityContextManager.getInstance().getHomeController()), pluginEnums.eMessageManager.M_DOWNLOAD_FAILURE);
onCancel();
}
}
@ -299,7 +299,7 @@ public class localFileDownloader extends AsyncTask<String, Integer, String> {
build.addAction(0, null, null);
build.setContentIntent(pendingIntent);
build.setContentText("Download complete");
build.setSmallIcon(R.xml.ic_check);
build.setSmallIcon(R.drawable.ic_download_complete);
build.setColor(Color.parseColor("#84989f"));
build.setProgress(0, 0, false);
build.setAutoCancel(true);

View File

@ -11,15 +11,12 @@ import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Build;
import androidx.core.app.NotificationCompat;
import androidx.core.content.ContextCompat;
import com.darkweb.genesissearchengine.appManager.activityContextManager;
import com.darkweb.genesissearchengine.constants.status;
import com.darkweb.genesissearchengine.constants.strings;
import com.example.myapplication.R;
import org.torproject.android.proxy.wrapper.orbotLocalConstants;
import java.util.Random;
public class userEngagementNotification extends BroadcastReceiver {

View File

@ -441,7 +441,6 @@ class messageManager
mDialog.dismiss();
}
});
mDialog.setOnDismissListener(dialog -> onClearReference());
}
private void downloadFileLongPress()
@ -565,7 +564,6 @@ class messageManager
};
handler.postDelayed(runnable, 1000);
});
mDialog.setOnDismissListener(dialog -> onClearReference());
}
void onReset(){

View File

@ -6,7 +6,7 @@ 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.wrapper.orbotLocalConstants;
import java.lang.ref.WeakReference;
import java.util.List;
@ -47,7 +47,7 @@ class orbotManager
orbotLocalConstants.mIsManualBridge = status.sBridgeGatewayManual;
orbotLocalConstants.mManualBridgeType = status.sBridgeCustomType;
Prefs.putBridgesEnabled(status.sBridgeStatus);
Intent mServiceIntent = new Intent(mAppContext.get(), OrbotService.class);
Intent mServiceIntent = new Intent(mAppContext.get().getApplicationContext(), OrbotService.class);
mServiceIntent.setAction(ACTION_START);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mAppContext.get().getApplicationContext().startForegroundService(mServiceIntent);
@ -200,6 +200,12 @@ class orbotManager
return OrbotService.getServiceObject().getProxyStatus();
}
private void onDestroy(){
if(!status.mThemeApplying) {
OrbotService.getServiceObject().onDestroy();
}
}
/*External Triggers*/
Object onTrigger(List<Object> pData, pluginEnums.eOrbotManager pEventType) {
@ -263,6 +269,10 @@ class orbotManager
{
newCircuit();
}
else if(pEventType.equals(pluginEnums.eOrbotManager.M_DESTROY))
{
onDestroy();
}
return null;
}

View File

@ -1,5 +1,8 @@
package com.darkweb.genesissearchengine.pluginManager;
import android.os.Handler;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
import com.darkweb.genesissearchengine.appManager.activityContextManager;
import com.darkweb.genesissearchengine.appManager.homeManager.homeController.homeController;
@ -203,7 +206,10 @@ public class pluginController
((homeController)mHomeController.get()).onLoadURL(pData.get(0).toString());
}
else if(pEventType.equals(M_PANIC_RESET)){
new Handler().postDelayed(() ->
{
activityContextManager.getInstance().getHomeController().panicExitInvoked();
}, 300);
}
else if(pEventType.equals(M_DOWNLOAD_SINGLE)){
if(pData.size()<3){

View File

@ -46,6 +46,6 @@ public class pluginEnums
/*Orbot Manager*/
public enum eOrbotManager{
M_GET_NOTIFICATION_STATUS, M_NEW_CIRCUIT,M_ENABLE_NOTIFICATION, M_DISABLE_NOTIFICATION, M_DISABLE_NOTIFICATION_NO_BANDWIDTH, M_GET_LOGS, M_UPDATE_PRIVACY,M_START_ORBOT,M_IS_ORBOT_RUNNING, M_GET_ORBOT_STATUS, M_UPDATE_BRIDGES, M_UPDATE_VPN, M_SET_PROXY, M_SHOW_NOTIFICATION_STATUS, M_ORBOT_RUNNING
M_GET_NOTIFICATION_STATUS, M_NEW_CIRCUIT, M_DESTROY,M_ENABLE_NOTIFICATION, M_DISABLE_NOTIFICATION, M_DISABLE_NOTIFICATION_NO_BANDWIDTH, M_GET_LOGS, M_UPDATE_PRIVACY,M_START_ORBOT,M_IS_ORBOT_RUNNING, M_GET_ORBOT_STATUS, M_UPDATE_BRIDGES, M_UPDATE_VPN, M_SET_PROXY, M_SHOW_NOTIFICATION_STATUS, M_ORBOT_RUNNING
}
}

View File

@ -3,20 +3,27 @@ package com.widget.search;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.widget.RemoteViews;
import com.darkweb.genesissearchengine.appManager.activityContextManager;
import com.darkweb.genesissearchengine.constants.enums;
import com.darkweb.genesissearchengine.constants.status;
import com.darkweb.genesissearchengine.constants.strings;
import com.darkweb.genesissearchengine.helperManager.helperMethod;
import com.example.myapplication.R;
public class searchWidgetManager extends AppWidgetProvider {
private static final String SHARED_PREF_FILE = "com.example.android.appwidgetsample";
private static final String COUNT_KEY = "count";
private static int mCurrentWidth = -1;
private void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
@ -43,9 +50,10 @@ public class searchWidgetManager extends AppWidgetProvider {
views.setOnClickPendingIntent(R.id.pSearchLogo, pendingUpdate);
views.setOnClickPendingIntent(R.id.pTopBarContainer, pendingUpdate);
views.setOnClickPendingIntent(R.id.pSearchInput, pendingUpdate);
views.setOnClickPendingIntent(R.id.pSearchInputWidget, pendingUpdate);
views.setOnClickPendingIntent(R.id.pVoiceInput, mpintentUpdate);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
public void onReceive(Context context, Intent intent) {
@ -103,10 +111,34 @@ public class searchWidgetManager extends AppWidgetProvider {
}
}
@Override
public void onAppWidgetOptionsChanged (Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle widgetInfo) {
int width = widgetInfo.getInt (AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH);
mCurrentWidth = width;
int[] appWidgetIds = new int[1];
appWidgetIds[0] = appWidgetId;
onUpdate(context, appWidgetManager, appWidgetIds);
}
private int getColsNum (int size) {
return (int) Math.floor ((size - 30) / 70);
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
int size = getColsNum(mCurrentWidth);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_search_controller);
if(mCurrentWidth!=-1){
if(size<=2){
views.setTextColor(R.id.pSearchInputWidget, Color.WHITE);
}else {
views.setTextColor(R.id.pSearchInputWidget, Color.GRAY);
}
appWidgetManager.updateAppWidget(appWidgetIds, views);
}
}
}
}

View File

@ -6,7 +6,7 @@
<shape
android:shape="rectangle" android:padding="10dp" >
<solid android:color="@color/white"/>
<corners android:radius="7dp"/>
<corners android:radius="6dp"/>
</shape>
</item>
<item android:state_pressed="false"
@ -14,7 +14,7 @@
<shape
android:shape="rectangle" android:padding="10dp">
<solid android:color="@color/white"/>
<corners android:radius="7dp"/>
<corners android:radius="6dp"/>
</shape>
</item>
</selector>

View File

@ -25,6 +25,7 @@
android:background="@color/c_background"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:fitsSystemWindows="true"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
android:translationZ="3dp">
<com.google.android.material.appbar.CollapsingToolbarLayout
@ -32,9 +33,8 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:fitsSystemWindows="true"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/pTopLayout"
@ -44,9 +44,8 @@
android:clipToPadding="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:fitsSystemWindows="true"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:id="@+id/pTopbar"
@ -144,7 +143,7 @@
android:scaleX="1.1"
android:scaleY="1.1"
android:src="@xml/ic_baseline_keyboard_voice"
android:tint="@color/c_navigation_tint"
android:tint="@color/c_text_v8"
android:visibility="gone" />
<Button

View File

@ -24,7 +24,7 @@
android:layout_width="52dp"
android:layout_height="52dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="5dp"
android:layout_marginStart="2.5dp"
android:background="@xml/gx_ripple_default_round"
android:contentDescription="@string/GENERAL_TODO"
android:padding="6dp"
@ -33,10 +33,10 @@
android:translationZ="10dp"/>
<TextView
android:id="@+id/pSearchInput"
android:id="@+id/pSearchInputWidget"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="-56dp"
android:layout_marginStart="-53dp"
android:layout_gravity="center_vertical"
android:paddingTop="13dp"
android:layout_marginEnd="1dp"
@ -48,19 +48,18 @@
android:ems="10"
android:fadingEdgeLength="20dp"
android:focusableInTouchMode="true"
android:hint="@string/GENERAL_HIDDEN_WEB"
android:text="@string/GENERAL_HIDDEN_WEB"
android:importantForAutofill="no"
android:inputType="textNoSuggestions"
android:maxLines="1"
android:paddingStart="70dp"
android:paddingStart="60dp"
android:paddingEnd="15dp"
android:popupElevation="0dp"
android:privateImeOptions="nm"
android:requiresFadingEdge="horizontal"
android:selectAllOnFocus="true"
android:textColor="@color/c_text_v1"
android:textColor="#737373"
android:textColorHighlight="@color/text_color_highlight_v3"
android:textColorHint="#737373"
android:textCursorDrawable="@xml/gx_search_cursor_state"
android:textIsSelectable="false"
android:textSize="15sp">

View File

@ -2,7 +2,8 @@
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialKeyguardLayout="@layout/widget_search_controller"
android:initialLayout="@layout/widget_search_controller"
android:minWidth="100dp"
android:minWidth="1000dp"
android:minResizeWidth="100.0dp"
android:previewImage="@drawable/widget_ref"
android:resizeMode="horizontal"
android:updatePeriodMillis="86400000"

View File

@ -68,7 +68,7 @@
android:layout_marginEnd="-1dp"
android:layout_height="48dp"
android:visibility="visible"
android:alpha="1"
android:alpha="0"
android:translationZ="3dp"
android:src="@drawable/tick_recycler_view_green"
android:gravity="center_vertical"

View File

@ -1,16 +0,0 @@
## For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
#
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx1024m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
#
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
#Wed Oct 07 12:31:34 PKT 2020
android.enableJetifier=true
android.useAndroidX=true
org.gradle.jvmargs=-Xms1g -Xmx4g

View File

@ -1,9 +1,9 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion 30
buildToolsVersion '30.0.3'
ndkVersion '21.4.7075529'
compileSdkVersion 29
buildToolsVersion '29.0.3'
ndkVersion '21.3.6528147'
sourceSets {
main {
@ -12,8 +12,8 @@ android {
}
defaultConfig {
minSdkVersion 21
targetSdkVersion 31
minSdkVersion 16
targetSdkVersion 29
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
@ -31,30 +31,31 @@ android {
}
lintOptions {
checkReleaseBuilds false
abortOnError true
abortOnError false
}
htmlReport true
xmlReport false
textReport false
lintConfig file("../lint.xml")
packagingOptions {
exclude 'assets/arm/obfs4proxy' //this is redundant
}
}
dependencies {
testImplementation 'junit:junit:4.13.2'
implementation fileTree(dir: 'libs', include: ['.so'])
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
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 'org.torproject:tor-android-binary:0.4.3.6-actual'
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 'com.jaredrummler:android-shell:1.0.0'
implementation fileTree(dir: 'libs', include: ['.so'])
implementation 'androidx.core:core:1.3.2'
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
testImplementation 'junit:junit:4.13'
implementation 'com.offbynull.portmapper:portmapper:2.0.5'
implementation 'info.guardianproject:jtorctl:0.4'
implementation 'com.github.tladesignz:IPtProxy:0.5.0'
}

View File

@ -1,5 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.torproject.android.proxy">
package="org.torproject.android.service">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>

View File

@ -2,13 +2,12 @@ package org.torproject.android.proxy;
import android.text.TextUtils;
import androidx.core.app.NotificationCompat;
import net.freehaven.tor.control.EventHandler;
import org.torproject.android.proxy.util.ExternalIPFetcher;
import org.torproject.android.proxy.util.Prefs;
import org.torproject.android.proxy.wrapper.orbotLocalConstants;
import org.torproject.android.service.R;
import org.torproject.android.service.wrapper.orbotLocalConstants;
import java.text.NumberFormat;
import java.util.HashMap;

View File

@ -103,7 +103,7 @@ public interface TorServiceConstants {
// actions for internal command Intents
String CMD_SIGNAL_HUP = "signal_hup";
String CMD_NEWNYM = "newnym";
String CMD_setting = "setting";
String CMD_SETTING = "setting";
String CMD_SET_EXIT = "setexit";
String CMD_ACTIVE = "ACTIVE";

View File

@ -4,7 +4,7 @@ import android.content.Context;
import android.content.SharedPreferences;
import org.torproject.android.proxy.OrbotConstants;
import org.torproject.android.proxy.wrapper.orbotLocalConstants;
import org.torproject.android.service.wrapper.orbotLocalConstants;
import java.util.Locale;
@ -98,7 +98,7 @@ public class Prefs {
}
public static boolean useDebugLogging() {
return prefs.getBoolean(PREF_ENABLE_LOGGING, false);
return false;//prefs.getBoolean(PREF_ENABLE_LOGGING, false);
}
public static boolean persistNotifications() {

View File

@ -35,10 +35,11 @@ import com.runjva.sourceforge.jsocks.server.ServerAuthenticatorNone;
import org.torproject.android.proxy.OrbotConstants;
import org.torproject.android.proxy.OrbotService;
import org.torproject.android.proxy.R;
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;

View File

@ -0,0 +1,38 @@
/* Copyright (c) 2009, Nathan Freitas, Orbot/The Guardian Project - http://openideals.com/guardian */
/* See LICENSE for licensing information */
package org.torproject.android.service;
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";
}

View File

@ -0,0 +1,43 @@
package org.torproject.android.service;
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.OrbotService;
import org.torproject.android.service.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 && Prefs.persistNotifications()) {
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);
}
}
}
}

View File

@ -0,0 +1,117 @@
/* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */
/* See LICENSE for licensing information */
package org.torproject.android.service;
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 = "8118"; // like Privoxy!
String SOCKS_PROXY_PORT_DEFAULT = "9050";
//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_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";
}

View File

@ -0,0 +1,126 @@
package org.torproject.android.service.util;
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";
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;
}
}

View File

@ -0,0 +1,80 @@
package org.torproject.android.service.util;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import com.jaredrummler.android.shell.CommandResult;
import com.jaredrummler.android.shell.Shell;
import com.jaredrummler.android.shell.ShellExitCode;
import com.jaredrummler.android.shell.StreamGobbler;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class CustomShell extends Shell {
@WorkerThread
public static CommandResult run(@NonNull String shell, boolean waitFor, @Nullable Map<String, String> env, @NonNull String command) {
List<String> stdout = Collections.synchronizedList(new ArrayList<>());
List<String> stderr = Collections.synchronizedList(new ArrayList<>());
int exitCode = -1;
try {
// setup our process, retrieve stdin stream, and stdout/stderr gobblers
//Process process = runWithEnv(command, env);
ProcessBuilder builder = new ProcessBuilder();
if (env != null && (!env.isEmpty()))
builder.environment().putAll(env);
builder.command("/system/bin/" + shell, "-c", command);
Process process = builder.start();
StreamGobbler stdoutGobbler = null;
StreamGobbler stderrGobbler = null;
if (waitFor) {
stdoutGobbler = new StreamGobbler(process.getInputStream(), stdout);
stderrGobbler = new StreamGobbler(process.getErrorStream(), stderr);
// start gobbling and write our commands to the shell
stdoutGobbler.start();
stderrGobbler.start();
}
// wait for our process to finish, while we gobble away in the background
if (waitFor)
exitCode = process.waitFor();
else
exitCode = 0;
// make sure our threads are done gobbling, our streams are closed, and the process is destroyed - while the
// latter two shouldn't be needed in theory, and may even produce warnings, in "normal" Java they are required
// for guaranteed cleanup of resources, so lets be safe and do this on Android as well
/**
try {
stdin.close();
} catch (IOException e) {
// might be closed already
}**/
if (waitFor) {
stdoutGobbler.join();
stderrGobbler.join();
}
} catch (InterruptedException e) {
exitCode = ShellExitCode.WATCHDOG_EXIT;
} catch (IOException e) {
exitCode = ShellExitCode.SHELL_WRONG_UID;
}
return new CommandResult(stdout, stderr, exitCode);
}
}

View File

@ -0,0 +1,184 @@
package org.torproject.android.service.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);
}
}

View File

@ -0,0 +1,15 @@
package org.torproject.android.service.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();
}
}

View File

@ -0,0 +1,85 @@
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 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 = 8118;
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());
}
}
}

View File

@ -0,0 +1,96 @@
package org.torproject.android.service.util;
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";
private static boolean loadFromZip(Context context, String libName, File destLocalFile, String folder) {
ZipFile zipFile = null;
InputStream stream = null;
try {
zipFile = new ZipFile(context.getApplicationInfo().sourceDir);
/**
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements())
{
ZipEntry entry = entries.nextElement();
Log.d("Zip","entry: " + entry.getName());
}
**/
ZipEntry entry = zipFile.getEntry("lib/" + folder + "/" + libName + ".so");
if (entry == null) {
entry = zipFile.getEntry("lib/" + folder + "/" + libName);
if (entry == null)
throw new Exception("Unable to find file in apk:" + "lib/" + folder + "/" + libName);
}
stream = zipFile.getInputStream(entry);
OutputStream out = new FileOutputStream(destLocalFile);
byte[] buf = new byte[4096];
int len;
while ((len = stream.read(buf)) > 0) {
Thread.yield();
out.write(buf, 0, len);
}
out.close();
destLocalFile.setReadable(true, false);
destLocalFile.setExecutable(true, false);
destLocalFile.setWritable(true);
return true;
} catch (Exception e) {
Log.e(TAG, e.getMessage());
} finally {
if (stream != null) {
try {
stream.close();
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
if (zipFile != null) {
try {
zipFile.close();
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
}
return false;
}
public static synchronized boolean initNativeLibs(Context context, String binaryName, File destLocalFile) {
try {
String folder = Build.CPU_ABI;
String javaArch = System.getProperty("os.arch");
if (javaArch != null && javaArch.contains("686")) {
folder = "x86";
}
return loadFromZip(context, binaryName, destLocalFile, folder);
} catch (Throwable e) {
e.printStackTrace();
}
return false;
}
}

View File

@ -0,0 +1,77 @@
package org.torproject.android.service.util;
import android.util.Log;
import com.offbynull.portmapper.PortMapperFactory;
import com.offbynull.portmapper.gateway.Bus;
import com.offbynull.portmapper.gateway.Gateway;
import com.offbynull.portmapper.gateways.network.NetworkGateway;
import com.offbynull.portmapper.gateways.network.internalmessages.KillNetworkRequest;
import com.offbynull.portmapper.gateways.process.ProcessGateway;
import com.offbynull.portmapper.gateways.process.internalmessages.KillProcessRequest;
import com.offbynull.portmapper.mapper.MappedPort;
import com.offbynull.portmapper.mapper.PortMapper;
import com.offbynull.portmapper.mapper.PortType;
import java.util.List;
public class PortForwarder {
private boolean shutdown = false;
private Thread mThread = null;
public void shutdown() {
shutdown = true;
}
public void forward(final int internalPort, final int externalPort, final long lifetime) throws InterruptedException {
mThread = new Thread() {
public void run() {
try {
forwardSync(internalPort, externalPort, lifetime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
mThread.start();
}
public void forwardSync(int internalPort, int externalPort, long lifetime) throws InterruptedException {
// Start gateways
Gateway network = NetworkGateway.create();
Gateway process = ProcessGateway.create();
Bus networkBus = network.getBus();
Bus processBus = process.getBus();
// Discover port forwarding devices and take the first one found
List<PortMapper> mappers = PortMapperFactory.discover(networkBus, processBus);
PortMapper mapper = mappers.get(0);
// Map internal port 12345 to some external port (55555 preferred)
//
// IMPORTANT NOTE: Many devices prevent you from mapping ports that are <= 1024
// (both internal and external ports). Be mindful of this when choosing which
// ports you want to map.
MappedPort mappedPort = mapper.mapPort(PortType.TCP, internalPort, externalPort, lifetime);
Log.d(getClass().getName(), "Port mapping added: " + mappedPort);
// Refresh mapping half-way through the lifetime of the mapping (for example,
// if the mapping is available for 40 seconds, refresh it every 20 seconds)
while (!shutdown) {
mappedPort = mapper.refreshPort(mappedPort, mappedPort.getLifetime() / 2L);
Log.d(getClass().getName(), "Port mapping refreshed: " + mappedPort);
Thread.sleep(mappedPort.getLifetime() * 1000L);
}
// Unmap port 12345
mapper.unmapPort(mappedPort);
// Stop gateways
networkBus.send(new KillNetworkRequest());
processBus.send(new KillProcessRequest()); // can kill this after discovery
}
}

View File

@ -0,0 +1,118 @@
package org.torproject.android.service.util;
import android.content.Context;
import android.content.SharedPreferences;
import org.torproject.android.service.OrbotConstants;
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 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
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 void setDefaultLocale(String value) {
putString(PREF_DEFAULT_LOCALE, value);
}
public static boolean expandedNotifications() {
return prefs.getBoolean(PREF_EXPANDED_NOTIFICATIONS, true);
}
public static boolean useDebugLogging() {
if(prefs == null){
return false;
}
return 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);
}
}

View File

@ -0,0 +1,307 @@
package org.torproject.android.service.util;
/***********************************************************************
*
* Copyright (c) 2013, Sebastiano Gottardo
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the MegaDevs nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL SEBASTIANO GOTTARDO BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Main class for the TCPSourceApp library.
*
* @author Sebastiano Gottardo
*/
public class TCPSourceApp {
/*
* In a Linux-based OS, each active TCP socket is mapped in the following
* two files. A socket may be mapped in the '/proc/net/tcp' file in case
* of a simple IPv4 address, or in the '/proc/net/tcp6' if an IPv6 address
* is available.
*/
private static final String TCP_4_FILE_PATH = "/proc/net/tcp";
private static final String TCP_6_FILE_PATH = "/proc/net/tcp6";
/*
* Two regular expressions that are able to extract valuable informations
* from the two /proc/net/tcp* files. More specifically, there are three
* fields that are extracted:
* - address
* - port
* - PID
*/
private static final String TCP_6_PATTERN = "\\d+:\\s([0-9A-F]{32}):([0-9A-F]{4})\\s[0-9A-F]{32}:[0-9A-F]{4}\\s[0-9A-F]{2}\\s[0-9]{8}:[0-9]{8}\\s[0-9]{2}:[0-9]{8}\\s[0-9]{8}\\s+([0-9]+)";
private static final String TCP_4_PATTERN = "\\d+:\\s([0-9A-F]{8}):([0-9A-F]{4})\\s[0-9A-F]{8}:[0-9A-F]{4}\\s[0-9A-F]{2}\\s[0-9A-F]{8}:[0-9A-F]{8}\\s[0-9]{2}:[0-9]{8}\\s[0-9A-F]{8}\\s+([0-9]+)";
//sargo:/ $ cat /proc/net/tcp6
// sl local_address remote_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
// 0: 00000000000000000000000000000000:C36A 00000000000000000000000000000000:0000 8A 00000000:00000000 00:00000000 00000000 1001 0 35059 1 0000000000000000 99 0 0 10 0
// 1: 00000000000000000000000000000000:A64B 00000000000000000000000000000000:0000 8A 00000000:00000000 00:00000000 00000000 1001 0 910009 1 0000000000000000 99 0 0 10 0
/*
* Optimises the socket lookup by checking if the connected network
* interface has a 'valid' IPv6 address (a global address, not a link-local
* one).
*/
private static boolean checkConnectedIfaces = true;
// sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
// 0: 00000000:C368 00000000:0000 8A 00000000:00000000 00:00000000 00000000 1001 0 34999 1 0000000000000000 99 0 0 10 0
/**
* The main method of the TCPSourceApp library. This method receives an
* Android Context instance, which is used to access the PackageManager.
* It parses the /proc/net/tcp* files, looking for a socket entry that
* matches the given port. If it finds an entry, this method extracts the
* PID value and it uses the PackageManager.getPackagesFromPid() method to
* find the originating application.
*
* @param context a valid Android Context instance
* @param daddr the (logical) address of the destination
* @param dport the (logical) port of the destination
* @return an AppDescriptor object, representing the found application; null
* if no application could be found
*/
public static AppDescriptor getApplicationInfo(Context context, String saddr, int sport, String daddr, int dport) {
File tcp;
BufferedReader reader;
String line;
StringBuilder builder;
String content;
try {
boolean hasIPv6 = true;
// if true, checks for a connected network interface with a valid
// IPv4 / IPv6 address
if (checkConnectedIfaces) {
String ipv4Address = getIPAddress(true);
String ipv6Address = getIPAddress(false);
hasIPv6 = (ipv6Address.length() > 0);
}
tcp = new File(TCP_6_FILE_PATH);
reader = new BufferedReader(new FileReader(tcp));
builder = new StringBuilder();
while ((line = reader.readLine()) != null) {
builder.append(line);
}
content = builder.toString();
Matcher m6 = Pattern.compile(TCP_6_PATTERN, Pattern.CASE_INSENSITIVE | Pattern.UNIX_LINES | Pattern.DOTALL).matcher(content);
if (hasIPv6)
while (m6.find()) {
String addressEntry = m6.group(1);
String portEntry = m6.group(2);
int pidEntry = Integer.valueOf(m6.group(3));
if (Integer.parseInt(portEntry, 16) == dport) {
PackageManager manager = context.getPackageManager();
String[] packagesForUid = manager.getPackagesForUid(pidEntry);
if (packagesForUid != null) {
String packageName = packagesForUid[0];
PackageInfo pInfo = manager.getPackageInfo(packageName, 0);
String version = pInfo.versionName;
return new AppDescriptor(pidEntry, packageName, version);
}
}
}
} catch (SocketException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NameNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
// From here, no connection with the given port could be found in the tcp6 file
// So let's try the tcp (IPv4) one
try {
tcp = new File(TCP_4_FILE_PATH);
reader = new BufferedReader(new FileReader(tcp));
builder = new StringBuilder();
while ((line = reader.readLine()) != null) {
builder.append(line);
}
content = builder.toString();
Matcher m4 = Pattern.compile(TCP_4_PATTERN, Pattern.CASE_INSENSITIVE | Pattern.UNIX_LINES | Pattern.DOTALL).matcher(content);
while (m4.find()) {
String addressEntry = m4.group(1);
String portEntry = m4.group(2);
int pidEntry = Integer.valueOf(m4.group(3));
if (Integer.parseInt(portEntry, 16) == dport) {
PackageManager manager = context.getPackageManager();
String[] packagesForUid = manager.getPackagesForUid(pidEntry);
if (packagesForUid != null) {
String packageName = packagesForUid[0];
PackageInfo pInfo = manager.getPackageInfo(packageName, 0);
String version = pInfo.versionName;
return new AppDescriptor(pidEntry, packageName, version);
}
}
}
} catch (SocketException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NameNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@SuppressLint("DefaultLocale")
public static String getIPAddress(boolean useIPv4) throws SocketException {
List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface intf : interfaces) {
List<InetAddress> addrs = Collections.list(intf.getInetAddresses());
for (InetAddress addr : addrs) {
if (!addr.isLoopbackAddress()) {
String sAddr = addr.getHostAddress().toUpperCase();
boolean isIPv4 = addr instanceof Inet4Address;
if (useIPv4) {
if (isIPv4)
return sAddr;
} else {
if (!isIPv4) {
if (sAddr.startsWith("fe80") || sAddr.startsWith("FE80")) // skipping link-local addresses
continue;
int delim = sAddr.indexOf('%'); // drop ip6 port suffix
return delim < 0 ? sAddr : sAddr.substring(0, delim);
}
}
}
}
}
return "";
}
/*
* Sets the connected interfaces optimisation.
*/
public static void setCheckConnectedIfaces(boolean value) {
checkConnectedIfaces = value;
}
/*
* This class represents an Android application. Each application is
* uniquely identified by its package name (e.g. com.megadevs.tcpsourceapp)
* and its version (e.g. 1.0).
*/
public static class AppDescriptor {
private String packageName;
private String version;
private int uid;
public AppDescriptor(int uid, String pName, String ver) {
this.uid = uid;
packageName = pName;
version = ver;
}
public int getUid() {
return uid;
}
public String getPackageName() {
return packageName;
}
public String getVersion() {
return version;
}
/*
* Override of the 'equals' method, in order to have a proper
* comparison between two AppDescriptor objects.
*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object o) {
if (o instanceof AppDescriptor) {
boolean c1 = ((AppDescriptor) o).packageName.compareTo(this.packageName) == 0;
boolean c2 = ((AppDescriptor) o).version.compareTo(this.version) == 0;
return c1 && c2;
}
return false;
}
}
}

View File

@ -0,0 +1,27 @@
/* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */
/* See LICENSE for licensing information */
package org.torproject.android.service.util;
import org.torproject.android.service.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;
}
}
}

View File

@ -0,0 +1,183 @@
/* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */
/* See LICENSE for licensing information */
package org.torproject.android.service.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];
}
}

View File

@ -0,0 +1,402 @@
/*
* 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.service.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.text.TextUtils;
import android.util.Log;
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.R;
import org.torproject.android.service.TorServiceConstants;
import org.torproject.android.service.util.CustomNativeLoader;
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;
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;
import static org.torproject.android.service.TorServiceConstants.ACTION_START_VPN;
import static org.torproject.android.service.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 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 boolean isRestart = false;
private VpnService mService;
public OrbotVpnManager(VpnService service) throws IOException, TimeoutException {
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 (!TextUtils.isEmpty(action)) {
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 = "OrbotVPN";
final String localhost = "127.0.0.1";
final String virtualGateway = "192.168.200.1";
final String virtualIP = "192.168.200.2";
final String virtualNetMask = "255.255.255.0";
final String dummyDNS = "1.1.1.1"; //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);
// Create a new interface using the builder and save the parameters.
ParcelFileDescriptor newInterface = builder.setSession(mSessionName)
.setConfigureIntent(null) // previously this was set to a null member variable
.establish();
if (mInterface != null) {
Log.d(TAG, "Stopping existing VPN interface");
mInterface.close();
mInterface = null;
}
mInterface = newInterface;
isRestart = false;
//start PDNSD daemon pointing to actual DNS
if (filePdnsd != null) {
pdnsdPort++;
startDNS(filePdnsd.getCanonicalPath(), localhost, mTorDns, virtualGateway, pdnsdPort);
final boolean localDnsTransparentProxy = true;
Tun2Socks.Start(mService, mInterface, VPN_MTU, virtualIP, virtualNetMask, localSocks, virtualGateway + ":" + pdnsdPort, localDnsTransparentProxy);
}
} catch (Exception e) {
Log.d(TAG, "tun2Socks has stopped", e);
}
}
};
mThreadVPN.start();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void doLollipopAppRouting(VpnService.Builder builder) throws NameNotFoundException {
SharedPreferences prefs = Prefs.getSharedPrefs(mService.getApplicationContext());
ArrayList<TorifiedApp> apps = TorifiedApp.getApps(mService, prefs);
boolean perAppEnabled = false;
for (TorifiedApp app : apps) {
if (app.isTorified() && (!app.getPackageName().equals(mService.getPackageName()))) {
if (prefs.getBoolean(app.getPackageName() + OrbotConstants.APP_TOR_KEY, true)) {
builder.addAllowedApplication(app.getPackageName());
}
perAppEnabled = true;
}
}
if (!perAppEnabled)
builder.addDisallowedApplication(mService.getPackageName());
}
private void startDNS(String pdnsPath, String torDnsHost, int torDnsPort, String pdnsdHost, int pdnsdPort) throws IOException, TimeoutException {
File fileConf = makePdnsdConf(mService, mService.getFilesDir(), torDnsHost, torDnsPort, pdnsdHost, pdnsdPort);
String[] cmdString = {pdnsPath, "-c", fileConf.toString(), "-g", "-v2"};
ProcessBuilder pb = new ProcessBuilder(cmdString);
pb.redirectErrorStream(true);
Process proc = pb.start();
try {
proc.waitFor();
} catch (Exception e) {
}
Log.i(TAG, "PDNSD: " + proc.exitValue());
if (proc.exitValue() != 0) {
BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
Log.d(TAG, "pdnsd: " + line);
}
}
}
private boolean stopDns() {
if (filePdnsPid != null && filePdnsPid.exists()) {
List<String> lines;
try {
lines = IOUtils.readLines(new FileReader(filePdnsPid));
String dnsPid = lines.get(0);
VpnUtils.killProcess(dnsPid, "");
filePdnsPid.delete();
filePdnsPid = null;
} catch (Exception e) {
Log.e("OrbotVPN", "error killing dns process", e);
}
}
return false;
}
public boolean isStarted() {
return isStarted;
}
}

View File

@ -0,0 +1,260 @@
package org.torproject.android.service.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.service.vpn.VpnPrefs.PREFS_KEY_TORIFIED;
public class TorifiedApp implements Comparable {
private boolean enabled;
private int uid;
private String username;
private String procname;
private String name;
private Drawable icon;
private String packageName;
private boolean torified = false;
private boolean usesInternet = false;
private int[] enabledPorts;
public static ArrayList<TorifiedApp> getApps(Context context, SharedPreferences prefs) {
String tordAppString = prefs.getString(PREFS_KEY_TORIFIED, "");
String[] tordApps;
StringTokenizer st = new StringTokenizer(tordAppString, "|");
tordApps = new String[st.countTokens()];
int tordIdx = 0;
while (st.hasMoreTokens()) {
tordApps[tordIdx++] = st.nextToken();
}
Arrays.sort(tordApps);
//else load the apps up
PackageManager pMgr = context.getPackageManager();
List<ApplicationInfo> lAppInfo = pMgr.getInstalledApplications(0);
Iterator<ApplicationInfo> itAppInfo = lAppInfo.iterator();
ArrayList<TorifiedApp> apps = new ArrayList<>();
ApplicationInfo aInfo;
int appIdx = 0;
TorifiedApp app;
while (itAppInfo.hasNext()) {
aInfo = itAppInfo.next();
app = new TorifiedApp();
try {
PackageInfo pInfo = pMgr.getPackageInfo(aInfo.packageName, PackageManager.GET_PERMISSIONS);
if (pInfo != null && pInfo.requestedPermissions != null) {
for (String permInfo : pInfo.requestedPermissions) {
if (permInfo.equals(Manifest.permission.INTERNET)) {
app.setUsesInternet(true);
}
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if ((aInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 1) {
//System app
app.setUsesInternet(true);
}
if (!app.usesInternet())
continue;
else {
apps.add(app);
}
app.setEnabled(aInfo.enabled);
app.setUid(aInfo.uid);
app.setUsername(pMgr.getNameForUid(app.getUid()));
app.setProcname(aInfo.processName);
app.setPackageName(aInfo.packageName);
try {
app.setName(pMgr.getApplicationLabel(aInfo).toString());
} catch (Exception e) {
app.setName(aInfo.packageName);
}
//app.setIcon(pMgr.getApplicationIcon(aInfo));
// check if this application is allowed
if (Arrays.binarySearch(tordApps, app.getUsername()) >= 0) {
app.setTorified(true);
} else {
app.setTorified(false);
}
appIdx++;
}
Collections.sort(apps);
return apps;
}
public boolean usesInternet() {
return usesInternet;
}
public void setUsesInternet(boolean usesInternet) {
this.usesInternet = usesInternet;
}
/**
* @return the torified
*/
public boolean isTorified() {
return torified;
}
/**
* @param torified the torified to set
*/
public void setTorified(boolean torified) {
this.torified = torified;
}
/**
* @return the enabledPorts
*/
public int[] getEnabledPorts() {
return enabledPorts;
}
/**
* @param enabledPorts the enabledPorts to set
*/
public void setEnabledPorts(int[] enabledPorts) {
this.enabledPorts = enabledPorts;
}
/**
* @return the enabled
*/
public boolean isEnabled() {
return enabled;
}
/**
* @param enabled the enabled to set
*/
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
/**
* @return the uid
*/
public int getUid() {
return uid;
}
/**
* @param uid the uid to set
*/
public void setUid(int uid) {
this.uid = uid;
}
/**
* @return the username
*/
public String getUsername() {
return username;
}
/**
* @param username the username to set
*/
public void setUsername(String username) {
this.username = username;
}
/**
* @return the procname
*/
public String getProcname() {
return procname;
}
/**
* @param procname the procname to set
*/
public void setProcname(String procname) {
this.procname = procname;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
public Drawable getIcon() {
return icon;
}
public void setIcon(Drawable icon) {
this.icon = icon;
}
@Override
public int compareTo(Object another) {
return this.toString().compareToIgnoreCase(another.toString());
}
@Override
public String toString() {
return getName();
}
public String getPackageName() {
return packageName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
}

View File

@ -0,0 +1,173 @@
package org.torproject.android.service.vpn;
/*
* Copyright (c) 2013, Psiphon Inc.
* All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import android.annotation.TargetApi;
import android.content.Context;
import android.net.ConnectivityManager;
import android.os.Build;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import org.torproject.android.service.util.TCPSourceApp;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.HashMap;
import static android.content.Context.CONNECTIVITY_SERVICE;
public class Tun2Socks {
private static final String TAG = Tun2Socks.class.getSimpleName();
private static final boolean LOGD = true;
private static ParcelFileDescriptor mVpnInterfaceFileDescriptor;
private static int mVpnInterfaceMTU;
private static String mVpnIpAddress;
private static String mVpnNetMask;
private static String mSocksServerAddress;
private static String mUdpgwServerAddress;
private static boolean mUdpgwTransparentDNS;
private static HashMap<Integer, String> mAppUidBlacklist = new HashMap<>();
static {
System.loadLibrary("tun2socks");
}
public static void init() {
}
// Note: this class isn't a singleton, but you can't run more
// than one instance due to the use of global state (the lwip
// module, etc.) in the native code.
public static void Start(
Context context,
ParcelFileDescriptor vpnInterfaceFileDescriptor,
int vpnInterfaceMTU,
String vpnIpAddress,
String vpnNetMask,
String socksServerAddress,
String udpgwServerAddress,
boolean udpgwTransparentDNS) {
mVpnInterfaceFileDescriptor = vpnInterfaceFileDescriptor;
mVpnInterfaceMTU = vpnInterfaceMTU;
mVpnIpAddress = vpnIpAddress;
mVpnNetMask = vpnNetMask;
mSocksServerAddress = socksServerAddress;
mUdpgwServerAddress = udpgwServerAddress;
mUdpgwTransparentDNS = udpgwTransparentDNS;
if (mVpnInterfaceFileDescriptor != null)
runTun2Socks(
mVpnInterfaceFileDescriptor.detachFd(),
mVpnInterfaceMTU,
mVpnIpAddress,
mVpnNetMask,
mSocksServerAddress,
mUdpgwServerAddress,
mUdpgwTransparentDNS ? 1 : 0);
}
public static void Stop() {
terminateTun2Socks();
}
public static void logTun2Socks(
String level,
String channel,
String msg) {
String logMsg = level + "(" + channel + "): " + msg;
if (0 == level.compareTo("ERROR")) {
Log.e(TAG, logMsg);
} else {
if (LOGD) Log.d(TAG, logMsg);
}
}
private native static int runTun2Socks(
int vpnInterfaceFileDescriptor,
int vpnInterfaceMTU,
String vpnIpAddress,
String vpnNetMask,
String socksServerAddress,
String udpgwServerAddress,
int udpgwTransparentDNS);
private native static void terminateTun2Socks();
public static boolean checkIsAllowed(Context context, int protocol, String sourceAddr, int sourcePort, String destAddr, int destPort) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
return isAllowedQ(context, protocol, sourceAddr, sourcePort, destAddr, destPort);
} else
return isAllowed(context, protocol, sourceAddr, sourcePort, destAddr, destPort);
}
public static boolean isAllowed(Context context, int protocol, String sourceAddr, int sourcePort, String destAddr, int destPort) {
TCPSourceApp.AppDescriptor aInfo = TCPSourceApp.getApplicationInfo(context, sourceAddr, sourcePort, destAddr, destPort);
if (aInfo != null) {
int uid = aInfo.getUid();
return mAppUidBlacklist.containsKey(uid);
} else
return true;
}
@TargetApi(Build.VERSION_CODES.Q)
public static boolean isAllowedQ(Context context, int protocol, String sourceAddr, int sourcePort, String destAddr, int destPort) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(CONNECTIVITY_SERVICE);
if (cm == null)
return false;
InetSocketAddress local = new InetSocketAddress(sourceAddr, sourcePort);
InetSocketAddress remote = new InetSocketAddress(destAddr, destPort);
int uid = cm.getConnectionOwnerUid(protocol, local, remote);
return mAppUidBlacklist.containsKey(uid);
}
public static void setBlacklist(HashMap<Integer, String> appUidBlacklist) {
mAppUidBlacklist = appUidBlacklist;
}
public static void clearBlacklist() {
mAppUidBlacklist.clear();
}
public static void addToBlacklist(int uid, String pkgId) {
mAppUidBlacklist.put(uid, pkgId);
}
public static void removeFromBlacklist(int uid) {
mAppUidBlacklist.remove(uid);
}
public interface IProtectSocket {
boolean doVpnProtect(Socket socket);
boolean doVpnProtect(DatagramSocket socket);
}
}

View File

@ -0,0 +1,8 @@
package org.torproject.android.service.vpn;
public interface VpnPrefs {
String PREFS_DNS_PORT = "PREFS_DNS_PORT";
String PREFS_KEY_TORIFIED = "PrefTord";
}

View File

@ -0,0 +1,136 @@
package org.torproject.android.service.vpn;
import android.util.Log;
import org.apache.commons.io.IOUtils;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import static java.lang.Runtime.getRuntime;
public class VpnUtils {
public static int findProcessId(String command) throws IOException {
String[] cmds = {"ps -ef", "ps -A", "toolbox ps"};
for (int i = 0; i < cmds.length; i++) {
Process procPs = getRuntime().exec(cmds[i]);
BufferedReader reader = new BufferedReader(new InputStreamReader(procPs.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
if (!line.contains("PID") && line.contains(command)) {
String[] lineParts = line.split("\\s+");
try {
return Integer.parseInt(lineParts[1]); //for most devices it is the second
} catch (NumberFormatException e) {
return Integer.parseInt(lineParts[0]); //but for samsungs it is the first
} finally {
try {
procPs.destroy();
} catch (Exception e) {
}
}
}
}
}
return -1;
}
public static void killProcess(File fileProcBin) throws Exception {
killProcess(fileProcBin, "-9"); // this is -KILL
}
public static int killProcess(File fileProcBin, String signal) throws Exception {
int procId = -1;
int killAttempts = 0;
while ((procId = findProcessId(fileProcBin.getName())) != -1) {
killAttempts++;
String pidString = String.valueOf(procId);
boolean itBeDead = killProcess(pidString, signal);
if (!itBeDead) {
String[] cmds = {"", "busybox ", "toolbox "};
for (int i = 0; i < cmds.length; i++) {
Process proc;
try {
proc = getRuntime().exec(cmds[i] + "killall " + signal + " " + fileProcBin.getName
());
int exitValue = proc.waitFor();
if (exitValue == 0)
break;
} catch (IOException ioe) {
}
try {
proc = getRuntime().exec(cmds[i] + "killall " + signal + " " + fileProcBin.getCanonicalPath());
int exitValue = proc.waitFor();
if (exitValue == 0)
break;
} catch (IOException ioe) {
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// ignored
}
}
if (killAttempts > 4)
throw new Exception("Cannot kill: " + fileProcBin.getAbsolutePath());
}
return procId;
}
public static boolean killProcess(String pidString, String signal) throws Exception {
String[] cmds = {"", "toolbox ", "busybox "};
for (int i = 0; i < cmds.length; i++) {
try {
Process proc = getRuntime().exec(cmds[i] + "kill " + signal + " " + pidString);
int exitVal = proc.waitFor();
List<String> lineErrors = IOUtils.readLines(proc.getErrorStream());
List<String> lineInputs = IOUtils.readLines(proc.getInputStream());
if (exitVal != 0) {
Log.d("Orbot.killProcess", "exit=" + exitVal);
for (String line : lineErrors)
Log.d("Orbot.killProcess", line);
for (String line : lineInputs)
Log.d("Orbot.killProcess", line);
} else {
//it worked, let's exit
return true;
}
} catch (IOException ioe) {
Log.e("Orbot.killprcess", "error killing process: " + pidString, ioe);
}
}
return false;
}
}

View File

@ -1,4 +1,4 @@
package org.torproject.android.proxy.wrapper;
package org.torproject.android.service.wrapper;
import android.annotation.TargetApi;
import android.content.Context;

View File

@ -1,4 +1,4 @@
package org.torproject.android.proxy.wrapper;
package org.torproject.android.service.wrapper;
import java.time.LocalDateTime;
import java.util.Calendar;

View File

@ -1,4 +1,4 @@
package org.torproject.android.proxy.wrapper;
package org.torproject.android.service.wrapper;
public class logRowModel {
/*Private Variables*/

View File

@ -1,4 +1,4 @@
package org.torproject.android.proxy.wrapper;
package org.torproject.android.service.wrapper;
import android.content.Context;
import android.content.Intent;

View File

@ -5,4 +5,3 @@ obfs4 37.218.240.34:40035 88CD36D45A35271963EF82E511C8827A24730913 cert=eGXYfWOD
obfs4 37.218.245.14:38224 D9A82D2F9C2F65A18407B1D2B764F130847F8B5D cert=bjRaMrr1BRiAW8IE9U5z27fQaYgOhX1UCmOpg2pFpoMvo6ZgQMzLsaTzzQNTlm7hNcb+Sg iat-mode=0
obfs4 85.31.186.98:443 011F2599C0E9B27EE74B353155E244813763C3E5 cert=ayq0XzCwhpdysn5o0EyDUbmSOx3X/oTEbzDMvczHOdBJKlvIdHHLJGkZARtT4dcBFArPPg iat-mode=0
meek_lite 0.0.2.0:2 97700DFE9F483596DDA6264C4D7DF7641E1E39CE url=https://meek.azureedge.net/ front=ajax.aspnetcdn.com
snowflake 192.0.2.3:1

View File

@ -14,13 +14,10 @@
<string name="something_bad_happened">Something bad happened. Check the log</string>
<string name="unable_to_read_hidden_service_name">unable to read onion service name</string>
<string name="unable_to_start_tor">Unable to start Tor:</string>
<string name="waiting_for_control_port">Waiting for control port...</string>
<string name="connecting_to_control_port">Connecting to control port:</string>
<string name="newnym">You\'ve switched to a new Tor identity!</string>
<string name="updating_settings_in_tor_service">updating settings in Tor service</string>
<string name="menu_new_identity">New Identity</string>
<string name="no_network_connectivity_putting_tor_to_sleep_">No network connectivity. Putting Tor to sleep…</string>
<string name="network_connectivity_is_good_waking_tor_up_">Network connectivity is good. Waking Tor up…</string>
</resources>

View File

@ -0,0 +1,15 @@
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);
}
}