mirror of https://github.com/M66B/NetGuard.git
252 lines
11 KiB
Java
252 lines
11 KiB
Java
package eu.faircode.netguard;
|
|
|
|
/*
|
|
This file is part of NetGuard.
|
|
|
|
NetGuard 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.
|
|
|
|
NetGuard 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 NetGuard. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
Copyright 2015-2018 by Marcel Bokhorst (M66B)
|
|
*/
|
|
|
|
import android.content.DialogInterface;
|
|
import android.database.Cursor;
|
|
import android.os.AsyncTask;
|
|
import android.os.Bundle;
|
|
import android.view.LayoutInflater;
|
|
import android.view.Menu;
|
|
import android.view.MenuInflater;
|
|
import android.view.MenuItem;
|
|
import android.view.View;
|
|
import android.widget.AdapterView;
|
|
import android.widget.ArrayAdapter;
|
|
import android.widget.EditText;
|
|
import android.widget.ListView;
|
|
import android.widget.PopupMenu;
|
|
import android.widget.ProgressBar;
|
|
import android.widget.Spinner;
|
|
import android.widget.Toast;
|
|
|
|
import java.net.InetAddress;
|
|
import java.util.List;
|
|
|
|
import androidx.appcompat.app.AlertDialog;
|
|
import androidx.appcompat.app.AppCompatActivity;
|
|
|
|
public class ActivityForwarding extends AppCompatActivity {
|
|
private boolean running;
|
|
private ListView lvForwarding;
|
|
private AdapterForwarding adapter;
|
|
private AlertDialog dialog = null;
|
|
|
|
private DatabaseHelper.ForwardChangedListener listener = new DatabaseHelper.ForwardChangedListener() {
|
|
@Override
|
|
public void onChanged() {
|
|
runOnUiThread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
if (adapter != null)
|
|
adapter.changeCursor(DatabaseHelper.getInstance(ActivityForwarding.this).getForwarding());
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
@Override
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
Util.setTheme(this);
|
|
super.onCreate(savedInstanceState);
|
|
setContentView(R.layout.forwarding);
|
|
running = true;
|
|
|
|
getSupportActionBar().setTitle(R.string.setting_forwarding);
|
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
|
|
|
|
|
lvForwarding = findViewById(R.id.lvForwarding);
|
|
adapter = new AdapterForwarding(this, DatabaseHelper.getInstance(this).getForwarding());
|
|
lvForwarding.setAdapter(adapter);
|
|
|
|
lvForwarding.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
|
@Override
|
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
|
Cursor cursor = (Cursor) adapter.getItem(position);
|
|
final int protocol = cursor.getInt(cursor.getColumnIndex("protocol"));
|
|
final int dport = cursor.getInt(cursor.getColumnIndex("dport"));
|
|
final String raddr = cursor.getString(cursor.getColumnIndex("raddr"));
|
|
final int rport = cursor.getInt(cursor.getColumnIndex("rport"));
|
|
|
|
PopupMenu popup = new PopupMenu(ActivityForwarding.this, view);
|
|
popup.inflate(R.menu.forward);
|
|
popup.getMenu().findItem(R.id.menu_port).setTitle(
|
|
Util.getProtocolName(protocol, 0, false) + " " +
|
|
dport + " > " + raddr + "/" + rport);
|
|
|
|
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
|
@Override
|
|
public boolean onMenuItemClick(MenuItem menuItem) {
|
|
if (menuItem.getItemId() == R.id.menu_delete) {
|
|
DatabaseHelper.getInstance(ActivityForwarding.this).deleteForward(protocol, dport);
|
|
ServiceSinkhole.reload("forwarding", ActivityForwarding.this, false);
|
|
adapter = new AdapterForwarding(ActivityForwarding.this,
|
|
DatabaseHelper.getInstance(ActivityForwarding.this).getForwarding());
|
|
lvForwarding.setAdapter(adapter);
|
|
}
|
|
return false;
|
|
}
|
|
});
|
|
|
|
popup.show();
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
protected void onResume() {
|
|
super.onResume();
|
|
DatabaseHelper.getInstance(this).addForwardChangedListener(listener);
|
|
if (adapter != null)
|
|
adapter.changeCursor(DatabaseHelper.getInstance(ActivityForwarding.this).getForwarding());
|
|
}
|
|
|
|
@Override
|
|
protected void onPause() {
|
|
super.onPause();
|
|
DatabaseHelper.getInstance(this).removeForwardChangedListener(listener);
|
|
}
|
|
|
|
@Override
|
|
protected void onDestroy() {
|
|
running = false;
|
|
adapter = null;
|
|
if (dialog != null) {
|
|
dialog.dismiss();
|
|
dialog = null;
|
|
}
|
|
super.onDestroy();
|
|
}
|
|
|
|
@Override
|
|
public boolean onCreateOptionsMenu(Menu menu) {
|
|
MenuInflater inflater = getMenuInflater();
|
|
inflater.inflate(R.menu.forwarding, menu);
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean onOptionsItemSelected(MenuItem item) {
|
|
switch (item.getItemId()) {
|
|
case R.id.menu_add:
|
|
LayoutInflater inflater = LayoutInflater.from(this);
|
|
View view = inflater.inflate(R.layout.forwardadd, null, false);
|
|
final Spinner spProtocol = view.findViewById(R.id.spProtocol);
|
|
final EditText etDPort = view.findViewById(R.id.etDPort);
|
|
final EditText etRAddr = view.findViewById(R.id.etRAddr);
|
|
final EditText etRPort = view.findViewById(R.id.etRPort);
|
|
final ProgressBar pbRuid = view.findViewById(R.id.pbRUid);
|
|
final Spinner spRuid = view.findViewById(R.id.spRUid);
|
|
|
|
final AsyncTask task = new AsyncTask<Object, Object, List<Rule>>() {
|
|
@Override
|
|
protected void onPreExecute() {
|
|
pbRuid.setVisibility(View.VISIBLE);
|
|
spRuid.setVisibility(View.GONE);
|
|
}
|
|
|
|
@Override
|
|
protected List<Rule> doInBackground(Object... objects) {
|
|
return Rule.getRules(true, ActivityForwarding.this);
|
|
}
|
|
|
|
@Override
|
|
protected void onPostExecute(List<Rule> rules) {
|
|
ArrayAdapter spinnerArrayAdapter =
|
|
new ArrayAdapter(ActivityForwarding.this,
|
|
android.R.layout.simple_spinner_item, rules);
|
|
spRuid.setAdapter(spinnerArrayAdapter);
|
|
pbRuid.setVisibility(View.GONE);
|
|
spRuid.setVisibility(View.VISIBLE);
|
|
}
|
|
};
|
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
|
|
dialog = new AlertDialog.Builder(this)
|
|
.setView(view)
|
|
.setCancelable(true)
|
|
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
|
|
@Override
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
try {
|
|
int pos = spProtocol.getSelectedItemPosition();
|
|
String[] values = getResources().getStringArray(R.array.protocolValues);
|
|
final int protocol = Integer.valueOf(values[pos]);
|
|
final int dport = Integer.parseInt(etDPort.getText().toString());
|
|
final String raddr = etRAddr.getText().toString();
|
|
final int rport = Integer.parseInt(etRPort.getText().toString());
|
|
final int ruid = ((Rule) spRuid.getSelectedItem()).uid;
|
|
|
|
InetAddress iraddr = InetAddress.getByName(raddr);
|
|
if (rport < 1024 && (iraddr.isLoopbackAddress() || iraddr.isAnyLocalAddress()))
|
|
throw new IllegalArgumentException("Port forwarding to privileged port on local address not possible");
|
|
|
|
new AsyncTask<Object, Object, Throwable>() {
|
|
@Override
|
|
protected Throwable doInBackground(Object... objects) {
|
|
try {
|
|
DatabaseHelper.getInstance(ActivityForwarding.this)
|
|
.addForward(protocol, dport, raddr, rport, ruid);
|
|
return null;
|
|
} catch (Throwable ex) {
|
|
return ex;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void onPostExecute(Throwable ex) {
|
|
if (running)
|
|
if (ex == null) {
|
|
ServiceSinkhole.reload("forwarding", ActivityForwarding.this, false);
|
|
adapter = new AdapterForwarding(ActivityForwarding.this,
|
|
DatabaseHelper.getInstance(ActivityForwarding.this).getForwarding());
|
|
lvForwarding.setAdapter(adapter);
|
|
} else
|
|
Toast.makeText(ActivityForwarding.this, ex.toString(), Toast.LENGTH_LONG).show();
|
|
}
|
|
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
} catch (Throwable ex) {
|
|
Toast.makeText(ActivityForwarding.this, ex.toString(), Toast.LENGTH_LONG).show();
|
|
}
|
|
}
|
|
})
|
|
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
|
|
@Override
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
task.cancel(false);
|
|
dialog.dismiss();
|
|
}
|
|
})
|
|
.setOnDismissListener(new DialogInterface.OnDismissListener() {
|
|
@Override
|
|
public void onDismiss(DialogInterface dialogInterface) {
|
|
dialog = null;
|
|
}
|
|
})
|
|
.create();
|
|
dialog.show();
|
|
return true;
|
|
default:
|
|
return super.onOptionsItemSelected(item);
|
|
}
|
|
}
|
|
}
|