Basic port forwarding UI

Fixes #292
This commit is contained in:
M66B 2016-02-09 10:53:52 +01:00
parent a5ace98900
commit 27cc16eb2e
27 changed files with 591 additions and 56 deletions

View File

@ -76,6 +76,7 @@
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/jni/netguard" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/renderscript" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
@ -94,12 +95,14 @@
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/recyclerview-v7/23.1.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/23.1.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-support" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/objectFiles" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard-rules" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/restart-dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />

View File

@ -53,7 +53,7 @@ model {
}
}
android.lintOptions {
abortOnError false
abortOnError false
}
}

View File

@ -76,7 +76,17 @@
</activity>
<activity
android:name=".ActivityForward"
android:name=".ActivityForwarding"
android:configChanges="orientation|screenSize"
android:label="@string/setting_forwarding"
android:parentActivityName=".ActivitySettings">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".ActivitySettings" />
</activity>
<activity
android:name=".ActivityForwardApproval"
android:configChanges="orientation|screenSize"
android:label="@string/app_name"
android:theme="@style/AppDialog">

View File

@ -28,7 +28,7 @@ import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class ActivityForward extends Activity {
public class ActivityForwardApproval extends Activity {
private static final String TAG = "NetGuard.Forward";
private static final String ACTION_START_PORT_FORWARD = "eu.faircode.netguard.START_PORT_FORWARD";
private static final String ACTION_STOP_PORT_FORWARD = "eu.faircode.netguard.STOP_PORT_FORWARD";
@ -40,7 +40,7 @@ public class ActivityForward extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.forward);
setContentView(R.layout.forwardapproval);
final int protocol = getIntent().getIntExtra("protocol", 0);
final int dport = getIntent().getIntExtra("dport", 0);
@ -74,7 +74,7 @@ public class ActivityForward extends Activity {
if (ACTION_START_PORT_FORWARD.equals(getIntent().getAction())) {
/*
am start -a eu.faircode.netguard.START_PORT_FORWARD \
-n eu.faircode.netguard/eu.faircode.netguard.ActivityForward \
-n eu.faircode.netguard/eu.faircode.netguard.ActivityForwardApproval \
--ei protocol 17 \
--ei dport 53 \
--es raddr 8.8.4.4 \
@ -83,7 +83,7 @@ am start -a eu.faircode.netguard.START_PORT_FORWARD \
--user 0
*/
Log.i(TAG, "Start forwarding protocol " + protocol + " port " + dport + " to " + raddr + ":" + rport + " uid " + ruid);
DatabaseHelper dh = new DatabaseHelper(ActivityForward.this);
DatabaseHelper dh = new DatabaseHelper(ActivityForwardApproval.this);
dh.deleteForward(protocol, dport);
dh.addForward(protocol, dport, raddr, rport, ruid);
dh.close();
@ -91,18 +91,18 @@ am start -a eu.faircode.netguard.START_PORT_FORWARD \
} else if (ACTION_STOP_PORT_FORWARD.equals(getIntent().getAction())) {
/*
am start -a eu.faircode.netguard.STOP_PORT_FORWARD \
-n eu.faircode.netguard/eu.faircode.netguard.ActivityForward \
-n eu.faircode.netguard/eu.faircode.netguard.ActivityForwardApproval \
--ei protocol 17 \
--ei dport 53 \
--user 0
*/
Log.i(TAG, "Stop forwarding protocol " + protocol + " port " + dport);
new DatabaseHelper(ActivityForward.this)
new DatabaseHelper(ActivityForwardApproval.this)
.deleteForward(protocol, dport)
.close();
}
SinkholeService.reload(null, "port forwarding", ActivityForward.this);
SinkholeService.reload(null, "forwarding", ActivityForwardApproval.this);
finish();
}

View File

@ -0,0 +1,189 @@
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-2016 by Marcel Bokhorst (M66B)
*/
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
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.EditText;
import android.widget.ListView;
import android.widget.PopupMenu;
import android.widget.Toast;
import java.net.InetAddress;
public class ActivityForwarding extends AppCompatActivity {
private boolean running;
private DatabaseHelper dh;
private ListView lvForwarding;
private ForwardingAdapter adapter;
private AlertDialog dialog = null;
@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);
dh = new DatabaseHelper(this);
lvForwarding = (ListView) findViewById(R.id.lvForwarding);
adapter = new ForwardingAdapter(this, dh.getForwarding());
lvForwarding.setAdapter(adapter);
lvForwarding.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
PackageManager pm = getPackageManager();
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(dport + " > " + raddr + "/" + rport);
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
if (menuItem.getItemId() == R.id.menu_delete) {
dh.deleteForward(protocol, dport);
SinkholeService.reload(null, "forwarding", ActivityForwarding.this);
adapter = new ForwardingAdapter(ActivityForwarding.this, dh.getForwarding());
lvForwarding.setAdapter(adapter);
}
return false;
}
});
popup.show();
}
});
}
@Override
protected void onDestroy() {
dh.close();
running = false;
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);
final EditText etProtocol = (EditText) view.findViewById(R.id.etProtocol);
final EditText etDPort = (EditText) view.findViewById(R.id.etDPort);
final EditText etRAddr = (EditText) view.findViewById(R.id.etRAddr);
final EditText etRPort = (EditText) view.findViewById(R.id.etRPort);
final EditText etRUid = (EditText) view.findViewById(R.id.etRUid);
etRAddr.setText("127.0.0.1");
dialog = new AlertDialog.Builder(this)
.setView(view)
.setCancelable(false)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
try {
final int protocol = Integer.parseInt(etProtocol.getText().toString());
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 = Integer.parseInt(etRUid.getText().toString());
new AsyncTask<Object, Object, Throwable>() {
@Override
protected Throwable doInBackground(Object... objects) {
try {
InetAddress.getByName(raddr);
dh.addForward(protocol, dport, raddr, rport, ruid);
return null;
} catch (Throwable ex) {
return ex;
}
}
@Override
protected void onPostExecute(Throwable ex) {
if (running)
if (ex == null) {
SinkholeService.reload(null, "forwarding", ActivityForwarding.this);
adapter = new ForwardingAdapter(ActivityForwarding.this, dh.getForwarding());
lvForwarding.setAdapter(adapter);
} else
Toast.makeText(ActivityForwarding.this, ex.toString(), Toast.LENGTH_LONG).show();
}
}.execute();
} 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) {
dialog.dismiss();
}
})
.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialogInterface) {
dialog = null;
}
})
.create();
dialog.show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}

View File

@ -88,7 +88,7 @@ public class ActivityLog extends AppCompatActivity implements SharedPreferences.
protected void onCreate(Bundle savedInstanceState) {
Util.setTheme(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.logview);
setContentView(R.layout.logging);
running = true;
// Action bar

View File

@ -167,6 +167,16 @@ public class ActivitySettings extends AppCompatActivity implements SharedPrefere
options.removePreference(screen.findPreference("filter"));
}
// Handle port forwarding
Preference pref_forwarding = screen.findPreference("forwarding");
pref_forwarding.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
startActivity(new Intent(ActivitySettings.this, ActivityForwarding.class));
return true;
}
});
// VPN parameters
screen.findPreference("vpn4").setTitle(getString(R.string.setting_vpn4, prefs.getString("vpn4", "10.1.10.1")));
screen.findPreference("vpn6").setTitle(getString(R.string.setting_vpn6, prefs.getString("vpn6", "fd00:1:fd00:1:fd00:1:fd00:1")));

View File

@ -577,9 +577,12 @@ public class DatabaseHelper extends SQLiteOpenHelper {
return this;
}
public Cursor getForward() {
public Cursor getForwarding() {
SQLiteDatabase db = this.getReadableDatabase();
return db.query("forward", null, null, null, null, null, null);
String query = "SELECT ID AS _id, *";
query += " FROM forward";
query += " ORDER BY dport";
return db.rawQuery(query, new String[]{});
}
public void addLogChangedListener(LogChangedListener listener) {

View File

@ -0,0 +1,95 @@
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-2016 by Marcel Bokhorst (M66B)
*/
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.preference.PreferenceManager;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.text.TextUtils;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
public class ForwardingAdapter extends CursorAdapter {
private static String TAG = "NetGuard.Forward";
private boolean resolve;
private int colProtocol;
private int colDPort;
private int colRAddr;
private int colRPort;
private int colRUid;
public ForwardingAdapter(Context context, Cursor cursor) {
super(context, cursor, 0);
colProtocol = cursor.getColumnIndex("protocol");
colDPort = cursor.getColumnIndex("dport");
colRAddr = cursor.getColumnIndex("raddr");
colRPort = cursor.getColumnIndex("rport");
colRUid = cursor.getColumnIndex("ruid");
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.forward, parent, false);
}
@Override
public void bindView(final View view, final Context context, final Cursor cursor) {
// Get values
int protocol = cursor.getInt(colProtocol);
int dport = cursor.getInt(colDPort);
String raddr = cursor.getString(colRAddr);
int rport = cursor.getInt(colRPort);
int ruid = cursor.getInt(colRUid);
// Get views
TextView tvProtocol = (TextView) view.findViewById(R.id.tvProtocol);
TextView tvDPort = (TextView) view.findViewById(R.id.tvDPort);
TextView tvRAddr = (TextView) view.findViewById(R.id.tvRAddr);
TextView tvRPort = (TextView) view.findViewById(R.id.tvRPort);
TextView tvRUid = (TextView) view.findViewById(R.id.tvRUid);
tvProtocol.setText(Util.getProtocolName(protocol, 0, false));
tvDPort.setText(Integer.toString(dport));
tvRAddr.setText(raddr);
tvRPort.setText(Integer.toString(rport));
tvRUid.setText(TextUtils.join(", ", Util.getApplicationNames(ruid, context)));
}
}

View File

@ -1002,7 +1002,7 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
DatabaseHelper dh = new DatabaseHelper(SinkholeService.this);
Cursor cursor = dh.getForward();
Cursor cursor = dh.getForwarding();
int colProtocol = cursor.getColumnIndex("protocol");
int colDPort = cursor.getColumnIndex("dport");
int colRAddr = cursor.getColumnIndex("raddr");

View File

@ -339,7 +339,9 @@ public class Util {
else {
PackageManager pm = context.getPackageManager();
String[] pkgs = pm.getPackagesForUid(uid);
if (pkgs != null)
if (pkgs == null)
listResult.add(Integer.toString(uid));
else
for (String pkg : pkgs)
try {
ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
@ -421,7 +423,7 @@ public class Util {
}
if (p == null)
return Integer.toString(protocol) + "/" + version;
return (brief ? p.substring(0, 1) + version : p + version);
return ((brief ? p.substring(0, 1) : p) + (version > 0 ? version : ""));
}
public interface DoubtListener {

Binary file not shown.

After

Width:  |  Height:  |  Size: 487 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 947 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1,60 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
android:paddingEnd="8dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingStart="8dp"
tools:context=".ActivityForwarding">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
<TextView
android:id="@+id/tvProtocol"
android:layout_width="32dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@mipmap/ic_launcher" />
android:textAppearance="@style/TextSmall" />
<TextView
android:layout_width="wrap_content"
android:id="@+id/tvDPort"
android:layout_width="48dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:text="@string/app_name"
android:textAppearance="@style/TextLarge"
android:textStyle="bold" />
android:layout_gravity="end"
android:layout_marginLeft="4dp"
android:layout_marginStart="4dp"
android:textAlignment="textEnd"
android:textAppearance="@style/TextSmall" />
<TextView
android:id="@+id/tvRAddr"
android:layout_width="160dp"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_marginStart="4dp"
android:textAppearance="@style/TextSmall" />
<TextView
android:id="@+id/tvRPort"
android:layout_width="48dp"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginLeft="4dp"
android:layout_marginStart="4dp"
android:textAlignment="textEnd"
android:textAppearance="@style/TextSmall" />
</LinearLayout>
<TextView
android:id="@+id/tvForward"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:textAppearance="@style/TextMedium"
android:textStyle="bold" />
<RelativeLayout
android:id="@+id/tvRUid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="32dp">
<Button
android:id="@+id/btnOk"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:text="@android:string/ok" />
<Button
android:id="@+id/btnCancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:text="@android:string/cancel" />
</RelativeLayout>
</LinearLayout>
android:layout_marginLeft="88dp"
android:layout_marginStart="88dp"
android:textAppearance="@style/TextSmall" />
</LinearLayout>

View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp"
tools:context=".ActivityForwarding">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@mipmap/ic_launcher" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:text="@string/app_name"
android:textAppearance="@style/TextLarge"
android:textStyle="bold" />
</LinearLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title_protocol"
android:textAppearance="@style/TextMedium" />
<EditText
android:id="@+id/etProtocol"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:textAppearance="@style/TextMedium" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title_dport"
android:textAppearance="@style/TextMedium" />
<EditText
android:id="@+id/etDPort"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:textAppearance="@style/TextMedium" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title_raddr"
android:textAppearance="@style/TextMedium" />
<EditText
android:id="@+id/etRAddr"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@style/TextMedium" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title_rport"
android:textAppearance="@style/TextMedium" />
<EditText
android:id="@+id/etRPort"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:textAppearance="@style/TextMedium" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title_ruid"
android:textAppearance="@style/TextMedium" />
<EditText
android:id="@+id/etRUid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:textAppearance="@style/TextMedium" />
</LinearLayout>
</ScrollView>
</LinearLayout>

View File

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@mipmap/ic_launcher" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:text="@string/app_name"
android:textAppearance="@style/TextLarge"
android:textStyle="bold" />
</LinearLayout>
<TextView
android:id="@+id/tvForward"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:textAppearance="@style/TextMedium"
android:textStyle="bold" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="32dp">
<Button
android:id="@+id/btnOk"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:text="@android:string/ok" />
<Button
android:id="@+id/btnCancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:text="@android:string/cancel" />
</RelativeLayout>
</LinearLayout>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingEnd="@dimen/activity_horizontal_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingStart="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<ListView
android:id="@+id/lvForwarding"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbarStyle="insideOverlay"
android:scrollbars="vertical" />
</RelativeLayout>

View File

@ -7,7 +7,6 @@
android:padding="16dp"
tools:context=".ActivityPro">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/menu_port"
android:enabled="false"
android:title="" />
<item
android:id="@+id/menu_delete"
android:title="@string/menu_delete" />
</menu>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:netguard="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_add"
android:icon="@drawable/ic_add_circle_outline_white_24dp"
android:title="@string/menu_add"
netguard:showAsAction="always|collapseActionView" />
</menu>

View File

@ -35,6 +35,15 @@ however it is impossible to guarantee NetGuard will work correctly on every devi
<string name="menu_clear">Clear</string>
<string name="menu_reset">Reset</string>
<string name="menu_add">Add</string>
<string name="menu_delete">Delete</string>
<string name="title_protocol">Protocol</string>
<string name="title_dport">Source port</string>
<string name="title_raddr">Destination address</string>
<string name="title_rport">Destination port</string>
<string name="title_ruid">Destination application</string>
<string name="setting_defaults">Defaults</string>
<string name="setting_whitelist_wifi">Block Wi-Fi</string>
<string name="setting_whitelist_other">Block mobile</string>
@ -64,6 +73,7 @@ however it is impossible to guarantee NetGuard will work correctly on every devi
<string name="setting_filter">Filter traffic</string>
<string name="setting_resolved">Store resolved domain names</string>
<string name="setting_block_domains">Block domain names</string>
<string name="setting_forwarding">Port forwarding</string>
<string name="setting_vpn4">VPN IPv4: %s</string>
<string name="setting_vpn6">VPN IPv6: %s</string>
<string name="setting_dns">VPN DNS: %s</string>

View File

@ -124,6 +124,10 @@
android:key="use_hosts"
android:summary="@string/summary_block_domains"
android:title="@string/setting_block_domains" />
<Preference
android:dependency="filter"
android:key="forwarding"
android:title="@string/setting_forwarding" />
<EditTextPreference
inputType="phone"
android:hint="10.1.10.1"

View File

@ -124,6 +124,10 @@
android:key="use_hosts"
android:summary="@string/summary_block_domains"
android:title="@string/setting_block_domains" />
<Preference
android:dependency="filter"
android:key="forwarding"
android:title="@string/setting_forwarding" />
<EditTextPreference
inputType="phone"
android:hint="10.1.10.1"